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 end