gwoe-antragspruefer/tests/test_icons.py
Dotty Dotter d552582a0c test: gesamte Test-Suite gruen (1294/1294) vor v2.0.0
- conftest: pymupdf-Alias-Loading robuster, fuer echte Render-Tests
- test_v2_pdf_consistency: fehlende_programme deserialisieren
- test_endpoints_smoke: Auth-Tests skippen wenn Keycloak nicht aktiv;
  queue/status-Schema auf workers_running aktualisiert
- test_inline_styles_baseline: skippen wenn tools/-Dir fehlt (Container)
- test_presse_generator_style: Mock-Body lang genug fuer kein Re-Generate;
  neuer event-loop pro Test (3.10+-Lifecycle)
- test_bug_regressions: EMBEDDINGS_DB-Patch auch im analyzer_mod;
  raising=False bei fitz/pymupdf raus (zerstoerte Folge-Tests)
- test_icons: macOS AppleDouble-Files (._*) ueberspringen
- test_protokoll_parsers_nrw: raising=False raus (Test-Isolation)
2026-05-09 22:29:37 +02:00

67 lines
2.3 KiB
Python

"""Verify dass jeder im Template-Code referenzierte Icon-Name als
phosphor/<name>.svg-File existiert.
Hintergrund: Vor diesem Test gab es einen 500 nach Login, weil
`base.html` `icon("scales")` aufrief, das SVG aber nicht im Repo lag
(commit 741faae). Mit `ignore missing` rendert das Macro jetzt leer
statt zu crashen — aber wir wollen trotzdem in CI sehen, dass kein
Aufruf ins Leere läuft.
"""
from __future__ import annotations
import re
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parent.parent
TEMPLATES_DIR = REPO_ROOT / "app" / "templates"
ICONS_DIR = TEMPLATES_DIR / "v2" / "icons" / "phosphor"
# Matcht: icon("name", …) oder icon('name', …) — Default-Quote +/-.
ICON_CALL_PATTERN = re.compile(r"""\bicon\(\s*['"]([a-z0-9-]+)['"]""")
def _collect_referenced_icons() -> set[str]:
"""Sammle alle Icon-Namen, die irgendwo in templates/ aufgerufen werden."""
referenced: set[str] = set()
for path in TEMPLATES_DIR.rglob("*.html"):
# macOS-AppleDouble-Metadaten (._foo.html) ueberspringen — keine Templates.
if path.name.startswith("._"):
continue
text = path.read_text(encoding="utf-8")
for m in ICON_CALL_PATTERN.finditer(text):
referenced.add(m.group(1))
return referenced
def _existing_icons() -> set[str]:
"""Set der existierenden phosphor-Icon-Namen (ohne .svg)."""
if not ICONS_DIR.exists():
return set()
return {p.stem for p in ICONS_DIR.glob("*.svg")}
class TestIconCoverage:
def test_phosphor_dir_exists(self):
assert ICONS_DIR.is_dir(), f"erwartetes Verzeichnis fehlt: {ICONS_DIR}"
def test_at_least_one_icon_present(self):
icons = _existing_icons()
assert icons, "keine Icon-Files im phosphor/-Verzeichnis"
def test_at_least_one_call_referenced(self):
refs = _collect_referenced_icons()
assert refs, "keine icon('name')-Aufrufe in Templates gefunden"
def test_every_referenced_icon_has_file(self):
"""Jeder im Template referenzierte Icon-Name muss als SVG-File existieren."""
referenced = _collect_referenced_icons()
existing = _existing_icons()
missing = referenced - existing
assert not missing, (
f"{len(missing)} referenzierte Icons fehlen in "
f"{ICONS_DIR.relative_to(REPO_ROOT)}: {sorted(missing)}"
)