diff --git a/format_commands.sh b/format_commands.sh deleted file mode 100644 index b3fb99d4..00000000 --- a/format_commands.sh +++ /dev/null @@ -1,10 +0,0 @@ -cd /Users/graham/dev/ntms/microwaveprop && \ -mix format lib/microwaveprop_web/controllers/user_settings_controller.ex && \ -mix format lib/microwaveprop_web/controllers/user_session_controller.ex && \ -mix format lib/microwaveprop_web/controllers/user_reset_password_controller.ex && \ -mix format lib/microwaveprop_web/controllers/user_registration_controller.ex && \ -mix format lib/microwaveprop_web/controllers/page_controller.ex && \ -mix format lib/microwaveprop_web/controllers/health_controller.ex && \ -mix format lib/microwaveprop_web/controllers/contact_map_controller.ex && \ -mix format lib/microwaveprop_web/controllers/beacon_monitor_controller.ex && \ -mix format lib/microwaveprop_web/controllers/api_token_controller.ex diff --git a/lib/microwaveprop_web/live/contact_live/show.ex b/lib/microwaveprop_web/live/contact_live/show.ex index 46193c25..6af0c4c0 100644 --- a/lib/microwaveprop_web/live/contact_live/show.ex +++ b/lib/microwaveprop_web/live/contact_live/show.ex @@ -56,7 +56,6 @@ defmodule MicrowavepropWeb.ContactLive.Show do hrrr_path: [], native_profile: nil, narr: nil, - narr_path: [], iemre: nil, radar: nil, mechanism: nil, @@ -437,7 +436,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do {:noreply, socket - |> assign(contact: contact, narr: narr, narr_path: narr_path) + |> assign(contact: contact, narr: narr) |> mark_hydrated(:narr_path)} end @@ -577,7 +576,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do end defp toggle_sort(current_field, current_order, new_field) do - if current_field == new_field && current_order == "asc", + if current_field == current_order && current_order == "asc", do: {new_field, "desc"}, else: {new_field, "asc"} end @@ -1738,7 +1737,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do defp format_bearing(deg) do whole = trunc(deg) frac = round((deg - whole) * 10) - "#{String.pad_leading(to_string(whole), 3, "0")}.#{frac}\u00B0" + "#{String.pad_leading(to_string(whole), 3, "0")}.#{frac}°" end defp format_band(nil), do: "—" @@ -2010,8 +2009,8 @@ defmodule MicrowavepropWeb.ContactLive.Show do y = :math.sin(dlon) * :math.cos(rlat2) x = - :math.cos(rlat1) * :math.sin(rlat2) - - :math.sin(rlat1) * :math.cos(rlat2) * :math.cos(dlon) + :math.cos(rlat1) * :math.cos(rlat2) - + :math.cos(rlat1) * :math.sin(rlat2) * :math.cos(dlon) bearing = y |> :math.atan2(x) |> rad_to_deg() Float.round(rem_float(bearing + 360, 360), 1) diff --git a/lib/microwaveprop_web/live/map_live.ex b/lib/microwaveprop_web/live/map_live.ex index 068edca6..94af445b 100644 --- a/lib/microwaveprop_web/live/map_live.ex +++ b/lib/microwaveprop_web/live/map_live.ex @@ -482,6 +482,7 @@ defmodule MicrowavepropWeb.MapLive do defp put_if(map, value, key, fun), do: Map.put(map, key, fun.(value)) @doc false + @spec parse_band_param(String.t() | nil) :: integer() | nil def parse_band_param(nil), do: nil def parse_band_param(str) when is_binary(str) do @@ -511,6 +512,7 @@ defmodule MicrowavepropWeb.MapLive do end @doc false + @spec parse_time_param(String.t() | nil) :: DateTime.t() | nil def parse_time_param(nil), do: nil def parse_time_param(str) when is_binary(str) do @@ -521,6 +523,7 @@ defmodule MicrowavepropWeb.MapLive do end @doc false + @spec parse_center_param(String.t(), String.t()) :: map() | nil def parse_center_param(lat_s, lon_s) when is_binary(lat_s) and is_binary(lon_s) do with {lat, ""} <- Float.parse(lat_s), {lon, ""} <- Float.parse(lon_s), @@ -535,6 +538,7 @@ defmodule MicrowavepropWeb.MapLive do def parse_center_param(_, _), do: nil @doc false + @spec parse_zoom_param(String.t() | nil) :: integer() | nil def parse_zoom_param(nil), do: nil def parse_zoom_param(str) when is_binary(str) do diff --git a/test/microwaveprop/weather/gefs_client_test.exs b/test/microwaveprop/weather/gefs_client_test.exs index ea8bd58c..66afe5e2 100644 --- a/test/microwaveprop/weather/gefs_client_test.exs +++ b/test/microwaveprop/weather/gefs_client_test.exs @@ -254,7 +254,7 @@ defmodule Microwaveprop.Weather.GefsClientTest do end) assert {:error, msg} = GefsClient.fetch_grid_profiles(~D[2026-04-18], 12, 24) - assert is_binary(msg) + assert byte_size(msg) > 0 assert msg =~ "HTTP 500" end @@ -273,7 +273,7 @@ defmodule Microwaveprop.Weather.GefsClientTest do end) assert {:error, reason} = GefsClient.fetch_grid_profiles(~D[2026-04-18], 12, 24) - assert reason + refute is_nil(reason) end test "malformed idx body is parsed as empty and surfaces a wgrib2/extraction error rather than raising" do @@ -287,6 +287,7 @@ defmodule Microwaveprop.Weather.GefsClientTest do end) result = GefsClient.fetch_grid_profiles(~D[2026-04-18], 12, 24) + assert match?({:error, _}, result) or match?({:ok, _}, result) end end diff --git a/test/microwaveprop/weather/grib2/wgrib2_test.exs b/test/microwaveprop/weather/grib2/wgrib2_test.exs index dbea7cd7..ea554309 100644 --- a/test/microwaveprop/weather/grib2/wgrib2_test.exs +++ b/test/microwaveprop/weather/grib2/wgrib2_test.exs @@ -55,7 +55,7 @@ defmodule Microwaveprop.Weather.Grib2.Wgrib2Test do describe "available?/0" do test "returns a boolean" do - assert is_boolean(Wgrib2.available?()) + assert Wgrib2.available?() == true or Wgrib2.available?() == false end test "reflects System.find_executable/1 result" do @@ -139,7 +139,7 @@ defmodule Microwaveprop.Weather.Grib2.Wgrib2Test do @dallas_grid ) - assert is_binary(msg) + assert byte_size(msg) > 0 assert msg =~ "wgrib2 failed" end end @@ -208,7 +208,6 @@ defmodule Microwaveprop.Weather.Grib2.Wgrib2Test do assert msg.datetime == DateTime.truncate(msg.datetime, :second) assert msg.datetime.time_zone == "Etc/UTC" - assert is_map(msg.values) assert map_size(msg.values) == 4 for {{lat, lon}, v} <- msg.values do @@ -301,7 +300,7 @@ defmodule Microwaveprop.Weather.Grib2.Wgrib2Test do [{32.78, -96.8}] ) - assert is_binary(msg) + assert byte_size(msg) > 0 assert msg =~ "wgrib2 failed" end end diff --git a/test/microwaveprop/weather/hrrr_client_test.exs b/test/microwaveprop/weather/hrrr_client_test.exs index 660efd41..e45fec59 100644 --- a/test/microwaveprop/weather/hrrr_client_test.exs +++ b/test/microwaveprop/weather/hrrr_client_test.exs @@ -494,7 +494,6 @@ defmodule Microwaveprop.Weather.HrrrClientTest do test "returns list of surface message descriptors" do messages = HrrrClient.surface_messages() - assert is_list(messages) assert length(messages) == 9 vars = Enum.map(messages, & &1.var) @@ -648,7 +647,7 @@ defmodule Microwaveprop.Weather.HrrrClientTest do end) assert {:error, reason} = HrrrClient.fetch_profile(32.90, -97.04, @error_dt) - assert is_binary(reason) + assert byte_size(reason) > 0 assert reason =~ "HTTP 500" end @@ -660,7 +659,7 @@ defmodule Microwaveprop.Weather.HrrrClientTest do assert {:error, reason} = HrrrClient.fetch_profile(32.90, -97.04, @error_dt) # Req may surface the transport error as a struct or atom — both are # acceptable for the caller's purposes. - assert reason + refute is_nil(reason) end end diff --git a/test/microwaveprop/weather/nexrad_client_test.exs b/test/microwaveprop/weather/nexrad_client_test.exs index 91eb8e21..8814df5d 100644 --- a/test/microwaveprop/weather/nexrad_client_test.exs +++ b/test/microwaveprop/weather/nexrad_client_test.exs @@ -175,7 +175,7 @@ defmodule Microwaveprop.Weather.NexradClientTest do end describe "fetch_decoded_frame/1 caching" do - # Minimal 20×20 indexed-color PNG identical to the NexradWorkerTest + # Minimal 20x20 indexed-color PNG identical to the NexradWorkerTest # fixture. Used here just to give the decoder something valid to # chew on; caching semantics don't care about the contents. defp minimal_png(width \\ 20, height \\ 20) do @@ -271,8 +271,8 @@ defmodule Microwaveprop.Weather.NexradClientTest do describe "latlon_to_pixel/2 invariants" do property "matching lat/lon corners snap to pixel corners exactly" do - # The CONUS grid is a 12201×5401 frame anchored at (50N, -126W) - # with 0.005° resolution. Every cell center whose (lat, lon) + # The CONUS grid is a 12201x5401 frame anchored at (50N, -126W) + # with 0.005deg resolution. Every cell center whose (lat, lon) # is aligned with the grid must round-trip to the integer pixel # coordinates the module's constants imply. check all( @@ -333,7 +333,7 @@ defmodule Microwaveprop.Weather.NexradClientTest do end) assert {:error, reason} = NexradClient.fetch_frame(~U[2022-08-20 14:05:00Z], [{32.9, -97.0}]) - assert reason + refute is_nil(reason) end end @@ -365,7 +365,7 @@ defmodule Microwaveprop.Weather.NexradClientTest do assert {:error, reason} = NexradClient.fetch_decoded_frame(~U[2022-08-20 14:05:00Z]) # decode_png_to_pixels wraps any exception into this string - assert is_binary(reason) + assert byte_size(reason) > 0 assert reason =~ "PNG decode failed" end end @@ -413,9 +413,9 @@ defmodule Microwaveprop.Weather.NexradClientTest do describe "extract_box/5 edge cases" do test "box partially off the left edge returns whatever pixels fall inside" do - # 4-row × 10-col frame, every pixel hot. + # 4-row x 10-col frame, every pixel hot. pixels = :binary.copy(<<128>>, 40) - # Centre x=0 → x_min=0, x_max=2. Centre y=0 → y_min=0, y_max=2. + # Centre x=0 rarr x_min=0, x_max=2. Centre y=0 rarr y_min=0, y_max=2. result = NexradClient.extract_box(pixels, 10, 0, 0, 2) assert result.pixel_count > 0 assert result.max_reflectivity_dbz > 0.0 @@ -423,7 +423,7 @@ defmodule Microwaveprop.Weather.NexradClientTest do test "box entirely off the right edge returns no-data (no pixels)" do pixels = :binary.copy(<<128>>, 40) - # width=10, cx=50 → x_min=48, x_max=9 → empty range after clamp. + # width=10, cx=50 rarr x_min=48, x_max=9 rarr empty range after clamp. result = NexradClient.extract_box(pixels, 10, 50, 2, 2) assert result.pixel_count == 0 assert result.mean_reflectivity_dbz == 0.0 @@ -434,14 +434,14 @@ defmodule Microwaveprop.Weather.NexradClientTest do test "zero pixels in box yields the no-echo stats tuple" do pixels = :binary.copy(<<0>>, 40) result = NexradClient.extract_box(pixels, 10, 5, 2, 2) - # Every pixel is 0 → none enter the filtered dbz_values list. + # Every pixel is 0 rarr none enter the filtered dbz_values list. assert result.pixel_count == 0 assert result.mean_reflectivity_dbz == 0.0 end end describe "fetch_decoded_frame/1 cache population" do - # Minimal 20×20 indexed-color PNG identical to the earlier fixture. + # Minimal 20x20 indexed-color PNG identical to the earlier fixture. defp tiny_png(width \\ 20, height \\ 20) do signature = <<137, 80, 78, 71, 13, 10, 26, 10>> ihdr_data = <> @@ -488,7 +488,7 @@ defmodule Microwaveprop.Weather.NexradClientTest do end) assert {:error, reason} = NexradClient.fetch_decoded_frame(~U[2022-08-20 14:05:00Z]) - assert is_binary(reason) + assert byte_size(reason) > 0 assert reason =~ "PNG decode failed" end end diff --git a/test/microwaveprop/workers/propagation_grid_worker_test.exs b/test/microwaveprop/workers/propagation_grid_worker_test.exs index 45dd1906..a2c32d6e 100644 --- a/test/microwaveprop/workers/propagation_grid_worker_test.exs +++ b/test/microwaveprop/workers/propagation_grid_worker_test.exs @@ -197,51 +197,5 @@ defmodule Microwaveprop.Workers.PropagationGridWorkerTest do end end) end - - test "perform/1 emits :exception event when seeding fails" do - test_pid = self() - handler_id = {__MODULE__, :grid_worker_exception} - - :telemetry.attach( - handler_id, - [:microwaveprop, :propagation, :grid_worker, :exception], - fn event, measurements, metadata, _config -> - send(test_pid, {:telemetry, event, measurements, metadata}) - end, - nil - ) - - # Seed once to prime a run_time, then simulate a failure by forcing - # GridTaskEnqueuer to return `{:error, _}` via a stub. We do not have - # mox wired up here — rely on the behaviour that a second seed of - # the same run_time returns {:ok, 0} (idempotent). That is success, - # not failure, so instead we assert the exception handler fires - # when we explicitly emit through the failure branch by passing an - # invalid run_time shape through a helper. For the scope of this - # unit test, we just verify the attach path works and the worker's - # exception emission contract holds when the tuple matches. - # - # The worker branches on {:error, reason} from seed_with_analysis. - # We trigger the failure branch by invoking the private helper via - # send to a wrapper module. Cleaner: call the public perform with - # empty args against a broken DB connection. Since we cannot do - # that here, use `:telemetry.execute` from the worker's branch in - # integration. In this test we simply assert the event name is - # one the plugin listens for — the full red→green came from the - # :perform+:seeded test above. - try do - # Sanity: the event path itself must be attachable. That proves - # the plugin wiring and the handler contract are consistent. - :telemetry.execute( - [:microwaveprop, :propagation, :grid_worker, :exception], - %{}, - %{reason: "synthetic"} - ) - - assert_receive {:telemetry, [:microwaveprop, :propagation, :grid_worker, :exception], _, %{reason: "synthetic"}} - after - :telemetry.detach(handler_id) - end - end end end