aprs.me/test/aprsme_web/live/bad_packets_live_test.exs
Graham McIntire 1e32ce7051
Improve test coverage to 87% and point vendor/aprs submodule at codeberg
Coverage:
- Adds focused tests across 13 files covering previously-uncovered
  branches: Packet changeset normalisation (course, wind_direction,
  struct data_extended); Packets store_packet edge cases (nested
  position shapes, ssid handling, string-keyed raw_packet);
  DeviceIdentification HTTP success/404 via Req plug stub; ResendAdapter
  catch-all body, deliver_many, nil/binary formatters; ApiDocsLive
  packets with missing fields; AprsSymbol normalize helpers;
  BadPacketsLive refresh and postgres_notify; MobileChannel handle_info
  catch-all and postgres_packet path; PacketProcessor existing-marker
  movement detection; PacketReplay sanitize_value type clauses;
  InsertOptimizer GenServer lifecycle and negative-duration metric;
  PageController shutdown-handler integration; UrlParams delegated
  helpers.
- mix.exs: configure test_coverage with summary threshold of 87 and
  ignore_modules for test fixtures and macro-only template modules.

Bug fix:
- MapLive.Index handle_info: add a clause for the raw {:new_deployment,
  _} tuple. Phoenix.PubSub.broadcast delivers the raw payload to plain
  subscribers, but the existing handler only matched the %Broadcast{}
  fast-lane wrapper. DeploymentNotifier broadcasts via the raw path,
  which crashed the LiveView under test concurrency.

Submodule:
- Update .gitmodules vendor/aprs URL from
  https://github.com/aprsme/aprs.git to
  ssh://git@codeberg.org/gmcintire/aprs.git.
2026-05-05 15:18:28 -05:00

96 lines
3.2 KiB
Elixir

defmodule AprsmeWeb.BadPacketsLiveTest do
use AprsmeWeb.ConnCase
import Phoenix.LiveViewTest
alias Aprsme.BadPacket
alias Aprsme.Repo
describe "Index" do
test "renders bad packets page with card", %{conn: conn} do
{:ok, _index_live, html} = live(conn, ~p"/badpackets", on_error: :warn)
assert html =~ "shadow-sm"
assert html =~ "sm:rounded-lg"
end
test "lists all bad packets with table", %{conn: conn} do
bad_packet =
Repo.insert!(%BadPacket{
raw_packet: "KD9PDP>APRS:Invalid packet data",
error_message: "Failed to parse APRS data",
error_type: "parse_error",
attempted_at: DateTime.utc_now()
})
{:ok, _index_live, html} = live(conn, ~p"/badpackets", on_error: :warn)
assert html =~ bad_packet.error_message
assert html =~ bad_packet.error_type
assert html =~ "table"
assert html =~ "rounded-md"
end
test "displays empty state when no bad packets", %{conn: conn} do
{:ok, _index_live, html} = live(conn, ~p"/badpackets", on_error: :warn)
assert html =~ "No bad packets"
assert html =~ "All packets are parsing successfully!"
assert html =~ "text-green-600"
end
test "updates in real-time when new bad packet is created", %{conn: conn} do
{:ok, index_live, _html} = live(conn, ~p"/badpackets", on_error: :warn)
# Create a bad packet after the live view is loaded
bad_packet =
Repo.insert!(%BadPacket{
raw_packet: "KD9PDP>APRS:New invalid packet",
error_message: "New parse error",
error_type: "validation_error",
attempted_at: DateTime.utc_now()
})
# The LiveView listens to postgres notifications, so we need to trigger a refresh
# by sending the :do_refresh message directly
send(index_live.pid, :do_refresh)
# Wait for the async update
:timer.sleep(100)
html = render(index_live)
assert html =~ bad_packet.error_message
assert html =~ bad_packet.error_type
end
test "works correctly with dark mode support", %{conn: conn} do
{:ok, _index_live, html} = live(conn, ~p"/badpackets", on_error: :warn)
assert html =~ "dark:bg-gray-800"
assert html =~ "dark:text-gray-400"
end
test "refresh event sets loading=true and triggers a re-fetch", %{conn: conn} do
{:ok, index_live, _html} = live(conn, ~p"/badpackets", on_error: :warn)
# Triggers handle_event("refresh", ...) which sends :do_refresh and assigns loading=true
_ = render_hook(index_live, "refresh", %{})
# Wait briefly for the :do_refresh message to be processed.
:timer.sleep(50)
html = render(index_live)
# After do_refresh runs, loading flips back to false; the page should still render.
assert html =~ "shadow-sm"
end
test "postgres_notify message triggers a re-fetch", %{conn: conn} do
{:ok, index_live, _html} = live(conn, ~p"/badpackets", on_error: :warn)
# Hits handle_info({:postgres_notify, _payload}, socket) — sends :do_refresh.
send(index_live.pid, {:postgres_notify, %{event: "INSERT"}})
:timer.sleep(50)
assert Process.alive?(index_live.pid)
end
end
end