test: 11 weitere Smoketests fuer Stimmverhalten-Endpoints
Smoketests fuer alle 7 Stimmverhalten-Aggregat-Endpoints (stimm-index, heuchelei, empfehlungs-konsistenz, pro-wert, cross-bl, zeitreihe) plus zwei CSV-Tests (Header-Spalten + konsistente Datenzeilen-Spaltenzahl). Refs: ADR 0010 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9498ca4b97
commit
a8f85bf3ee
@ -234,3 +234,94 @@ class TestAdminStandAuth:
|
|||||||
def test_api_unauthenticated_rejected(self):
|
def test_api_unauthenticated_rejected(self):
|
||||||
resp = client.get("/api/admin/stand")
|
resp = client.get("/api/admin/stand")
|
||||||
assert resp.status_code in (401, 403, 307, 302)
|
assert resp.status_code in (401, 403, 307, 302)
|
||||||
|
|
||||||
|
|
||||||
|
class TestStimmverhaltenAggregateEndpoints:
|
||||||
|
"""Die 7 Stimmverhalten-Aggregat-Endpoints liefern strukturierte JSONs (siehe ADR 0010)."""
|
||||||
|
|
||||||
|
def test_stimm_index_returns_fraktionen(self):
|
||||||
|
resp = client.get("/api/auswertungen/stimm-index")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
data = resp.json()
|
||||||
|
assert "fraktionen" in data
|
||||||
|
assert isinstance(data["fraktionen"], list)
|
||||||
|
assert "n_assessments_matched" in data
|
||||||
|
|
||||||
|
def test_stimm_index_min_n_filter(self):
|
||||||
|
resp = client.get("/api/auswertungen/stimm-index?min_n=1")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
data = resp.json()
|
||||||
|
assert data["filter"]["min_n"] == 1
|
||||||
|
|
||||||
|
def test_stimm_index_exclude_antragsteller_default(self):
|
||||||
|
"""Default `exclude_antragsteller=True`."""
|
||||||
|
resp = client.get("/api/auswertungen/stimm-index")
|
||||||
|
data = resp.json()
|
||||||
|
assert data["filter"]["exclude_antragsteller"] in (True, "true", 1)
|
||||||
|
|
||||||
|
def test_heuchelei_returns_fraktionen(self):
|
||||||
|
resp = client.get("/api/auswertungen/heuchelei")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
data = resp.json()
|
||||||
|
assert "fraktionen" in data
|
||||||
|
|
||||||
|
def test_empfehlungs_konsistenz(self):
|
||||||
|
resp = client.get("/api/auswertungen/empfehlungs-konsistenz")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
data = resp.json()
|
||||||
|
assert "fraktionen" in data or "items" in data
|
||||||
|
|
||||||
|
def test_stimm_index_pro_wert_5_werte(self):
|
||||||
|
resp = client.get("/api/auswertungen/stimm-index-pro-wert")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
data = resp.json()
|
||||||
|
assert "werte" in data
|
||||||
|
# 5 GWÖ-Werte: Würde, Solidarität, Nachhaltigkeit, Gerechtigkeit, Demokratie
|
||||||
|
assert len(data["werte"]) == 5
|
||||||
|
|
||||||
|
def test_stimm_index_cross_bl(self):
|
||||||
|
resp = client.get("/api/auswertungen/stimm-index-cross-bl")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
data = resp.json()
|
||||||
|
assert "fraktionen" in data
|
||||||
|
assert "bundeslaender" in data
|
||||||
|
assert "cells" in data
|
||||||
|
|
||||||
|
def test_stimm_index_zeitreihe(self):
|
||||||
|
resp = client.get("/api/auswertungen/stimm-index-zeitreihe")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
data = resp.json()
|
||||||
|
# Erwartete Felder: buckets (Zeit-Achse), fraktionen, series
|
||||||
|
assert "buckets" in data
|
||||||
|
assert "fraktionen" in data
|
||||||
|
assert "series" in data
|
||||||
|
|
||||||
|
|
||||||
|
class TestStimmverhaltenCsvExport:
|
||||||
|
"""CSV-Export Long-Format aus #168."""
|
||||||
|
|
||||||
|
def test_csv_returns_text(self):
|
||||||
|
resp = client.get("/api/auswertungen/stimmverhalten.csv")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
ctype = resp.headers.get("content-type", "")
|
||||||
|
assert "text/csv" in ctype or "text/plain" in ctype
|
||||||
|
|
||||||
|
def test_csv_has_header_row(self):
|
||||||
|
resp = client.get("/api/auswertungen/stimmverhalten.csv")
|
||||||
|
body = resp.text
|
||||||
|
# Header-Zeile mit den erwarteten Long-Format-Spalten
|
||||||
|
first_line = body.split("\n", 1)[0]
|
||||||
|
# Mindestens drei Pflicht-Spalten erwartet — Partei statt Fraktion in CSV
|
||||||
|
for required in ("drucksache", "bundesland", "partei", "vote"):
|
||||||
|
assert required in first_line, f"Spalte {required!r} fehlt im Header: {first_line!r}"
|
||||||
|
|
||||||
|
def test_csv_data_rows_have_consistent_columns(self):
|
||||||
|
"""Datenzeilen haben gleiche Spalten-Anzahl wie der Header."""
|
||||||
|
resp = client.get("/api/auswertungen/stimmverhalten.csv")
|
||||||
|
body = resp.text.strip()
|
||||||
|
if not body:
|
||||||
|
pytest.skip("kein CSV-Body — DB enthält evtl. keine Vote-Matches")
|
||||||
|
lines = body.split("\n")
|
||||||
|
n_cols = lines[0].count(",") + 1
|
||||||
|
for line in lines[1:6]: # Samples
|
||||||
|
assert line.count(",") + 1 == n_cols, f"Spaltenzahl-Mismatch: {line!r}"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user