From a8f85bf3ee199901c2ef612c234e18a99659951a Mon Sep 17 00:00:00 2001 From: Dotty Dotter Date: Wed, 6 May 2026 15:45:59 +0200 Subject: [PATCH] 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) --- tests/test_endpoints_smoke.py | 91 +++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/tests/test_endpoints_smoke.py b/tests/test_endpoints_smoke.py index 2cb7eda..547a03b 100644 --- a/tests/test_endpoints_smoke.py +++ b/tests/test_endpoints_smoke.py @@ -234,3 +234,94 @@ class TestAdminStandAuth: def test_api_unauthenticated_rejected(self): resp = client.get("/api/admin/stand") 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}"