towerops/test/towerops_web/live/trace_live/index_test.exs
Graham McIntire c50dc08ad4 test: fix slow + flaky tests (Mox global, env pollution, pool starvation)
- Remove Mox.set_mox_global() in DPW extra test; rely on $callers
  instead so concurrent vendor SNMP tests stop intermittently failing
  with VerificationError.
- Make ToweropsWeb.Plugs.GraphQLIntrospectionTest async: false. It
  mutates Application.put_env(:towerops, :env, :prod), which polluted
  every async vendor test that reads :env via
  Towerops.Snmp.Client.phoenix_snmp_disabled/0.
- Bump test pool queue_target/queue_interval. AgentChannelTest spawns
  many `:proc_lib` channel processes that hold sandbox connections;
  the default 50ms queue caused intermittent
  'could not checkout the connection' errors.
- Tag real-System.cmd("ping") tests as :network so they're excluded
  by default. Saves ~20s on every full run.
- Make JobCleanupTask's internal 1s settle sleep configurable via
  :job_cleanup_settle_ms; the test overrides it to 0.

Plus the pending CoverageLive.Form edit-save / EIRP recompute and
TraceLive deep-link tests from before the compact.
2026-05-08 14:43:30 -05:00

145 lines
5.4 KiB
Elixir

defmodule ToweropsWeb.TraceLive.IndexTest do
use ToweropsWeb.ConnCase, async: true
import Phoenix.LiveViewTest
setup :register_and_log_in_user
setup %{user: user} do
{:ok, organization} =
Towerops.Organizations.create_organization(%{name: "Trace Org"}, user.id)
%{organization: organization}
end
describe "mount + events" do
test "renders the empty trace page", %{conn: conn} do
assert {:ok, _view, html} = live(conn, ~p"/trace")
assert html =~ "Trace" or html =~ "Search"
end
test "search with empty query keeps results empty", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/trace")
_ = render_hook(view, "search", %{"query" => ""})
assert true
end
test "search with a non-matching query returns []", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/trace")
_ = render_hook(view, "search", %{"query" => "absolutely-nothing-matches-this"})
assert true
end
test "select_result patches the URL with type+id params", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/trace")
id = Ecto.UUID.generate()
_ = render_hook(view, "select_result", %{"type" => "device", "id" => id})
assert true
end
test "clear resets state and patches back to /trace", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/trace?type=device&id=#{Ecto.UUID.generate()}")
_ = render_hook(view, "clear", %{})
assert true
end
end
describe "format helpers" do
alias ToweropsWeb.TraceLive.Index
test "type_badge_class covers known and unknown types" do
assert Index.type_badge_class(:account) == "badge-primary"
assert Index.type_badge_class(:inventory_item) == "badge-secondary"
assert Index.type_badge_class(:site) == "badge-warning"
assert Index.type_badge_class(:device) == "badge-accent"
assert Index.type_badge_class(:access_point) == "badge-info"
assert Index.type_badge_class(:totally_unknown) == "badge-ghost"
end
test "type_badge_label covers known and unknown" do
assert Index.type_badge_label(:account) == "Account"
assert Index.type_badge_label(:device) == "Device"
assert Index.type_badge_label(:other) == "Unknown"
end
test "status_badge_class covers all branches" do
assert Index.status_badge_class("active") == "badge-success"
assert Index.status_badge_class("suspended") == "badge-warning"
assert Index.status_badge_class("cancelled") == "badge-error"
assert Index.status_badge_class("frob") == "badge-ghost"
end
test "device_status_color covers all branches" do
assert Index.device_status_color(:up) =~ "green"
assert Index.device_status_color(:down) =~ "red"
assert Index.device_status_color(:other) =~ "gray"
end
test "format_speed covers all branches" do
assert Index.format_speed(nil) == ""
assert Index.format_speed(2500) == "2.5 Gbps"
assert Index.format_speed(100) == "100 Mbps"
assert Index.format_speed("???") == "???"
end
test "format_relative_time covers all branches" do
assert Index.format_relative_time(nil) == ""
assert Index.format_relative_time(DateTime.utc_now()) == "just now"
assert Index.format_relative_time(DateTime.add(DateTime.utc_now(), -120, :second)) =~ "m ago"
assert Index.format_relative_time(DateTime.add(DateTime.utc_now(), -7200, :second)) =~
"h ago"
assert Index.format_relative_time(DateTime.add(DateTime.utc_now(), -200_000, :second)) =~
"d ago"
end
test "format_score, format_pct, format_ms cover branches" do
assert Index.format_score(nil) == ""
assert Index.format_score(0.5) == "0.5"
assert Index.format_score("x") == "x"
assert Index.format_pct(nil) == ""
assert Index.format_pct(50.5) == "50.5%"
assert Index.format_pct("x") == "x"
assert Index.format_ms(nil) == ""
assert Index.format_ms(123) == "123.0 ms"
assert Index.format_ms("x") == "x"
end
end
describe "deep-link with trace data renders issues_callout" do
test "trace_type=device with a real device renders the trace shell",
%{conn: conn, organization: organization} do
{:ok, site} = Towerops.Sites.create_site(%{name: "Trace Test Site", organization_id: organization.id})
{:ok, device} =
Towerops.Devices.create_device(%{
name: "Trace Dev",
ip_address: "10.10.10.1",
site_id: site.id,
organization_id: organization.id
})
{:ok, _view, html} = live(conn, ~p"/trace?type=device&id=#{device.id}")
# Either renders the trace card or the empty state. Both exercise
# handle_params with type+id which calls Trace.assemble_trace/3.
assert html =~ "Trace" or html =~ device.name
end
test "trace_type=site with a real site renders the trace shell",
%{conn: conn, organization: organization} do
{:ok, site} = Towerops.Sites.create_site(%{name: "Trace Site", organization_id: organization.id})
{:ok, _view, html} = live(conn, ~p"/trace?type=site&id=#{site.id}")
assert html =~ "Trace" or html =~ site.name
end
test "trace_type=account with an unknown id still renders without crash",
%{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/trace?type=account&id=#{Ecto.UUID.generate()}")
assert html =~ "Trace"
end
end
end