defmodule AprsmeWeb.MapLive.NavigationTest do # Logger.info calls are fine during tests; we don't silence them. use ExUnit.Case, async: true alias AprsmeWeb.MapLive.Navigation alias Phoenix.LiveView.Socket describe "determine_map_location/2" do test "explicit URL params win over IP geolocation" do params = %{"lat" => "40.0", "lng" => "-95.0", "z" => "7"} session = %{"ip_geolocation" => %{"lat" => 10.0, "lng" => 20.0}} assert {%{lat: 40.0, lng: -95.0}, 7, false} = Navigation.determine_map_location(params, session) end test "valid IP geolocation used when no explicit URL params" do session = %{"ip_geolocation" => %{"lat" => 45.5, "lng" => -122.6}} assert {%{lat: 45.5, lng: -122.6}, 11, true} = Navigation.determine_map_location(%{}, session) end test "missing or invalid geolocation falls back to URL defaults" do # No geolocation and no URL params → default center + skip_initial_url_update=true assert {%{lat: _, lng: _}, _zoom, true} = Navigation.determine_map_location(%{}, %{}) # Geolocation present but with non-numeric values → fall back session = %{"ip_geolocation" => %{"lat" => "not-a-number", "lng" => "nope"}} assert {%{lat: _, lng: _}, _zoom, true} = Navigation.determine_map_location(%{}, session) end test "URL params win even with malformed geolocation" do session = %{"ip_geolocation" => %{"lat" => "oops", "lng" => "oops"}} params = %{"lat" => "10.0"} {_, _, skip?} = Navigation.determine_map_location(params, session) assert skip? == false end end describe "handle_callsign_tracking/4" do @default_center %{lat: 10.0, lng: 20.0} @default_zoom 5 test "empty callsign returns unchanged center and zoom" do assert Navigation.handle_callsign_tracking("", @default_center, @default_zoom, false) == {@default_center, @default_zoom} assert Navigation.handle_callsign_tracking("", @default_center, @default_zoom, true) == {@default_center, @default_zoom} end test "when explicit URL params are set, tracking is bypassed" do assert Navigation.handle_callsign_tracking("K5ABC", @default_center, @default_zoom, true) == {@default_center, @default_zoom} end test "returns defaults when the database lookup raises" do # With a callsign that won't match any test data and no DB ownership, # the rescue clause returns the defaults. assert Navigation.handle_callsign_tracking( "NONEXISTENT-99", @default_center, @default_zoom, false ) == {@default_center, @default_zoom} end end describe "handle_callsign_search/2" do test "empty string returns the socket untouched" do socket = %Socket{assigns: %{__changed__: %{}}} assert {:noreply, ^socket} = Navigation.handle_callsign_search("", socket) end test "invalid callsign puts a flash error" do socket = %Socket{assigns: %{__changed__: %{}, flash: %{}}} {:noreply, result} = Navigation.handle_callsign_search("HELLO WORLD", socket) assert result.assigns.flash["error"] == "Invalid callsign format" end test "valid callsign triggers push_navigate" do socket = %Socket{ assigns: %{__changed__: %{}, flash: %{}}, redirected: nil } {:noreply, result} = Navigation.handle_callsign_search("K5ABC-9", socket) # push_navigate/2 sets the `redirected` field on the socket. assert result.redirected end end describe "update_and_zoom_to_location/4" do test "sets map_center and map_zoom assigns, and pushes a zoom event" do socket = %Socket{assigns: %{__changed__: %{}}} result = Navigation.update_and_zoom_to_location(socket, 30.5, -95.0, 8) assert result.assigns.map_center == %{lat: 30.5, lng: -95.0} assert result.assigns.map_zoom == 8 end end describe "zoom_to_current_location/1" do test "pushes a zoom_to_location event using the socket's center/zoom" do socket = %Socket{ assigns: %{__changed__: %{}, map_center: %{lat: 1.0, lng: 2.0}, map_zoom: 10} } # The function returns the socket (with push_event recorded). result = Navigation.zoom_to_current_location(socket) assert %Socket{} = result end end end