mtg_python_deckbuilder/code/tests/test_diagnostics.py

173 lines
5.6 KiB
Python

import os
import importlib
import types
import pytest
from starlette.testclient import TestClient
from code.deck_builder.summary_telemetry import _reset_metrics_for_test, record_partner_summary
fastapi = pytest.importorskip("fastapi") # skip tests if FastAPI isn't installed
def load_app_with_env(**env: str) -> types.ModuleType:
for key in (
"SHOW_LOGS",
"SHOW_DIAGNOSTICS",
"SHOW_SETUP",
"SHOW_COMMANDERS",
"ENABLE_THEMES",
"ENABLE_PWA",
"ENABLE_PRESETS",
"APP_VERSION",
"THEME",
):
os.environ.pop(key, None)
for k, v in env.items():
os.environ[k] = v
import code.web.app as app_module
importlib.reload(app_module)
return app_module
def test_healthz_ok_and_request_id_header():
app_module = load_app_with_env()
client = TestClient(app_module.app)
r = client.get("/healthz")
assert r.status_code == 200
data = r.json()
assert data.get("status") in {"ok", "degraded"}
assert "uptime_seconds" in data
assert r.headers.get("X-Request-ID")
def test_404_renders_html_when_accept_html():
app_module = load_app_with_env()
client = TestClient(app_module.app)
r = client.get("/this-does-not-exist", headers={"Accept": "text/html"})
assert r.status_code == 404
body = r.text.lower()
assert "page not found" in body
assert "go home" in body
assert r.headers.get("X-Request-ID")
def test_htmx_http_exception_returns_json_with_request_id():
app_module = load_app_with_env(SHOW_DIAGNOSTICS="1")
client = TestClient(app_module.app)
r = client.get("/diagnostics/trigger-error", headers={"HX-Request": "true"})
assert r.status_code == 418
data = r.json()
assert data.get("error") is True
assert data.get("status") == 418
assert data.get("request_id")
assert r.headers.get("X-Request-ID")
def test_unhandled_exception_returns_500_json_with_request_id():
app_module = load_app_with_env(SHOW_DIAGNOSTICS="1")
# Configure client to not re-raise server exceptions so we can assert the 500 response
client = TestClient(app_module.app, raise_server_exceptions=False)
r = client.get("/diagnostics/trigger-error?kind=unhandled", headers={"HX-Request": "true"})
assert r.status_code == 500
data = r.json()
assert data.get("error") is True
assert data.get("status") == 500
assert data.get("request_id")
assert r.headers.get("X-Request-ID")
def test_status_sys_summary_and_flags():
app_module = load_app_with_env(
SHOW_LOGS="1",
SHOW_DIAGNOSTICS="1",
SHOW_SETUP="1",
SHOW_COMMANDERS="1",
ENABLE_THEMES="1",
ENABLE_PWA="1",
ENABLE_PRESETS="1",
APP_VERSION="testver",
THEME="dark",
)
client = TestClient(app_module.app)
r = client.get("/status/sys")
assert r.status_code == 200
data = r.json()
assert data.get("version") == "testver"
assert isinstance(data.get("uptime_seconds"), int)
assert isinstance(data.get("server_time_utc"), str)
flags = data.get("flags") or {}
assert flags.get("SHOW_LOGS") is True
assert flags.get("SHOW_DIAGNOSTICS") is True
assert flags.get("SHOW_SETUP") is True
assert flags.get("SHOW_COMMANDERS") is True
# Theme-related flags
assert flags.get("ENABLE_THEMES") is True
assert flags.get("ENABLE_PWA") is True
assert flags.get("ENABLE_PRESETS") is True
assert flags.get("DEFAULT_THEME") == "dark"
def test_commanders_nav_hidden_when_flag_disabled():
app_module = load_app_with_env(SHOW_COMMANDERS="0")
client = TestClient(app_module.app)
r = client.get("/")
assert r.status_code == 200
body = r.text
assert '<a href="/commanders"' not in body
def test_commanders_nav_visible_by_default():
app_module = load_app_with_env()
client = TestClient(app_module.app)
r = client.get("/")
assert r.status_code == 200
body = r.text
assert '<a href="/commanders"' in body
def test_partner_metrics_endpoint_reports_color_sources():
app_module = load_app_with_env(SHOW_DIAGNOSTICS="1")
_reset_metrics_for_test()
record_partner_summary(
{
"primary": "Tana, the Bloodsower",
"secondary": "Nadir Kraken",
"names": ["Tana, the Bloodsower", "Nadir Kraken"],
"partner_mode": "partner",
"combined": {
"partner_mode": "partner",
"color_identity": ["G", "U"],
"color_code": "GU",
"color_label": "Simic (GU)",
"color_sources": [
{"color": "G", "providers": [{"name": "Tana, the Bloodsower", "role": "primary"}]},
{"color": "U", "providers": [{"name": "Nadir Kraken", "role": "partner"}]},
],
"color_delta": {
"added": ["U"],
"removed": [],
"primary": ["G"],
"secondary": ["U"],
},
"secondary_role": "partner",
"secondary_role_label": "Partner commander",
},
}
)
client = TestClient(app_module.app)
resp = client.get("/status/partner_metrics")
assert resp.status_code == 200
payload = resp.json()
assert payload.get("ok") is True
metrics = payload.get("metrics") or {}
assert metrics.get("total_pairs", 0) >= 1
last = metrics.get("last_summary")
assert last is not None
sources = last.get("color_sources") or []
assert any(entry.get("color") == "G" for entry in sources)
assert any(
provider.get("role") == "partner"
for entry in sources
for provider in entry.get("providers", [])
)