diff --git a/test/aprsme_web/live/map_live/historical_loading_test.exs b/test/aprsme_web/live/map_live/historical_loading_test.exs index 3d3b15e..d8a0983 100644 --- a/test/aprsme_web/live/map_live/historical_loading_test.exs +++ b/test/aprsme_web/live/map_live/historical_loading_test.exs @@ -81,7 +81,7 @@ defmodule AprsmeWeb.MapLive.HistoricalLoadingTest do packet_ids = Enum.map(recent_packets, & &1.id) assert packet1.id in packet_ids assert packet2.id in packet_ids - refute _old_packet.id in packet_ids + refute Enum.any?(packet_ids, fn id -> id == _old_packet.id end) end test "loads historical packets with custom historical hours setting", %{conn: conn} do @@ -236,6 +236,104 @@ defmodule AprsmeWeb.MapLive.HistoricalLoadingTest do end end + describe "historical packet push events" do + test "sends add_historical_packets_batch events to client", %{conn: conn} do + now = DateTime.utc_now() + + # Create test packets + packets = for i <- 1..5 do + packet_fixture(%{ + sender: "PUSH#{i}", + base_callsign: "PUSH#{i}", + ssid: "0", + lat: 40.7 + (i * 0.01), + lon: -74.0 + (i * 0.01), + received_at: DateTime.add(now, -(i * 5 * 60), :second), + comment: "Push test station #{i}" + }) + end + + # Connect to the map at high zoom (should use marker mode, not heat map) + {:ok, view, _html} = live(conn, "/?z=12") + + # Send map_ready event + assert render_hook(view, "map_ready", %{}) + + # Send bounds that include all test packets + bounds = %{ + "north" => 40.8, + "south" => 40.6, + "east" => -73.9, + "west" => -74.1 + } + + # Send bounds_changed event + assert render_hook(view, "bounds_changed", %{"bounds" => bounds}) + + # Wait for historical loading + Process.sleep(200) + + # Verify all packets would be included in the query + recent_packets = Packets.get_recent_packets(%{ + bounds: [bounds["west"], bounds["south"], bounds["east"], bounds["north"]], + hours_back: 1, + limit: 500 + }) + + packet_ids = Enum.map(recent_packets, & &1.id) + assert length(packet_ids) >= 5 + + # Verify all our test packets are included + for packet <- packets do + assert packet.id in packet_ids + end + end + + test "does not send historical packets when bounds are invalid", %{conn: conn} do + # Create a test packet + packet_fixture(%{ + sender: "INVALID1", + base_callsign: "INVALID1", + ssid: "0", + lat: 40.7128, + lon: -74.0060, + received_at: DateTime.add(DateTime.utc_now(), -30 * 60, :second), + comment: "Test for invalid bounds" + }) + + # Connect to the map + {:ok, view, _html} = live(conn, "/") + + # Send map_ready event + assert render_hook(view, "map_ready", %{}) + + # Send invalid bounds (north < south) + invalid_bounds = %{ + "north" => 40.5, + "south" => 40.9, + "east" => -73.7, + "west" => -74.3 + } + + # This should not cause an error, but bounds won't be processed + assert render_hook(view, "bounds_changed", %{"bounds" => invalid_bounds}) + + # Wait briefly + Process.sleep(100) + + # Since we can't check internal state, we verify the view is still functional + # by sending valid bounds and checking it still works + valid_bounds = %{ + "north" => 40.9, + "south" => 40.5, + "east" => -73.7, + "west" => -74.3 + } + + assert render_hook(view, "bounds_changed", %{"bounds" => valid_bounds}) + end + end + describe "progressive historical loading" do test "loads packets in batches for low zoom levels", %{conn: conn} do now = DateTime.utc_now() diff --git a/test/integration/historical_loading_integration_test.exs b/test/integration/historical_loading_integration_test.exs new file mode 100644 index 0000000..b890b0f --- /dev/null +++ b/test/integration/historical_loading_integration_test.exs @@ -0,0 +1,251 @@ +defmodule AprsmeWeb.HistoricalLoadingIntegrationTest do + @moduledoc """ + Integration tests for historical packet loading using Wallaby + Tests the complete user experience including initial page load behavior + """ + use ExUnit.Case, async: false + use Wallaby.Feature + + import Wallaby.Browser + import Wallaby.Query + import Aprsme.PacketsFixtures + + @tag :integration + describe "historical packet loading on page load" do + test "displays historical packets immediately after map loads", %{session: session} do + # Create test packets with known positions + now = DateTime.utc_now() + + packet1 = packet_fixture(%{ + sender: "INTTEST1", + base_callsign: "INTTEST1", + ssid: "0", + lat: 40.7128, + lon: -74.0060, + received_at: DateTime.add(now, -20 * 60, :second), + comment: "Integration test station 1", + symbol_code: "k", + symbol_table_id: "/" + }) + + packet2 = packet_fixture(%{ + sender: "INTTEST2", + base_callsign: "INTTEST2", + ssid: "0", + lat: 40.7580, + lon: -73.9855, + received_at: DateTime.add(now, -10 * 60, :second), + comment: "Integration test station 2", + symbol_code: "-", + symbol_table_id: "/" + }) + + # Navigate to the map + session + |> visit("/") + |> assert_has(css("#map", text: "")) + + # Wait for map to initialize and markers to appear + # The map should automatically load historical packets + Process.sleep(2000) + + # Check that markers are present on the map + # Look for Leaflet marker elements + assert_has(session, css(".leaflet-marker-icon")) + + # Verify at least 2 markers are present (our test packets) + marker_count = + session + |> all(css(".leaflet-marker-icon")) + |> length() + + assert marker_count >= 2, "Expected at least 2 markers, found #{marker_count}" + + # Click on a marker to verify it's one of our test packets + session + |> click(css(".leaflet-marker-icon", at: 0)) + + # Wait for popup to appear + Process.sleep(500) + + # Verify popup contains one of our test callsigns + assert_has(session, css(".leaflet-popup-content", text: ~r/INTTEST[12]/)) + end + + test "loads packets within specified historical time range", %{session: session} do + now = DateTime.utc_now() + + # Create packets at different times + _old_packet = packet_fixture(%{ + sender: "OLDTEST", + base_callsign: "OLDTEST", + ssid: "0", + lat: 40.7128, + lon: -74.0060, + received_at: DateTime.add(now, -3 * 60 * 60, :second), # 3 hours ago + comment: "Old packet - should not appear with hist=1" + }) + + recent_packet = packet_fixture(%{ + sender: "RECENTTEST", + base_callsign: "RECENTTEST", + ssid: "0", + lat: 40.7128, + lon: -74.0060, + received_at: DateTime.add(now, -30 * 60, :second), # 30 minutes ago + comment: "Recent packet - should appear" + }) + + # Navigate to map with 1 hour historical range (default) + session + |> visit("/?hist=1") + |> assert_has(css("#map")) + + # Wait for historical loading + Process.sleep(2000) + + # Click on the marker (should be the recent one) + session + |> click(css(".leaflet-marker-icon", at: 0)) + + Process.sleep(500) + + # Verify it's the recent packet, not the old one + assert_has(session, css(".leaflet-popup-content", text: "RECENTTEST")) + refute_has(session, css(".leaflet-popup-content", text: "OLDTEST")) + + # Now test with extended historical range + session + |> visit("/?hist=6") # 6 hours + |> assert_has(css("#map")) + + Process.sleep(2000) + + # Now both packets should be visible + marker_count = + session + |> all(css(".leaflet-marker-icon")) + |> length() + + assert marker_count >= 2, "Expected at least 2 markers with 6-hour range" + end + + test "updates historical packets when bounds change", %{session: session} do + now = DateTime.utc_now() + + # Create packets in different locations + nyc_packet = packet_fixture(%{ + sender: "NYC1", + base_callsign: "NYC1", + ssid: "0", + lat: 40.7128, + lon: -74.0060, + received_at: DateTime.add(now, -30 * 60, :second), + comment: "NYC packet" + }) + + la_packet = packet_fixture(%{ + sender: "LA1", + base_callsign: "LA1", + ssid: "0", + lat: 34.0522, + lon: -118.2437, + received_at: DateTime.add(now, -30 * 60, :second), + comment: "LA packet" + }) + + # Start focused on NYC + session + |> visit("/?lat=40.7128&lng=-74.0060&z=10") + |> assert_has(css("#map")) + + Process.sleep(2000) + + # Should see NYC packet + session + |> click(css(".leaflet-marker-icon", at: 0)) + + Process.sleep(500) + + assert_has(session, css(".leaflet-popup-content", text: "NYC1")) + + # Close popup + session + |> send_keys([:escape]) + + # Pan to LA (this would be done via map interaction in real usage) + # For testing, we'll navigate to new URL + session + |> visit("/?lat=34.0522&lng=-118.2437&z=10") + + Process.sleep(2000) + + # Should now see LA packet instead + session + |> click(css(".leaflet-marker-icon", at: 0)) + + Process.sleep(500) + + assert_has(session, css(".leaflet-popup-content", text: "LA1")) + end + end + + @tag :integration + describe "historical loading with tracked callsigns" do + test "loads all packets for tracked callsign regardless of bounds", %{session: session} do + now = DateTime.utc_now() + + # Create packets for tracked station at different locations + packet1 = packet_fixture(%{ + sender: "TRACK1-9", + base_callsign: "TRACK1", + ssid: "9", + lat: 40.7128, + lon: -74.0060, + received_at: DateTime.add(now, -45 * 60, :second), + comment: "NYC position" + }) + + packet2 = packet_fixture(%{ + sender: "TRACK1-9", + base_callsign: "TRACK1", + ssid: "9", + lat: 41.8781, + lon: -87.6298, + received_at: DateTime.add(now, -30 * 60, :second), + comment: "Chicago position" + }) + + packet3 = packet_fixture(%{ + sender: "TRACK1-9", + base_callsign: "TRACK1", + ssid: "9", + lat: 34.0522, + lon: -118.2437, + received_at: DateTime.add(now, -15 * 60, :second), + comment: "LA position" + }) + + # Navigate to tracked callsign URL + session + |> visit("/TRACK1-9") + |> assert_has(css("#map")) + + # Wait for map to load and center on latest position + Process.sleep(2000) + + # Should see trail connecting all positions + # Verify we have markers (latest position + trail points) + marker_count = + session + |> all(css(".leaflet-marker-icon")) + |> length() + + # Should have at least 1 marker for current position + assert marker_count >= 1, "Expected markers for tracked station" + + # Verify polyline trail exists + assert_has(session, css(".leaflet-pane .leaflet-overlay-pane polyline")) + end + end +end \ No newline at end of file