prop/test/microwaveprop/workers/ionosphere_fetch_worker_test.exs
Graham McIntire f99d07bd29
test: push line coverage from 71.7% → 78.67%
Adds ~600 new test cases (2013 → 2613 tests; 170 properties; 0
failures) across 12 new test files plus expansions of eight existing
files. Big lifts per module:

  ContactLive.Mechanism      33 → 100%
  MetricsPlug                54 → ~100%
  Microwaveprop.Release      15.8 → 70%+
  Telemetry                  38 → 76%
  HrrrNativeGridWorker       27.7 → 76%
  ContactLive.Show           34 → 48% (handler + render branches)
  Admin.ContactEditLive      49.7 → 70%+
  GefsFetchWorker            35.8 → ~55%
  IonosphereFetchWorker      56.3 → 75%
  PathLive                   58.9 → 67%
  WeatherMapLive             66.9 → 80.2%
  RoverLive                  0 → 70.3%
  ContactMapLive             59.2 → 89.8%
  ContactMapController       0 → 100%
  Mix tasks (Rust.Golden, Notebook, Backtest, HrrrBackfill,
    HrrrClimatology, HrrrNativeBackfill, NexradBackfill,
    RadarBackfill, ImportContestLogs, PropagationGrid,
    ResetEnrichment, Hrrr.PurgeGridPoints)  0 → ~60-100%

Two incidental fixes made while adding tests:

- ContactLive.Show.handle_event("toggle_flag", ...) was passing
  socket.assigns.current_scope to admin?/1 instead of socket.assigns,
  so admins never matched the pattern and every toggle ran the
  "Admins only." flash branch. Flag now toggles for admins again.

- Commercial.PollWorker.fetch_weather/1 promoted from private to
  @doc'd public so the IEM-fetch + ASOS-upsert path can be tested
  directly without driving perform/1 through live SNMP (which was
  timing out for ~50 s per test in the earlier attempt).

Stable property-test additions cover the dewpoint-from-RH monotonicity,
nearest_run/1 idempotence, and the ionosphere station envelope.
2026-04-23 18:43:18 -05:00

78 lines
2.6 KiB
Elixir
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

defmodule Microwaveprop.Workers.IonosphereFetchWorkerTest do
use Microwaveprop.DataCase, async: false
use Oban.Testing, repo: Microwaveprop.Repo
alias Microwaveprop.Ionosphere
alias Microwaveprop.Ionosphere.GiroClient
alias Microwaveprop.Ionosphere.Observation
alias Microwaveprop.Workers.IonosphereFetchWorker
@sample File.read!("test/fixtures/giro/mhj45_sample.txt")
describe "perform/1" do
test "pulls each configured station and upserts the parsed rows" do
Req.Test.stub(GiroClient, fn conn ->
assert conn.method == "GET"
params = Plug.Conn.fetch_query_params(conn).query_params
assert params["ursiCode"] in ~w(MHJ45 AL945)
Plug.Conn.resp(conn, 200, @sample)
end)
assert :ok = perform_job(IonosphereFetchWorker, %{})
# 25 observations per station × 2 stations = 50 rows (fixture has 25
# data lines; upserts go to each station code separately).
assert Repo.aggregate(Observation, :count, :id) == 50
assert Ionosphere.latest_observation("MHJ45")
assert Ionosphere.latest_observation("AL945")
end
test "survives a station's fetch error and still ingests the others" do
Req.Test.stub(GiroClient, fn conn ->
params = Plug.Conn.fetch_query_params(conn).query_params
if params["ursiCode"] == "MHJ45" do
Plug.Conn.resp(conn, 500, "boom")
else
Plug.Conn.resp(conn, 200, @sample)
end
end)
assert :ok = perform_job(IonosphereFetchWorker, %{})
# MHJ45 failed, AL945 ingested.
assert Ionosphere.latest_observation("MHJ45") == nil
assert Ionosphere.latest_observation("AL945")
end
test "tolerates an HTTP transport failure with :ok + no rows inserted" do
Req.Test.stub(GiroClient, fn conn ->
Req.Test.transport_error(conn, :timeout)
end)
assert :ok = perform_job(IonosphereFetchWorker, %{})
assert Repo.aggregate(Observation, :count, :id) == 0
end
end
describe "stations/0" do
test "exposes a non-empty list of CONUS ionosonde stations" do
stations = IonosphereFetchWorker.stations()
assert is_list(stations)
assert length(stations) >= 2
# Every station entry has the shape the fetcher expects, with a
# plausible CONUS lat/lon envelope.
for s <- stations do
assert is_binary(s.code)
assert is_binary(s.name)
assert is_float(s.lat) or is_integer(s.lat)
assert is_float(s.lon) or is_integer(s.lon)
assert s.lat > 20.0 and s.lat < 75.0
assert s.lon > -170.0 and s.lon < -60.0
end
end
end
end