2026-08-28 21:49:05 -04:00
|
|
|
"""HUD load-time: no market 404 poll, deferred overlays, WS backoff, nginx snippet."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
|
HTML = (ROOT / "app/static/index.html").read_text()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_summarizer_dockerfile_copies_intel_modules():
|
|
|
|
|
df = (ROOT / "news/summerizer/Dockerfile").read_text()
|
|
|
|
|
assert "intel.py" in df
|
|
|
|
|
assert "nous_client.py" in df
|
|
|
|
|
|
|
|
|
|
|
2026-08-28 22:53:31 -04:00
|
|
|
def test_news_panel_pins_daily_recap():
|
|
|
|
|
assert "kind=daily_recap" in HTML
|
|
|
|
|
assert "DAILY RECAP" in HTML
|
|
|
|
|
|
|
|
|
|
|
2026-08-28 21:49:05 -04:00
|
|
|
def test_nginx_ws_snippet_has_upgrade_headers():
|
|
|
|
|
conf = (ROOT / "deploy/osint-ws.nginx.conf").read_text()
|
|
|
|
|
assert "proxy_http_version 1.1" in conf
|
|
|
|
|
assert "Upgrade" in conf
|
|
|
|
|
assert "Connection" in conf
|
|
|
|
|
assert "/ws/" in conf
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_market_ticker_does_not_poll_unwired_endpoint():
|
|
|
|
|
assert "setInterval(probeMarket" not in HTML
|
|
|
|
|
assert "initMarketTicker()" not in HTML or "probeMarket();" not in HTML.split("function initMarketTicker")[1][:400]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_startup_defers_nonessential_overlays():
|
|
|
|
|
init = HTML.split("function initMap")[1].split("function readMapPrefs")[0]
|
|
|
|
|
# Must not fire all four DB loads + live overlays in the same tick.
|
|
|
|
|
assert "setTimeout" in init or "requestAnimationFrame" in init
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_ws_reconnect_uses_backoff():
|
|
|
|
|
assert "setTimeout(connectLiveWs, 4000)" not in HTML
|
|
|
|
|
ws = HTML.split("function connectLiveWs")[1][:1200]
|
|
|
|
|
assert "backoff" in ws.lower() or "wsRetry" in ws or "wsDelay" in ws
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_check_health_treats_degraded_status():
|
|
|
|
|
fn = HTML.split("async function checkHealth")[1].split("/* ═══════════════ NAV")[0]
|
|
|
|
|
assert "degraded" in fn.lower() or "d.status" in fn
|
2026-08-29 14:12:02 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_chokepoint_presets_in_toolbar():
|
|
|
|
|
assert 'id="chokepoint-btns"' in HTML
|
|
|
|
|
assert 'id="chokepoint-select"' in HTML
|
|
|
|
|
assert "loadChokepoints()" in HTML
|
|
|
|
|
assert "/api/map/chokepoints" in HTML
|
|
|
|
|
assert "function applyChokepoint" in HTML
|
|
|
|
|
for name in ("Hormuz", "Bab el-Mandeb", "Suez", "Malacca", "Taiwan"):
|
|
|
|
|
assert name in HTML
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_chokepoint_skips_aisstream_subscribe_outside_conus():
|
|
|
|
|
load = HTML.split("async function loadVessels")[1].split("async function toggleStorms")[0]
|
|
|
|
|
assert "intersectsConus()" in load
|
|
|
|
|
assert "api/vessels/subscribe" in load
|
|
|
|
|
assert "src=${encodeURIComponent(vesselSrcPref)}" in load or "&src=" in load
|
|
|
|
|
apply = HTML.split("function applyChokepoint")[1].split("function currentBBox")[0]
|
|
|
|
|
assert "vesselapi" in apply
|
|
|
|
|
assert "lp-vessels-on" in apply
|
|
|
|
|
assert "lp-sentinel-on" in apply
|
|
|
|
|
assert "map.setView" in apply
|
|
|
|
|
assert "minlat,minlon,maxlat,maxlon" in HTML.split("function chokepointLeafletBounds")[1][:400]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_phone_chokepoints_use_select_not_buttons():
|
|
|
|
|
mobile = HTML.split("@media (max-width: 820px)")[1].split("@media (prefers-reduced-motion")[0]
|
|
|
|
|
assert "#chokepoint-select { display: block; }" in mobile
|
|
|
|
|
assert ".chokepoint-btns { display: none; }" in mobile or "#chokepoint-label, .chokepoint-btns { display: none; }" in mobile
|
2026-08-29 14:20:04 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_dark_hull_v1_sar_ais_candidate_note():
|
|
|
|
|
sar = HTML.split('id="sentinel-1-sar"')[1].split('class="lp-layer"')[0]
|
|
|
|
|
assert "SAR + AIS:" in sar
|
|
|
|
|
assert "candidate" in sar
|
|
|
|
|
assert "not a detection" in sar
|
|
|
|
|
assert sar.count('class="lp-note"') >= 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_hormuz_tap_enables_sar_and_vesselapi_src():
|
|
|
|
|
apply = HTML.split("function applyChokepoint")[1].split("function currentBBox")[0]
|
|
|
|
|
assert "p.vesselapi ? 'vesselapi' : ''" in apply
|
|
|
|
|
assert "vChk.checked = true" in apply
|
|
|
|
|
assert "vesselsOn = true" in apply
|
|
|
|
|
assert "p.id === 'hormuz' || p.vesselapi" in apply
|
|
|
|
|
assert "sChk.checked = true" in apply
|
|
|
|
|
assert "sentinelOn = true" in apply
|
|
|
|
|
assert "if (vesselsOn) loadVessels();" in apply
|
|
|
|
|
assert "if (sentinelOn) loadSentinel1();" in apply
|
|
|
|
|
load = HTML.split("async function loadVessels")[1].split("async function toggleStorms")[0]
|
|
|
|
|
assert "&src=${encodeURIComponent(vesselSrcPref)}" in load or "src=${encodeURIComponent(vesselSrcPref)}" in load
|