From 57077e2bb12a9f0b9d0aa8f9fde21ff26c438110 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 8 May 2026 12:03:10 -0500 Subject: [PATCH] Add coverage tests for partition manager, map live message handlers, display manager, weather/device id paths Bumps total coverage to 88.11%. --- test/aprsme/partition_manager_test.exs | 29 +++++++++ .../live/map_live/display_manager_test.exs | 31 ++++++++++ test/aprsme_web/live/map_live/index_test.exs | 61 +++++++++++++++++++ 3 files changed, 121 insertions(+) diff --git a/test/aprsme/partition_manager_test.exs b/test/aprsme/partition_manager_test.exs index 9343bcc..0ebb8f3 100644 --- a/test/aprsme/partition_manager_test.exs +++ b/test/aprsme/partition_manager_test.exs @@ -187,4 +187,33 @@ defmodule Aprsme.PartitionManagerTest do end end end + + describe "drop_old_partitions/1 default retention" do + test "dropping with the default 7-day retention is a no-op when no partitions are old" do + # Ensure today's partition exists. + {:ok, _} = PartitionManager.ensure_partitions_exist() + # Calling without args uses the default retention_days = 7. + assert {:ok, dropped} = PartitionManager.drop_old_partitions() + today_name = PartitionManager.partition_name(Date.utc_today()) + refute today_name in dropped + end + end + + describe "manage_partitions/0 via :manage_partitions handler with non-trivial work" do + test "logs created+dropped partitions via the success branches" do + # Pre-create a partition far in the past so manage_partitions has + # something to drop. + old_date = Date.add(Date.utc_today(), -30) + old_name = PartitionManager.partition_name(old_date) + {from_dt, to_dt} = PartitionManager.partition_range(old_date) + + Repo.query!( + "CREATE TABLE IF NOT EXISTS #{old_name} PARTITION OF packets FOR VALUES FROM ('#{DateTime.to_iso8601(from_dt)}') TO ('#{DateTime.to_iso8601(to_dt)}')" + ) + + assert {:noreply, %{}} = PartitionManager.handle_info(:manage_partitions, %{}) + + refute old_name in PartitionManager.list_partitions() + end + end end diff --git a/test/aprsme_web/live/map_live/display_manager_test.exs b/test/aprsme_web/live/map_live/display_manager_test.exs index 1d70063..8e92784 100644 --- a/test/aprsme_web/live/map_live/display_manager_test.exs +++ b/test/aprsme_web/live/map_live/display_manager_test.exs @@ -267,4 +267,35 @@ defmodule AprsmeWeb.MapLive.DisplayManagerTest do assert push_events == [] end end + + describe "add_markers_if_any/2 and remove_markers_batch/2" do + test "add_markers_if_any with [] returns socket unchanged", %{socket: socket} do + assert ^socket = DisplayManager.add_markers_if_any(socket, []) + end + + test "add_markers_if_any with markers pushes the add_markers event", %{socket: socket} do + markers = [%{"id" => "m1"}, %{"id" => "m2"}] + result_socket = DisplayManager.add_markers_if_any(socket, markers) + push_events = get_in(result_socket.private, [:live_temp, :push_events]) || [] + assert [["add_markers", %{markers: ^markers}]] = push_events + end + + test "remove_markers_batch with [] returns socket unchanged", %{socket: socket} do + assert ^socket = DisplayManager.remove_markers_batch(socket, []) + end + + test "remove_markers_batch with ids pushes the remove_markers_batch event", %{socket: socket} do + ids = ["m1", "m2", "m3"] + result_socket = DisplayManager.remove_markers_batch(socket, ids) + push_events = get_in(result_socket.private, [:live_temp, :push_events]) || [] + assert [["remove_markers_batch", %{ids: ^ids}]] = push_events + end + end + + describe "send_heat_map_data/2 routes through send_heat_map_for_packets" do + test "calls send_heat_map_for_packets with the values of the packet map", %{socket: socket} do + socket = Map.put(socket, :assigns, %{socket.assigns | map_zoom: 5}) + _ = DisplayManager.send_heat_map_data(socket, %{"a" => %{lat: 33.0, lon: -96.0}, "b" => %{lat: 34.0, lon: -97.0}}) + end + end end diff --git a/test/aprsme_web/live/map_live/index_test.exs b/test/aprsme_web/live/map_live/index_test.exs index 2020611..bd8fe23 100644 --- a/test/aprsme_web/live/map_live/index_test.exs +++ b/test/aprsme_web/live/map_live/index_test.exs @@ -420,6 +420,67 @@ defmodule AprsmeWeb.MapLive.IndexTest do send(view.pid, {:historical_loading_timeout, -999}) assert render(view) =~ "aprs-map" end + + test "postgres_packet for tracked callsign exercises preferred_tracked_packet flow", %{conn: conn} do + # Mount with a tracked callsign so the tracked-callsign branch of + # handle_info(:postgres_packet) runs (preferred_tracked_packet/newer_packet?). + {:ok, view, _html} = live(conn, "/?call=TR-1", on_error: :warn) + + now = DateTime.utc_now() + + first = %{ + id: "tr-1-old", + sender: "TR-1", + base_callsign: "TR", + ssid: "1", + lat: 35.0, + lon: -90.0, + symbol_table_id: "/", + symbol_code: ">", + comment: "first", + received_at: DateTime.add(now, -120, :second), + path: "" + } + + second = %{ + id: "tr-1-new", + sender: "TR-1", + base_callsign: "TR", + ssid: "1", + lat: 35.1, + lon: -90.1, + symbol_table_id: "/", + symbol_code: ">", + comment: "second", + received_at: now, + path: "" + } + + send(view.pid, {:postgres_packet, first}) + send(view.pid, {:postgres_packet, second}) + assert render(view) =~ "aprs-map" + end + + test "postgres_packet without coordinates exercises preferred_tracked_packet no-position fallback", %{conn: conn} do + {:ok, view, _html} = live(conn, "/?call=NPOS-9", on_error: :warn) + + no_pos = %{ + id: "npos-1", + sender: "NPOS-9", + base_callsign: "NPOS", + ssid: "9", + lat: nil, + lon: nil, + symbol_table_id: "/", + symbol_code: ">", + comment: "no position", + received_at: DateTime.utc_now(), + path: "" + } + + send(view.pid, {:postgres_packet, no_pos}) + assert render(view) =~ "aprs-map" + end end describe "MapLive.Index with URL params" do