The 1-hour valid_time filter inherited from /weather is wrong for HRDPS: the model publishes 4x/day with 3-4h publication latency and the chain step adds ~13 min on top, so the freshest data on disk is routinely 4-6h old. With the 1h cutoff in place, /weather-ca's timeline was empty whenever there wasn't an active chain step running, which left the JS hook with nothing to fetch. The sidebar already shows the selected valid_time prominently — users can see for themselves how stale the data is and don't need the page to hide it.
89 lines
3 KiB
Elixir
89 lines
3 KiB
Elixir
defmodule MicrowavepropWeb.WeatherCaMapLiveTest do
|
|
# async: false because we touch the shared scalar / profile dirs.
|
|
use MicrowavepropWeb.ConnCase, async: false
|
|
|
|
import Phoenix.LiveViewTest
|
|
|
|
alias Microwaveprop.Propagation.ProfilesFile
|
|
alias Microwaveprop.Weather.GridCache
|
|
alias Microwaveprop.Weather.ScalarFile
|
|
|
|
setup do
|
|
GridCache.clear()
|
|
|
|
on_exit(fn ->
|
|
GridCache.clear()
|
|
ProfilesFile.prune_older_than(~U[2099-12-31 23:59:59Z])
|
|
end)
|
|
|
|
:ok
|
|
end
|
|
|
|
test "mounts at /weather-ca with Canadian default viewport", %{conn: conn} do
|
|
{:ok, _lv, html} = live(conn, ~p"/weather-ca")
|
|
|
|
# Default viewport is centered roughly on central Canada at a low
|
|
# zoom — different from /weather's DFW@z7. The exact numbers are
|
|
# asserted so a routing accident (mounting WeatherMapLive at this
|
|
# path by mistake) is caught.
|
|
assert html =~ ~s(data-initial-lat="55.0")
|
|
assert html =~ ~s(data-initial-lon="-100.0")
|
|
assert html =~ ~s(data-initial-zoom="4")
|
|
end
|
|
|
|
test "renders the weather map element with data-source=hrdps", %{conn: conn} do
|
|
{:ok, _lv, html} = live(conn, ~p"/weather-ca")
|
|
|
|
# The JS hook reads data-source and appends &source=hrdps to its cell
|
|
# fetches. Without this attribute the page would silently fall back
|
|
# to HRRR-only reads and never show Canadian data.
|
|
assert html =~ ~s(data-source="hrdps")
|
|
end
|
|
|
|
test "viewport_changed event push_patches /weather-ca, not /weather", %{conn: conn} do
|
|
{:ok, lv, _html} = live(conn, ~p"/weather-ca")
|
|
|
|
render_hook(lv, "viewport_changed", %{"lat" => 60.0, "lon" => -110.0, "zoom" => 5})
|
|
|
|
assert_patch(lv, "/weather-ca?layer=temperature&lat=60.0&lon=-110.0&zoom=5")
|
|
end
|
|
|
|
test "select_layer push_patches a /weather-ca URL", %{conn: conn} do
|
|
{:ok, lv, _html} = live(conn, ~p"/weather-ca")
|
|
|
|
render_hook(lv, "select_layer", %{"layer" => "pwat"})
|
|
|
|
assert_patch(lv, "/weather-ca?layer=pwat&lat=55.0&lon=-100.0&zoom=4")
|
|
end
|
|
|
|
test "shows HRDPS valid_times even when several hours old (no 1h cutoff)", %{conn: conn} do
|
|
# HRDPS publishes 4x/day with ~3-4h latency, plus our chain step
|
|
# takes ~13 min. The 1-hour cutoff /weather uses would routinely
|
|
# leave /weather-ca empty between fresh chain steps. Hand-write a
|
|
# 4-hour-old HRDPS chunk and confirm it lands in the timeline.
|
|
now =
|
|
DateTime.utc_now()
|
|
|> DateTime.truncate(:second)
|
|
|> Map.put(:minute, 0)
|
|
|> Map.put(:second, 0)
|
|
|
|
stale_t = DateTime.add(now, -4 * 3600, :second)
|
|
hrdps_dir = ScalarFile.dir_for_hrdps(stale_t)
|
|
File.mkdir_p!(hrdps_dir)
|
|
|
|
payload =
|
|
Msgpax.pack!(
|
|
[%{"lat" => 53.0, "lon" => -60.0, "valid_time" => DateTime.to_iso8601(stale_t), "temperature" => 8.0}],
|
|
iodata: false
|
|
)
|
|
|
|
File.write!(Path.join(hrdps_dir, "10_-12.mp.gz"), :zlib.gzip(payload))
|
|
|
|
on_exit(fn -> File.rm_rf!(hrdps_dir) end)
|
|
|
|
{:ok, _lv, html} = live(conn, ~p"/weather-ca")
|
|
|
|
iso = DateTime.to_iso8601(stale_t)
|
|
assert html =~ iso, "4-hour-old HRDPS valid_time should appear in /weather-ca timeline"
|
|
end
|
|
end
|