"""Tests for wahlprogramme.py — registry consistency + file existence.""" from app.wahlprogramme import ( WAHLPROGRAMME, REFERENZEN_PATH, get_wahlprogramm, parteien_mit_wahlprogramm, ) # ───────────────────────────────────────────────────────────────────────────── # Registry consistency # ───────────────────────────────────────────────────────────────────────────── class TestRegistryStructure: def test_active_bundeslaender_present(self): for code in ["NRW", "LSA", "MV", "BE"]: assert code in WAHLPROGRAMME, f"missing wahlprogramme entry for {code}" def test_each_entry_has_required_keys(self): required = {"file", "titel", "partei", "jahr", "seiten"} for bl, parteien in WAHLPROGRAMME.items(): for partei, info in parteien.items(): missing = required - set(info.keys()) assert not missing, f"{bl}/{partei} missing keys: {missing}" def test_jahr_is_integer(self): for bl, parteien in WAHLPROGRAMME.items(): for partei, info in parteien.items(): assert isinstance(info["jahr"], int), f"{bl}/{partei} jahr not int" def test_seiten_is_positive_integer(self): for bl, parteien in WAHLPROGRAMME.items(): for partei, info in parteien.items(): assert isinstance(info["seiten"], int) assert info["seiten"] > 0 def test_file_extension_is_pdf(self): for bl, parteien in WAHLPROGRAMME.items(): for partei, info in parteien.items(): assert info["file"].endswith(".pdf") # ───────────────────────────────────────────────────────────────────────────── # File existence — every registered file must exist on disk # ───────────────────────────────────────────────────────────────────────────── class TestFileExistence: """Catches typos in the file field that would silently break embedding indexing or PDF download links.""" def test_every_registered_pdf_exists(self): missing = [] for bl, parteien in WAHLPROGRAMME.items(): for partei, info in parteien.items(): path = REFERENZEN_PATH / info["file"] if not path.exists(): missing.append(f"{bl}/{partei}: {info['file']}") assert not missing, "missing PDFs:\n " + "\n ".join(missing) # ───────────────────────────────────────────────────────────────────────────── # Lookup helpers # ───────────────────────────────────────────────────────────────────────────── class TestGetWahlprogramm: def test_returns_dict_for_known_combination(self): info = get_wahlprogramm("MV", "CDU") assert info is not None assert info["partei"] == "CDU Mecklenburg-Vorpommern" def test_returns_none_for_unknown_bundesland(self): assert get_wahlprogramm("XX", "CDU") is None def test_returns_none_for_unknown_partei(self): assert get_wahlprogramm("NRW", "BSW") is None class TestParteienMitWahlprogramm: def test_nrw_has_five_parteien(self): parteien = parteien_mit_wahlprogramm("NRW") assert len(parteien) == 5 assert set(parteien) == {"CDU", "SPD", "GRÜNE", "FDP", "AfD"} def test_mv_has_six_parteien(self): parteien = parteien_mit_wahlprogramm("MV") assert set(parteien) == {"CDU", "SPD", "GRÜNE", "FDP", "AfD", "LINKE"} def test_be_has_five_parteien(self): parteien = parteien_mit_wahlprogramm("BE") assert set(parteien) == {"CDU", "SPD", "GRÜNE", "LINKE", "AfD"} def test_unknown_bundesland_empty_list(self): assert parteien_mit_wahlprogramm("XX") == [] # ───────────────────────────────────────────────────────────────────────────── # embeddings.PROGRAMME consistency cross-check # ───────────────────────────────────────────────────────────────────────────── class TestEmbeddingsRegistryConsistency: """Every entry in WAHLPROGRAMME must also exist in embeddings.PROGRAMME so the indexer can find it. Mismatch is the kind of bug a manual smoke misses but would show up during indexing.""" def test_every_wahlprogramm_has_embeddings_entry(self): from app.embeddings import PROGRAMME # Build expected programm_id from filename: "cdu-mv-2021.pdf" → "cdu-mv-2021" missing = [] for bl, parteien in WAHLPROGRAMME.items(): for partei, info in parteien.items(): pid = info["file"].rsplit(".", 1)[0] if pid not in PROGRAMME: missing.append(f"{bl}/{partei} → {pid}") assert not missing, ( "WAHLPROGRAMME entries missing in embeddings.PROGRAMME:\n " + "\n ".join(missing) )