166 lines
5.5 KiB
Elixir
166 lines
5.5 KiB
Elixir
defmodule ToweropsWeb.CoverageLive.MapTest do
|
|
use ToweropsWeb.ConnCase
|
|
|
|
import Phoenix.LiveViewTest
|
|
import Towerops.CoveragesFixtures
|
|
import Towerops.OrganizationsFixtures
|
|
|
|
alias Towerops.Coverages
|
|
|
|
setup :register_and_log_in_user
|
|
|
|
setup %{conn: conn, user: user} do
|
|
org = organization_fixture(user.id)
|
|
site = site_fixture(org.id, %{latitude: 30.27, longitude: -97.74})
|
|
conn = Plug.Conn.put_session(conn, :current_organization_id, org.id)
|
|
|
|
%{conn: conn, org: org, site: site}
|
|
end
|
|
|
|
describe "mount" do
|
|
test "shows empty state when no ready coverages exist", %{conn: conn} do
|
|
{:ok, _view, html} = live(conn, ~p"/coverage")
|
|
assert html =~ "No ready coverages"
|
|
end
|
|
|
|
test "shows ready coverages in tower toggle list", %{conn: conn, org: org, site: site} do
|
|
cov = coverage_fixture(org.id, site.id, %{name: "Mt Wilson"})
|
|
|
|
{:ok, ready} =
|
|
Coverages.mark_status(cov, "ready", %{
|
|
png_path: "/coverage/#{org.id}/#{cov.id}/rssi.png",
|
|
raster_path: "/coverage/#{org.id}/#{cov.id}/rssi.tif",
|
|
bbox_min_lat: 30.0,
|
|
bbox_min_lon: -98.0,
|
|
bbox_max_lat: 30.5,
|
|
bbox_max_lon: -97.5
|
|
})
|
|
|
|
{:ok, _view, html} = live(conn, ~p"/coverage")
|
|
assert html =~ ready.name
|
|
end
|
|
|
|
test "requires authentication" do
|
|
conn = build_conn()
|
|
assert {:error, {:redirect, %{to: path}}} = live(conn, ~p"/coverage")
|
|
assert path =~ "/users/log-in"
|
|
end
|
|
end
|
|
|
|
describe "tower toggle events" do
|
|
setup %{org: org, site: site} do
|
|
cov = coverage_fixture(org.id, site.id, %{name: "TowerA"})
|
|
|
|
{:ok, ready} =
|
|
Coverages.mark_status(cov, "ready", %{
|
|
png_path: "/coverage/#{org.id}/#{cov.id}/rssi.png",
|
|
raster_path: "/coverage/#{org.id}/#{cov.id}/rssi.tif",
|
|
bbox_min_lat: 30.0,
|
|
bbox_min_lon: -98.0,
|
|
bbox_max_lat: 30.5,
|
|
bbox_max_lon: -97.5
|
|
})
|
|
|
|
%{coverage: ready}
|
|
end
|
|
|
|
test "toggle_coverage flips one tower on/off", %{conn: conn, coverage: cov} do
|
|
{:ok, view, _html} = live(conn, ~p"/coverage")
|
|
|
|
# First click: disable
|
|
render_click(view, "toggle_coverage", %{"id" => cov.id})
|
|
# Second click: re-enable
|
|
assert render_click(view, "toggle_coverage", %{"id" => cov.id})
|
|
end
|
|
|
|
test "show_all and hide_all bulk toggle", %{conn: conn} do
|
|
{:ok, view, _html} = live(conn, ~p"/coverage")
|
|
|
|
assert render_click(view, "hide_all", %{})
|
|
assert render_click(view, "show_all", %{})
|
|
end
|
|
|
|
test "set_probe_units switches between ft and m", %{conn: conn} do
|
|
{:ok, view, _html} = live(conn, ~p"/coverage")
|
|
assert render_click(view, "set_probe_units", %{"units" => "m"})
|
|
assert render_click(view, "set_probe_units", %{"units" => "ft"})
|
|
end
|
|
|
|
test "close_probe is a no-op when no probe is open", %{conn: conn} do
|
|
{:ok, view, _html} = live(conn, ~p"/coverage")
|
|
assert render_click(view, "close_probe", %{})
|
|
end
|
|
|
|
test "probe_point queries coverages at the lat/lon and assigns the result", %{conn: conn, coverage: cov} do
|
|
{:ok, view, _html} = live(conn, ~p"/coverage")
|
|
|
|
# Send a probe_point inside the coverage's bbox. The handler queries the
|
|
# context and assigns probe data. We don't depend on the actual RSSI
|
|
# query (which would need gdal); we just exercise the event branch.
|
|
lat = "30.25"
|
|
lon = "-97.75"
|
|
_ = render_click(view, "probe_point", %{"lat" => lat, "lon" => lon})
|
|
|
|
# Force re-render so we observe the assigns change.
|
|
html = render(view)
|
|
# Either rows render with the coverage's name or the probe-summary block
|
|
# is present — both prove the handler ran.
|
|
assert html =~ cov.name or html =~ "30.25" or html =~ "Probe"
|
|
end
|
|
end
|
|
|
|
describe "format helpers" do
|
|
alias ToweropsWeb.CoverageLive.Map, as: M
|
|
|
|
test "fmt_distance converts to mi or km" do
|
|
assert M.fmt_distance(1609.344, "ft") == "1.00 mi"
|
|
assert M.fmt_distance(1000, "m") == "1.00 km"
|
|
assert M.fmt_distance(nil, "ft") == "—"
|
|
end
|
|
|
|
test "fmt_rssi formats values" do
|
|
assert M.fmt_rssi(:no_coverage) == "N/A"
|
|
assert M.fmt_rssi(nil) == "—"
|
|
assert M.fmt_rssi(-65.0) =~ "dBm"
|
|
end
|
|
|
|
test "coverages_payload shapes records for the JS hook" do
|
|
payload = M.coverages_payload([])
|
|
assert payload == []
|
|
end
|
|
end
|
|
|
|
describe "probe_point with non-numeric inputs" do
|
|
test "probe_point with malformed lat/lon strings clamps to 0.0", %{conn: conn} do
|
|
{:ok, view, _html} = live(conn, ~p"/coverage")
|
|
|
|
# Should hit the to_float :error branch
|
|
assert render_click(view, "probe_point", %{"lat" => "foo", "lon" => "bar"})
|
|
end
|
|
end
|
|
|
|
describe "coverage_status PubSub broadcast" do
|
|
test "rebuilds coverage list and pushes event on broadcast", %{conn: conn, org: org, site: site} do
|
|
cov = coverage_fixture(org.id, site.id, %{name: "PubSubCov"})
|
|
|
|
{:ok, _ready} =
|
|
Coverages.mark_status(cov, "ready", %{
|
|
png_path: "/coverage/#{org.id}/#{cov.id}/rssi.png",
|
|
raster_path: "/coverage/#{org.id}/#{cov.id}/rssi.tif",
|
|
bbox_min_lat: 30.0,
|
|
bbox_min_lon: -98.0,
|
|
bbox_max_lat: 30.5,
|
|
bbox_max_lon: -97.5
|
|
})
|
|
|
|
{:ok, view, _html} = live(conn, ~p"/coverage")
|
|
|
|
# Send the broadcast manually
|
|
send(view.pid, {:coverage_status, "ready", cov.id})
|
|
|
|
# Force re-render — handle_info ran
|
|
html = render(view)
|
|
assert html =~ "PubSubCov"
|
|
end
|
|
end
|
|
end
|