mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2025-12-17 08:00:13 +01:00
feat(web): Core Refactor Phase A — extract sampling and cache modules; add adaptive TTL + eviction heuristics, Redis PoC, and metrics wiring. Tests added for TTL, eviction, exports, splash-adaptive, card index, and service worker. Docs+roadmap updated.
This commit is contained in:
parent
c4a7fc48ea
commit
a029d430c5
49 changed files with 3889 additions and 701 deletions
58
code/tests/test_preview_export_endpoints.py
Normal file
58
code/tests/test_preview_export_endpoints.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
from typing import Set
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from code.web.app import app # FastAPI instance
|
||||
from code.web.services.theme_catalog_loader import load_index
|
||||
|
||||
|
||||
def _first_theme_slug() -> str:
|
||||
idx = load_index()
|
||||
# Deterministic ordering for test stability
|
||||
return sorted(idx.slug_to_entry.keys())[0]
|
||||
|
||||
|
||||
def test_preview_export_json_and_csv_curated_only_round_trip():
|
||||
slug = _first_theme_slug()
|
||||
client = TestClient(app)
|
||||
|
||||
# JSON full sample
|
||||
r = client.get(f"/themes/preview/{slug}/export.json", params={"curated_only": 0, "limit": 12})
|
||||
assert r.status_code == 200, r.text
|
||||
data = r.json()
|
||||
assert data["ok"] is True
|
||||
assert data["theme_id"] == slug
|
||||
assert data["count"] == len(data["items"]) <= 12 # noqa: SIM300
|
||||
required_keys_sampled = {"name", "roles", "score", "rarity", "mana_cost", "color_identity_list", "pip_colors"}
|
||||
sampled_role_set = {"payoff", "enabler", "support", "wildcard"}
|
||||
assert data["items"], "expected non-empty preview sample"
|
||||
for item in data["items"]:
|
||||
roles = set(item.get("roles") or [])
|
||||
# Curated examples & synthetic placeholders don't currently carry full card DB fields
|
||||
if roles.intersection(sampled_role_set):
|
||||
assert required_keys_sampled.issubset(item.keys()), f"sampled card missing expected fields: {item}"
|
||||
else:
|
||||
assert {"name", "roles", "score"}.issubset(item.keys())
|
||||
|
||||
# JSON curated_only variant: ensure only curated/synthetic roles remain
|
||||
r2 = client.get(f"/themes/preview/{slug}/export.json", params={"curated_only": 1, "limit": 12})
|
||||
assert r2.status_code == 200, r2.text
|
||||
curated = r2.json()
|
||||
curated_roles_allowed: Set[str] = {"example", "curated_synergy", "synthetic"}
|
||||
for item in curated["items"]:
|
||||
roles = set(item.get("roles") or [])
|
||||
assert roles, "item missing roles"
|
||||
assert roles.issubset(curated_roles_allowed), f"unexpected sampled role present: {roles}"
|
||||
|
||||
# CSV export header stability + curated_only path
|
||||
r3 = client.get(f"/themes/preview/{slug}/export.csv", params={"curated_only": 1, "limit": 12})
|
||||
assert r3.status_code == 200, r3.text
|
||||
text = r3.text.splitlines()
|
||||
assert text, "empty CSV response"
|
||||
header = text[0].strip()
|
||||
assert header == "name,roles,score,rarity,mana_cost,color_identity_list,pip_colors,reasons,tags"
|
||||
# Basic sanity: curated_only CSV should not contain a sampled role token
|
||||
sampled_role_tokens = {"payoff", "enabler", "support", "wildcard"}
|
||||
body = "\n".join(text[1:])
|
||||
for tok in sampled_role_tokens:
|
||||
assert f";{tok}" not in body, f"sampled role {tok} leaked into curated_only CSV"
|
||||
Loading…
Add table
Add a link
Reference in a new issue