Store surface observations (ASOS) and upper-air soundings (RAOB) alongside QSOs for atmospheric propagation correlation. Three new tables: weather_stations, surface_observations, and soundings with JSONB profiles and pre-computed derived parameters (refractivity, gradients, duct detection, stability indices). Includes IEM API client for historical data import and import script seeded with 95 ASOS + 9 sounding stations from PropCast coverage area.
79 lines
2.4 KiB
Elixir
79 lines
2.4 KiB
Elixir
defmodule Microwaveprop.Weather.SurfaceObservationTest do
|
|
use Microwaveprop.DataCase, async: true
|
|
|
|
alias Microwaveprop.Weather.Station
|
|
alias Microwaveprop.Weather.SurfaceObservation
|
|
|
|
defp create_station do
|
|
%Station{}
|
|
|> Station.changeset(%{
|
|
station_code: "KDFW",
|
|
station_type: "asos",
|
|
name: "Dallas/Fort Worth International",
|
|
lat: 32.8998,
|
|
lon: -97.0403
|
|
})
|
|
|> Repo.insert!()
|
|
end
|
|
|
|
@valid_obs_attrs %{
|
|
observed_at: ~U[2026-03-28 18:00:00Z],
|
|
temp_f: 75.0,
|
|
dewpoint_f: 55.0,
|
|
relative_humidity: 49.0,
|
|
wind_speed_kts: 12.0,
|
|
wind_direction_deg: 180,
|
|
sea_level_pressure_mb: 1013.25,
|
|
altimeter_setting: 29.92,
|
|
sky_condition: "SCT"
|
|
}
|
|
|
|
describe "changeset/2" do
|
|
test "valid attributes with station_id" do
|
|
station = create_station()
|
|
attrs = Map.put(@valid_obs_attrs, :station_id, station.id)
|
|
changeset = SurfaceObservation.changeset(%SurfaceObservation{}, attrs)
|
|
assert changeset.valid?
|
|
end
|
|
|
|
test "requires station_id and observed_at" do
|
|
changeset = SurfaceObservation.changeset(%SurfaceObservation{}, %{})
|
|
|
|
assert %{
|
|
station_id: ["can't be blank"],
|
|
observed_at: ["can't be blank"]
|
|
} = errors_on(changeset)
|
|
end
|
|
|
|
test "all weather fields are optional" do
|
|
station = create_station()
|
|
|
|
attrs = %{
|
|
station_id: station.id,
|
|
observed_at: ~U[2026-03-28 18:00:00Z]
|
|
}
|
|
|
|
changeset = SurfaceObservation.changeset(%SurfaceObservation{}, attrs)
|
|
assert changeset.valid?
|
|
end
|
|
|
|
test "persists to the database" do
|
|
station = create_station()
|
|
attrs = Map.put(@valid_obs_attrs, :station_id, station.id)
|
|
changeset = SurfaceObservation.changeset(%SurfaceObservation{}, attrs)
|
|
assert {:ok, obs} = Repo.insert(changeset)
|
|
assert obs.temp_f == 75.0
|
|
assert obs.sky_condition == "SCT"
|
|
assert obs.station_id == station.id
|
|
end
|
|
|
|
test "enforces unique station_id + observed_at" do
|
|
station = create_station()
|
|
attrs = Map.put(@valid_obs_attrs, :station_id, station.id)
|
|
|
|
assert {:ok, _} = %SurfaceObservation{} |> SurfaceObservation.changeset(attrs) |> Repo.insert()
|
|
assert {:error, changeset} = %SurfaceObservation{} |> SurfaceObservation.changeset(attrs) |> Repo.insert()
|
|
assert %{station_id: ["has already been taken"]} = errors_on(changeset)
|
|
end
|
|
end
|
|
end
|