prop/test/microwaveprop/ionosphere/giro_client_test.exs
Graham McIntire 33e2ccf51a
Some checks failed
Build base image / Build and push base image (push) Has been cancelled
Build and Push / Build CI test image (push) Has been cancelled
Build and Push / Build and Push Docker Image (push) Has been cancelled
fix: remove TLS verify_none, validate recovered map state, normalize PromEx transport tags
- giro_client: remove verify: :verify_none, default to OTP :verify_peer
- map_live: validate recovered_band against BandConfig and recovered_time
  against time_in_window?/2 to prevent stale-state breakage
- prom_ex: local fork of Plugins.Phoenix that normalizes transport tag
  values to prevent telemetry_metrics_prometheus_core dropping series
2026-08-06 17:04:15 -05:00

69 lines
2.4 KiB
Elixir

defmodule Microwaveprop.Ionosphere.GiroClientTest do
use ExUnit.Case, async: true
alias Microwaveprop.Ionosphere.GiroClient
describe "parse_tabular/1" do
test "decodes the real Millstone Hill fixture into observation maps" do
body = File.read!("test/fixtures/giro/mhj45_sample.txt")
assert {:ok, rows} = GiroClient.parse_tabular(body)
# The fixture is 2026-04-15 16:00 → 19:00 UTC at 7.5-minute cadence,
# so 25 observations.
assert Enum.count_until(rows, 26) == 25
first = hd(rows)
assert first.valid_time == ~U[2026-04-15 16:00:00Z]
assert first.confidence_score == 60
assert_in_delta first.fo_f2_mhz, 6.856, 0.001
assert_in_delta first.mufd_mhz, 23.63, 0.001
# foEs was missing ("---") at 16:00.
assert first.fo_es_mhz == nil
assert_in_delta first.fo_e_mhz, 3.50, 0.001
assert_in_delta first.hm_f2_km, 217.2, 0.1
# 16:07:30 has foEs == 3.42.
second = Enum.at(rows, 1)
assert second.valid_time == ~U[2026-04-15 16:07:30Z]
assert_in_delta second.fo_es_mhz, 3.42, 0.001
last = List.last(rows)
assert last.valid_time == ~U[2026-04-15 19:00:00Z]
assert_in_delta last.fo_f2_mhz, 7.400, 0.001
end
test "returns {:ok, []} for a body with only the header" do
body = """
# Global Ionospheric Radio Observatory
# Location: GEO 42.6N 288.5E, URSI-Code MHJ45 MILLSTONE HILL
#
#Time CS foF2 QD MUFD QD foEs QD foE QD hmF2 QD
"""
assert {:ok, []} = GiroClient.parse_tabular(body)
end
test "returns {:error, :no_header} when the column header is missing" do
body = """
# some junk
2026-04-15T18:00:00.000Z 80 7.113 // 23.00 //
"""
assert {:error, :no_header} = GiroClient.parse_tabular(body)
end
test "skips data lines whose token count doesn't match the header" do
# Header declares 5 value columns (10 tokens after time+CS) but the
# data row is truncated. Should be skipped rather than crashing.
body = """
#Time CS foF2 QD MUFD QD foEs QD foE QD hmF2 QD
2026-04-15T18:00:00.000Z 80 7.113 //
2026-04-15T18:07:30.000Z 80 7.088 // 22.76 // 3.35 // 3.13 // 246.0 //
"""
assert {:ok, [row]} = GiroClient.parse_tabular(body)
assert row.valid_time == ~U[2026-04-15 18:07:30Z]
end
end
end