towerops/test/towerops_web/live/trace_live/index_helpers_test.exs
Graham McIntire 3ca0834ef0 tests: raise coverage to 70% via helper promotion + new unit/property tests
Promoted pure presentation and utility helpers from `defp` to `def @doc false`
across ~20 LiveViews, Oban workers, and sync modules so they're reachable from
unit tests. Refactored several `cond` blocks into idiomatic function heads with
guards. Added ~250 new test cases in new files under test/towerops and
test/towerops_web, including DB-backed tests for CnMaestro.Sync and
AlertNotificationWorker, and removed dead LiveView tab components and
CapacityLive (no callers anywhere in lib/test).

Configured mix.exs test_coverage.ignore_modules to exclude vendored third-party
code (SnmpKit, protobuf-generated Towerops.Agent.*, Absinthe GraphQL types,
Phoenix HTML modules, Inspect protocol impls) from coverage calculations —
these are not our project code.

Coverage: 66.93% → 70.09%. Full suite: 10,127 tests, 0 failures.
2026-04-24 09:49:06 -05:00

225 lines
6.8 KiB
Elixir

defmodule ToweropsWeb.TraceLive.IndexHelpersTest do
use ExUnit.Case, async: true
alias ToweropsWeb.TraceLive.Index
describe "type_badge_class/1 + type_badge_label/1" do
test "known types" do
for {type, class, label} <- [
{:account, "badge-primary", "Account"},
{:inventory_item, "badge-secondary", "Inventory"},
{:site, "badge-warning", "Site"},
{:device, "badge-accent", "Device"},
{:access_point, "badge-info", "AP"}
] do
assert class == Index.type_badge_class(type)
assert label == Index.type_badge_label(type)
end
end
test "unknown falls through to ghost/Unknown" do
assert "badge-ghost" == Index.type_badge_class(:other)
assert "Unknown" == Index.type_badge_label(:other)
end
end
describe "status_badge_class/1" do
test "active/suspended/cancelled" do
assert "badge-success" == Index.status_badge_class("active")
assert "badge-warning" == Index.status_badge_class("suspended")
assert "badge-error" == Index.status_badge_class("cancelled")
end
test "unknown is ghost" do
assert "badge-ghost" == Index.status_badge_class(nil)
assert "badge-ghost" == Index.status_badge_class("other")
end
end
describe "device_status_color/1 + device_status_dot/1" do
test "up/down/other" do
assert String.contains?(Index.device_status_color(:up), "green")
assert String.contains?(Index.device_status_color(:down), "red")
assert String.contains?(Index.device_status_color(nil), "gray")
assert "bg-green-500" == Index.device_status_dot(:up)
assert "bg-red-500" == Index.device_status_dot(:down)
assert "bg-gray-400" == Index.device_status_dot(:other)
end
end
describe "format_speed/1" do
test "nil" do
assert "" == Index.format_speed(nil)
end
test "< 1000 Mbps stays as Mbps" do
assert "500 Mbps" == Index.format_speed(500)
end
test ">= 1000 Mbps becomes Gbps" do
assert "1.5 Gbps" == Index.format_speed(1500)
end
test "non-numeric passes through" do
assert "" == Index.format_speed("")
end
end
describe "format_relative_time/1" do
test "nil returns em-dash" do
assert "" == Index.format_relative_time(nil)
end
test "returns relative string for past datetime" do
dt = DateTime.add(DateTime.utc_now(), -120, :second)
result = Index.format_relative_time(dt)
assert String.contains?(result, "m") or result == "just now"
end
end
describe "format_score/1 + format_pct/1 + format_ms/1" do
test "nil returns em-dash" do
assert "" == Index.format_score(nil)
assert "" == Index.format_pct(nil)
assert "" == Index.format_ms(nil)
end
test "numeric formatted with 1 decimal" do
assert "50.0" == Index.format_score(50)
assert "75.5%" == Index.format_pct(75.5)
assert "12.3 ms" == Index.format_ms(12.345)
end
end
describe "format_throughput/1" do
test "nil" do
assert "" == Index.format_throughput(nil)
end
test "< 1000 Mbps" do
assert "100.0 Mbps" == Index.format_throughput(100)
end
test ">= 1000 becomes Gbps" do
assert "1.5 Gbps" == Index.format_throughput(1500)
end
end
describe "format_alert_type/1" do
test "nil returns em-dash" do
assert "" == Index.format_alert_type(nil)
end
test "humanizes snake_case" do
assert "Device down" == Index.format_alert_type("device_down")
assert "Packet loss" == Index.format_alert_type("packet_loss")
end
test "non-binary stringified" do
assert "42" == Index.format_alert_type(42)
end
end
describe "score_quality/1 + score_color/1" do
test "nil is unknown/gray" do
assert :unknown == Index.score_quality(nil)
assert "text-gray-400" == Index.score_color(nil)
end
test ">= 80 is good/green" do
assert :good == Index.score_quality(90)
assert String.contains?(Index.score_color(90), "green")
end
test "50-80 is warning/yellow" do
assert :warning == Index.score_quality(60)
assert String.contains?(Index.score_color(60), "yellow")
end
test "< 50 is bad/red" do
assert :bad == Index.score_quality(30)
assert String.contains?(Index.score_color(30), "red")
end
end
describe "latency_color/1, jitter_color/1, loss_color/1" do
test "all return gray for nil" do
assert "text-gray-400" == Index.latency_color(nil)
assert "text-gray-400" == Index.jitter_color(nil)
assert "text-gray-400" == Index.loss_color(nil)
end
test "latency thresholds" do
assert String.contains?(Index.latency_color(10), "green")
assert String.contains?(Index.latency_color(50), "yellow")
assert String.contains?(Index.latency_color(200), "red")
end
test "jitter thresholds" do
assert String.contains?(Index.jitter_color(5), "green")
assert String.contains?(Index.jitter_color(20), "yellow")
assert String.contains?(Index.jitter_color(50), "red")
end
test "loss thresholds" do
assert String.contains?(Index.loss_color(0), "green")
assert String.contains?(Index.loss_color(3), "yellow")
assert String.contains?(Index.loss_color(10), "red")
end
end
describe "alert_dot/1" do
test "critical severity" do
assert "bg-red-500" == Index.alert_dot(%{severity: "critical"})
end
test "warning severity" do
assert "bg-yellow-500" == Index.alert_dot(%{severity: "warning"})
end
test "alert_type down" do
assert "bg-red-500" == Index.alert_dot(%{alert_type: "down"})
end
test "fallback" do
assert "bg-orange-400" == Index.alert_dot(%{})
end
end
describe "urgency_dot/1" do
test "maps known values" do
assert "bg-red-500" == Index.urgency_dot("critical")
assert "bg-orange-500" == Index.urgency_dot("high")
assert "bg-yellow-500" == Index.urgency_dot("medium")
assert "bg-blue-400" == Index.urgency_dot("other")
end
end
describe "airtime_quality/1" do
test "nil is unknown" do
assert :unknown == Index.airtime_quality(nil)
end
test "thresholds" do
assert :good == Index.airtime_quality(40)
assert :warning == Index.airtime_quality(70)
assert :bad == Index.airtime_quality(90)
end
end
describe "safe_type/1" do
test "maps known strings to atoms" do
assert :account == Index.safe_type("account")
assert :inventory_item == Index.safe_type("inventory_item")
assert :site == Index.safe_type("site")
assert :device == Index.safe_type("device")
assert :access_point == Index.safe_type("access_point")
end
test "unknown defaults to :account" do
assert :account == Index.safe_type("garbage")
assert :account == Index.safe_type(nil)
end
end
end