"""Cross-Browser-Befunde (deterministische Matrix-Sicht, Phase 4). Sichert die Inkonsistenz-Erkennung ZWISCHEN Engines + die Einordnung, dass Browser-Tracking-Schutz (Safari/ITP, Brave/Shields, Firefox/ETP) Verstöße clientseitig maskiert (kein Compliance-Beleg).""" from compliance.services.browser_cross_finding import build_cross_findings def _row(pid, label, engine, *, before=0, reject_ok=True, impressum=True, dse=True, with_summary=True, track_before=0): if not with_summary: return {"profile_id": pid, "label": label, "engine": engine, "summary": None, "error": "launch failed"} return { "profile_id": pid, "label": label, "engine": engine, "summary": { "cookies_before_consent": before, "cookies_after_reject": 0 if reject_ok else 2, "reject_respected": reject_ok, "surface": {"has_impressum_link": impressum, "has_dse_link": dse}, # before_consent = nicht-essentielles Tracking vor Consent (das # rechtlich relevante Signal, NICHT die Cookie-Rohzahl `before`). "violations": {"before_consent": track_before}, }, } def _titles(findings): return " | ".join(f["title"] for f in findings) def test_empty_matrix(): assert build_cross_findings(None) == [] assert build_cross_findings({"browser_matrix": []}) == [] def test_tracking_before_consent_in_all_engines_high(): # Nicht-essentielles Tracking vor Consent (track_before>0) in allen Engines. m = {"browser_matrix": [ _row("chromium-headed-de", "Chromium", "blink", before=5, track_before=2), _row("firefox-headed-de", "Firefox", "gecko", before=3, track_before=1), ]} f = build_cross_findings(m) hit = [x for x in f if "Tracking vor der Einwilligung — in allen" in x["title"]] assert hit and hit[0]["severity"] == "HIGH" assert "§ 25 Abs. 2" in hit[0]["detail"] # essentielle Cookies ausgenommen def test_cookies_before_consent_without_tracking_is_no_finding(): # KERN-REGRESSION (User-Frage): Cookies vor Consent vorhanden, aber KEIN # Tracking (z.B. nur das Consent-Cookie selbst) → KEIN Verstoß-Befund. m = {"browser_matrix": [ _row("chromium-headed-de", "Chromium", "blink", before=5, track_before=0), _row("firefox-headed-de", "Firefox", "gecko", before=4, track_before=0), ]} f = build_cross_findings(m) assert [x for x in f if "Tracking vor" in x["title"]] == [] def test_tracking_before_consent_inconsistent_flags_browser_protection(): # Chrome (nachgiebig) lässt Tracker vor Consent, Safari/WebKit (ITP) nicht. m = {"browser_matrix": [ _row("chrome-channel-desktop-de", "Chrome", "blink", before=4, track_before=3), _row("webkit-headed-de", "Safari/WebKit", "webkit", before=0, track_before=0), ]} f = build_cross_findings(m) hit = [x for x in f if "nur in manchen" in x["title"]] assert hit and hit[0]["severity"] == "HIGH" # Einordnung: ITP maskiert clientseitig → kein Compliance-Beleg. assert "ITP" in hit[0]["detail"] assert "Chrome" in hit[0]["affected"] def test_reject_inconsistent_high(): m = {"browser_matrix": [ _row("chrome-channel-desktop-de", "Chrome", "blink", reject_ok=False), _row("brave-default-de", "Brave", "blink", reject_ok=True), ]} f = build_cross_findings(m) hit = [x for x in f if "nicht in allen Browsern respektiert" in x["title"]] assert hit and hit[0]["severity"] == "HIGH" assert "Chrome" in hit[0]["affected"] def test_missing_engines_coverage_hint(): m = {"browser_matrix": [ _row("chromium-headed-de", "Chromium", "blink"), _row("brave-default-de", "Brave", "blink", with_summary=False), ]} f = build_cross_findings(m) hit = [x for x in f if "Nicht alle Browser getestet" in x["title"]] assert hit and hit[0]["severity"] == "LOW" assert "Brave" in hit[0]["affected"] def test_clean_matrix_no_violations(): m = {"browser_matrix": [ _row("chromium-headed-de", "Chromium", "blink"), _row("firefox-headed-de", "Firefox", "gecko"), ]} # Alles sauber → keine Verstoß-Befunde (Impressum/DSE vorhanden). assert build_cross_findings(m) == []