towerops/test/towerops_web/live/coverage_live/show_test.exs
2026-06-14 08:27:57 -05:00

183 lines
6.5 KiB
Elixir

defmodule ToweropsWeb.CoverageLive.ShowTest do
use ToweropsWeb.ConnCase
import Phoenix.LiveViewTest
import Towerops.CoveragesFixtures
import Towerops.OrganizationsFixtures
alias Towerops.Coverages
alias ToweropsWeb.CoverageLive.Show
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 "renders coverage details for a draft coverage", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id, %{name: "Hilltop Sector"})
{:ok, _view, html} = live(conn, ~p"/coverage/#{cov.id}")
assert html =~ "Hilltop Sector"
assert html =~ "No heatmap available yet"
end
test "renders the parameters drawer when coverage is ready", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id, %{name: "ReadyOne"})
{: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/#{cov.id}")
assert html =~ "Parameters"
end
test "shows queued banner for queued coverage", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
{:ok, queued} = Coverages.mark_status(cov, "queued", %{})
{:ok, _view, html} = live(conn, ~p"/coverage/#{queued.id}")
assert html =~ "queued"
end
test "shows failed banner with error message", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
{:ok, failed} = Coverages.mark_status(cov, "failed", %{error_message: "test failure"})
{:ok, _view, html} = live(conn, ~p"/coverage/#{failed.id}")
assert html =~ "test failure"
end
test "404 for unknown coverage", %{conn: conn} do
assert_raise Ecto.NoResultsError, fn ->
live(conn, ~p"/coverage/#{Ecto.UUID.generate()}")
end
end
test "requires authentication" do
conn = build_conn()
assert {:error, {:redirect, %{to: path}}} = live(conn, ~p"/coverage/#{Ecto.UUID.generate()}")
assert path =~ "/users/log-in"
end
end
describe "events" do
test "toggle_params hides and re-shows the parameters drawer", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
{:ok, view, html} = live(conn, ~p"/coverage/#{cov.id}")
assert html =~ "Hide details"
html = render_click(view, "toggle_params", %{})
assert html =~ "Details"
refute html =~ "Hide details"
end
test "set_probe_units switches between ft and m", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
{:ok, view, _html} = live(conn, ~p"/coverage/#{cov.id}")
assert render_click(view, "set_probe_units", %{"units" => "m"})
assert render_click(view, "set_probe_units", %{"units" => "ft"})
end
test "delete removes the coverage and redirects", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id, %{name: "DoomedCoverage"})
{:ok, view, _html} = live(conn, ~p"/coverage/#{cov.id}")
result = render_click(view, "delete", %{})
assert {:error, {:live_redirect, %{to: "/coverage"}}} = result
assert nil == Coverages.get_coverage(org.id, cov.id)
end
test "recompute queues compute and refreshes status", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
{:ok, view, _html} = live(conn, ~p"/coverage/#{cov.id}")
html = render_click(view, "recompute", %{})
assert html =~ "queued"
end
test "probe_point handler stores point in assigns", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
{:ok, view, _html} = live(conn, ~p"/coverage/#{cov.id}")
assert render_hook(view, "probe_point", %{"lat" => "30.27", "lon" => "-97.74"})
end
test "close_probe clears the active probe", %{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
{:ok, view, _html} = live(conn, ~p"/coverage/#{cov.id}")
_ = render_hook(view, "probe_point", %{"lat" => "30.27", "lon" => "-97.74"})
assert render_click(view, "close_probe", %{})
end
end
describe "coverage_lat / coverage_lon helpers" do
test "coverage_lat returns the coverage's latitude when present", %{org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
valid? = is_number(Show.coverage_lat(cov)) or Show.coverage_lat(cov) == nil
assert valid?
end
test "coverage_lon returns the coverage's longitude when present", %{org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
valid? = is_number(Show.coverage_lon(cov)) or Show.coverage_lon(cov) == nil
assert valid?
end
end
describe "format helpers" do
test "format_ft converts metres to feet" do
assert Show.format_ft(30.0) == "98 ft"
assert Show.format_ft(nil) == ""
end
test "format_mi converts metres to miles" do
assert Show.format_mi(1609.344) == "1.0 mi"
assert Show.format_mi(nil) == ""
end
test "format_ghz converts MHz to GHz" do
assert Show.format_ghz(5800) == "5.8 GHz"
assert Show.format_ghz(nil) == ""
end
test "status_badge_class maps known statuses" do
assert Show.status_badge_class("ready") =~ "bg-green"
assert Show.status_badge_class("failed") =~ "bg-red"
assert Show.status_badge_class("computing") =~ "bg-yellow"
assert Show.status_badge_class("queued") =~ "bg-blue"
assert Show.status_badge_class("draft") =~ "bg-gray"
assert Show.status_badge_class("anything-else") =~ "bg-gray"
end
end
describe "handle_info :coverage_status" do
test "coverage_status update reloads the coverage and pushes list-changed",
%{conn: conn, org: org, site: site} do
cov = coverage_fixture(org.id, site.id)
{:ok, view, _html} = live(conn, ~p"/coverage/#{cov.id}")
send(view.pid, {:coverage_status, "ready", %{}})
# Force a render to ensure the handler ran
html = render(view)
assert html =~ cov.name
end
end
end