mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-04-29 22:37:49 +02:00
fc9eff865e
New features: - In-app auto-updater with confirmation dialog, manual download fallback, restart polling, and protected file safety net - Ship layers split into 4 independent toggles (Military/Carriers, Cargo/Tankers, Civilian, Cruise/Passenger) with per-category counts - Stable entity IDs using MMSI/callsign instead of volatile array indices - Dismissible threat alert bubbles (session-scoped, survives data refresh) Performance: - GDELT title fetching is now non-blocking (background enrichment) - Removed duplicate startup fetch jobs - Docker healthcheck start_period 15s → 90s Bug fixes: - Removed fake intelligence assessment generator (OSINT-only policy) - Fixed carrier tracker GDELT 429/TypeError crash - Fixed ETag collision (full payload hash) - Added concurrent /api/refresh guard Contributors: @imqdcr (ship split + stable IDs), @csysp (dismissible alerts, PR #48) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Former-commit-id: a2c4c67da54345393f70a9b33b52e7e4fd6c049f
115 lines
3.7 KiB
Python
115 lines
3.7 KiB
Python
"""Smoke tests for all API endpoints — verifies routes exist and return valid responses."""
|
|
import pytest
|
|
|
|
|
|
class TestHealthEndpoint:
|
|
def test_health_returns_200(self, client):
|
|
r = client.get("/api/health")
|
|
assert r.status_code == 200
|
|
data = r.json()
|
|
assert data["status"] == "ok"
|
|
assert "sources" in data
|
|
assert "freshness" in data
|
|
|
|
def test_health_has_uptime(self, client):
|
|
r = client.get("/api/health")
|
|
data = r.json()
|
|
assert "uptime_seconds" in data
|
|
assert isinstance(data["uptime_seconds"], (int, float))
|
|
|
|
|
|
class TestLiveDataEndpoints:
|
|
def test_live_data_returns_200(self, client):
|
|
r = client.get("/api/live-data")
|
|
assert r.status_code == 200
|
|
|
|
def test_live_data_fast_returns_200_or_304(self, client):
|
|
r = client.get("/api/live-data/fast")
|
|
assert r.status_code in (200, 304)
|
|
if r.status_code == 200:
|
|
data = r.json()
|
|
assert "freshness" in data
|
|
|
|
def test_live_data_slow_returns_200_or_304(self, client):
|
|
r = client.get("/api/live-data/slow")
|
|
assert r.status_code in (200, 304)
|
|
if r.status_code == 200:
|
|
data = r.json()
|
|
assert "freshness" in data
|
|
|
|
def test_fast_has_expected_keys(self, client):
|
|
r = client.get("/api/live-data/fast")
|
|
if r.status_code == 200:
|
|
data = r.json()
|
|
for key in ("commercial_flights", "military_flights", "ships", "satellites"):
|
|
assert key in data, f"Missing key: {key}"
|
|
|
|
def test_slow_has_expected_keys(self, client):
|
|
r = client.get("/api/live-data/slow")
|
|
if r.status_code == 200:
|
|
data = r.json()
|
|
for key in ("news", "stocks", "weather", "earthquakes"):
|
|
assert key in data, f"Missing key: {key}"
|
|
|
|
|
|
class TestDebugEndpoint:
|
|
def test_debug_latest_returns_list(self, client):
|
|
r = client.get("/api/debug-latest")
|
|
assert r.status_code == 200
|
|
data = r.json()
|
|
assert isinstance(data, list)
|
|
|
|
|
|
class TestSettingsEndpoints:
|
|
def test_get_api_keys(self, client):
|
|
r = client.get("/api/settings/api-keys")
|
|
assert r.status_code == 200
|
|
data = r.json()
|
|
assert isinstance(data, list)
|
|
|
|
def test_get_news_feeds(self, client):
|
|
r = client.get("/api/settings/news-feeds")
|
|
assert r.status_code == 200
|
|
data = r.json()
|
|
assert isinstance(data, list)
|
|
|
|
|
|
class TestRadioEndpoints:
|
|
def test_radio_top_returns_200(self, client):
|
|
r = client.get("/api/radio/top")
|
|
assert r.status_code == 200
|
|
|
|
def test_radio_openmhz_systems(self, client):
|
|
r = client.get("/api/radio/openmhz/systems")
|
|
assert r.status_code == 200
|
|
|
|
|
|
class TestQueryValidation:
|
|
def test_region_dossier_rejects_invalid_lat(self, client):
|
|
r = client.get("/api/region-dossier?lat=999&lng=0")
|
|
assert r.status_code == 422
|
|
|
|
def test_region_dossier_rejects_invalid_lng(self, client):
|
|
r = client.get("/api/region-dossier?lat=0&lng=999")
|
|
assert r.status_code == 422
|
|
|
|
def test_sentinel_rejects_invalid_coords(self, client):
|
|
r = client.get("/api/sentinel2/search?lat=-100&lng=0")
|
|
assert r.status_code == 422
|
|
|
|
def test_radio_nearest_rejects_invalid_lat(self, client):
|
|
r = client.get("/api/radio/nearest?lat=91&lng=0")
|
|
assert r.status_code == 422
|
|
|
|
|
|
class TestETagBehavior:
|
|
def test_fast_returns_etag_header(self, client):
|
|
r = client.get("/api/live-data/fast")
|
|
if r.status_code == 200:
|
|
assert "etag" in r.headers
|
|
|
|
def test_slow_returns_etag_header(self, client):
|
|
r = client.get("/api/live-data/slow")
|
|
if r.status_code == 200:
|
|
assert "etag" in r.headers
|