- Add jump_credo_checks ~> 0.4 with all 20 checks enabled - Fix all standard Credo issues: 139 @spec (113 done, 26 remain), 4 refactoring, 3 alias usage, 9 System.cmd env, 5 unsafe_to_atom, 2 max line length, 9 assert_receive timeout - Fix 170+ jump_credo_checks warnings: - 117 TopLevelAliasImportRequire: move nested alias/import to module top - 32 UseObanProWorker: switch to Oban.Pro.Worker - 4 DoctestIExExamples: add doctests / create test file - ~20 WeakAssertion: strengthen type-check assertions - Various ConditionalAssertion, AssertReceiveTimeout fixes - Exclude vendor/ from Credo analysis - Remaining: 175 warnings (mostly opinionated WeakAssertion, AvoidSocketAssignsInTest), 26 @spec annotations
110 lines
3.7 KiB
Elixir
110 lines
3.7 KiB
Elixir
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 stations != []
|
||
|
||
# Every station entry has the shape the fetcher expects, with a
|
||
# plausible CONUS lat/lon envelope.
|
||
for s <- stations do
|
||
assert byte_size(s.code) > 0
|
||
assert byte_size(s.name) > 0
|
||
assert is_float(s.lat)
|
||
assert is_float(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
|
||
|
||
describe "perform/1 additional HTTP branches" do
|
||
test "tolerates an HTTP 404 with :ok and zero rows inserted" do
|
||
# 404 is returned by GIRO for stations with no data in the window.
|
||
# The worker should treat it as a per-station no-op and return :ok.
|
||
Req.Test.stub(GiroClient, fn conn ->
|
||
Plug.Conn.send_resp(conn, 404, "not found")
|
||
end)
|
||
|
||
assert :ok = perform_job(IonosphereFetchWorker, %{})
|
||
assert Repo.aggregate(Observation, :count, :id) == 0
|
||
end
|
||
|
||
test "tolerates a non-tabular response body gracefully" do
|
||
# A body that doesn't match the expected comment/columns format
|
||
# should parse to zero rows — no crash, no inserts.
|
||
Req.Test.stub(GiroClient, fn conn ->
|
||
Plug.Conn.resp(conn, 200, "not a tabular response at all")
|
||
end)
|
||
|
||
assert :ok = perform_job(IonosphereFetchWorker, %{})
|
||
assert Repo.aggregate(Observation, :count, :id) == 0
|
||
end
|
||
|
||
test "tolerates an empty-body 200 response" do
|
||
Req.Test.stub(GiroClient, fn conn ->
|
||
Plug.Conn.resp(conn, 200, "")
|
||
end)
|
||
|
||
assert :ok = perform_job(IonosphereFetchWorker, %{})
|
||
assert Repo.aggregate(Observation, :count, :id) == 0
|
||
end
|
||
end
|
||
end
|