161 lines
6 KiB
Elixir
161 lines
6 KiB
Elixir
defmodule ToweropsWeb.TraceLive.IndexTest do
|
|
use ToweropsWeb.ConnCase, async: true
|
|
|
|
import Phoenix.LiveViewTest
|
|
|
|
alias ToweropsWeb.TraceLive.Index
|
|
|
|
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 =~ ~r/Trace|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 Process.alive?(view.pid)
|
|
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 Process.alive?(view.pid)
|
|
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 Process.alive?(view.pid)
|
|
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 Process.alive?(view.pid)
|
|
end
|
|
end
|
|
|
|
describe "format helpers" do
|
|
test "type_badge_class covers known and unknown types" do
|
|
assert Index.type_badge_class(:account) ==
|
|
"bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400"
|
|
|
|
assert Index.type_badge_class(:inventory_item) ==
|
|
"bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-400"
|
|
|
|
assert Index.type_badge_class(:site) ==
|
|
"bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400"
|
|
|
|
assert Index.type_badge_class(:device) ==
|
|
"bg-cyan-100 text-cyan-800 dark:bg-cyan-900/30 dark:text-cyan-400"
|
|
|
|
assert Index.type_badge_class(:access_point) ==
|
|
"bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400"
|
|
|
|
assert Index.type_badge_class(:totally_unknown) == "text-gray-700 dark:text-gray-300"
|
|
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") ==
|
|
"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400"
|
|
|
|
assert Index.status_badge_class("suspended") ==
|
|
"bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400"
|
|
|
|
assert Index.status_badge_class("cancelled") ==
|
|
"bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400"
|
|
|
|
assert Index.status_badge_class("frob") == "text-gray-700 dark:text-gray-300"
|
|
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 =~ ~r/Trace|#{Regex.escape(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 =~ ~r/Trace|#{Regex.escape(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
|