aprs.me/test/aprsme_web/live/status_live/index_test.exs

206 lines
6.8 KiB
Elixir

defmodule AprsmeWeb.StatusLive.IndexTest do
use AprsmeWeb.ConnCase
import Phoenix.LiveViewTest
alias AprsmeWeb.StatusLive.Index
alias Phoenix.LiveView.Socket
describe "mount via HTTP" do
test "renders the status page", %{conn: conn} do
{:ok, _lv, html} = live(conn, ~p"/status", on_error: :warn)
assert html =~ "System Status"
assert html =~ "APRS-IS Connection"
end
test "renders health score 3 (stable under 1 hour)", %{conn: conn} do
_ =
case :ets.info(:query_cache) do
:undefined -> :ets.new(:query_cache, [:named_table, :public, :set])
_ -> :ok
end
status = %{
connected: true,
server: "test.aprs.test",
port: 14_580,
connected_at: DateTime.add(DateTime.utc_now(), -1000, :second),
uptime_seconds: 1000,
login_id: "N0CALL",
filter: "r/33/-96/100",
packet_stats: %{total_packets: 10, last_packet_at: DateTime.utc_now(), packets_per_second: 1},
stored_packet_count: 50,
oldest_packet_timestamp: DateTime.add(DateTime.utc_now(), -3600, :second)
}
Aprsme.Cache.put(:query_cache, "aprs_status", status)
{:ok, _lv, html} = live(conn, ~p"/status", on_error: :warn)
# Uptime 1000s < 3600 → score 3. 50 stored packets.
assert html =~ "System Status"
assert html =~ "Connected"
Aprsme.Cache.del(:query_cache, "aprs_status")
end
test "renders health score 4 (stable under 1 day)", %{conn: conn} do
_ =
case :ets.info(:query_cache) do
:undefined -> :ets.new(:query_cache, [:named_table, :public, :set])
_ -> :ok
end
status = %{
connected: true,
server: "test",
port: 14_580,
connected_at: DateTime.add(DateTime.utc_now(), -10_000, :second),
# Uptime 10,000s is between 3600 and 86_400 → score 4.
uptime_seconds: 10_000,
login_id: "N0CALL",
filter: "r/0/0/100",
packet_stats: %{total_packets: 1, last_packet_at: nil, packets_per_second: 0},
stored_packet_count: 0,
oldest_packet_timestamp: nil
}
Aprsme.Cache.put(:query_cache, "aprs_status", status)
{:ok, _lv, html} = live(conn, ~p"/status", on_error: :warn)
assert html =~ "Connected"
Aprsme.Cache.del(:query_cache, "aprs_status")
end
test "renders the connected-path template when cache has a live status", %{conn: conn} do
# Ensure the cache ETS table exists for test.
_ =
case :ets.info(:query_cache) do
:undefined -> :ets.new(:query_cache, [:named_table, :public, :set])
_ -> :ok
end
status = %{
connected: true,
server: "cached.aprs.test",
port: 14_580,
connected_at: DateTime.add(DateTime.utc_now(), -3600, :second),
uptime_seconds: 3600,
login_id: "N0CALL",
filter: "r/33/-96/100",
packet_stats: %{
total_packets: 1234,
last_packet_at: DateTime.add(DateTime.utc_now(), -30, :second),
packets_per_second: 5
},
stored_packet_count: 5000,
oldest_packet_timestamp: DateTime.add(DateTime.utc_now(), -86_400, :second)
}
Aprsme.Cache.put(:query_cache, "aprs_status", status)
{:ok, _lv, html} = live(conn, ~p"/status", on_error: :warn)
assert html =~ "Connected"
assert html =~ "cached.aprs.test"
assert html =~ "N0CALL"
# Total packets formatted with thousands separator.
assert html =~ "1,234"
# Cleanup so other tests aren't affected.
Aprsme.Cache.del(:query_cache, "aprs_status")
end
end
describe "handle_info({:status_updated, status}, socket)" do
test "updates assigns with the new status" do
status = %{
connected: true,
server: "test-server",
port: 14_580,
connected_at: DateTime.utc_now(),
uptime_seconds: 60,
login_id: "TEST-ID",
filter: "r/0/0/100",
packet_stats: %{total_packets: 0, packets_per_second: 0, last_packet_at: nil},
stored_packet_count: 0,
oldest_packet_timestamp: nil
}
socket = %Socket{assigns: %{__changed__: %{}}}
assert {:noreply, new_socket} = Index.handle_info({:status_updated, status}, socket)
assert new_socket.assigns.aprs_status == status
assert new_socket.assigns.loading == false
assert %DateTime{} = new_socket.assigns.current_time
# Connected+uptime 60s → health score 2.
assert new_socket.assigns.health_score == 2
end
end
describe "handle_info({:aprs_status_update, status}, socket)" do
test "updates status without flipping loading flag" do
status = %{
connected: true,
server: "test-server",
port: 14_580,
connected_at: DateTime.utc_now(),
uptime_seconds: 100_000,
login_id: "TEST-ID",
filter: "r/0/0/100",
packet_stats: %{total_packets: 5, packets_per_second: 1, last_packet_at: DateTime.utc_now()},
stored_packet_count: 123,
oldest_packet_timestamp: DateTime.utc_now()
}
socket = %Socket{assigns: %{__changed__: %{}, loading: false}}
assert {:noreply, new_socket} =
Index.handle_info({:aprs_status_update, status}, socket)
assert new_socket.assigns.aprs_status == status
# Uptime > 86_400? 100_000 > 86_400 → yes → score 5.
assert new_socket.assigns.health_score == 5
# Loading flag is untouched (this code path doesn't toggle it).
assert new_socket.assigns.loading == false
end
end
describe "render with cluster_info populated" do
test "renders the Cluster Status section when cluster_info is present", %{conn: conn} do
_ =
case :ets.info(:query_cache) do
:undefined -> :ets.new(:query_cache, [:named_table, :public, :set])
_ -> :ok
end
status = %{
connected: true,
server: "clustered.aprs.test",
port: 14_580,
connected_at: DateTime.add(DateTime.utc_now(), -60, :second),
uptime_seconds: 60,
login_id: "N0CALL",
filter: "r/33/-96/100",
packet_stats: %{total_packets: 10, packets_per_second: 1, last_packet_at: DateTime.utc_now()},
stored_packet_count: 100,
oldest_packet_timestamp: DateTime.utc_now(),
cluster_info: %{
total_nodes: 3,
connected_nodes: 2,
leader_node: "node-a",
all_nodes: ["node-a", "node-b", "node-c"]
}
}
Aprsme.Cache.put(:query_cache, "aprs_status", status)
{:ok, _lv, html} = live(conn, ~p"/status", on_error: :warn)
assert html =~ "Cluster Status"
assert html =~ "Total Nodes"
assert html =~ "node-a"
assert html =~ "node-b"
Aprsme.Cache.del(:query_cache, "aprs_status")
end
end
end