mtg_python_deckbuilder/code/tests/test_preview_export_endpoints.py

59 lines
2.6 KiB
Python
Raw Permalink Normal View History

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"