feat(cookie): Deklaration-vs-Bibliothek-Diff-Sicht + Funnel-KPI
Für die Library-getroffene Teilmesse (~32%) pro Cookie die Feld- Abweichungen deklariert→Library (Kategorie/Laufzeit/Zweck) als Diff-Karte, plus ehrlicher Funnel (gesamt → geprüft → abweichend) — nicht-getroffene Cookies sind nicht prüfbar (kein Pass/Fail), passend zur Tonalität. - analyze_cookies: 'expected'-Soll-Wert an tracker_as_necessary/ excessive_lifetime/missing_purpose (+ _CAT_LABEL_DE). - neues cookie_declaration_diff.build_declaration_diff: reine Regroup- Aggregation der Findings pro Cookie (single source = analyze_cookies), Hinweis-Typen (third_country/eu_alternative) bewusst ausgeschlossen. - cookie-check exponiert out['declaration_diff']. - CookieDeclarationDiff.tsx oben im Cookie-Tab (vor Panel/ResultView). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
"""Deklaration-vs-Bibliothek-Diff: Regroup pro Cookie + Funnel."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from compliance.services.cookie_declaration_diff import build_declaration_diff
|
||||
|
||||
|
||||
def test_groups_diffs_per_cookie_with_funnel():
|
||||
analysis = {
|
||||
"summary": {"checked": 100, "in_library": 32, "findings": 4},
|
||||
"findings": [
|
||||
{"vendor": "Google", "cookie": "_ga", "type": "tracker_as_necessary",
|
||||
"severity": "HIGH", "declared": "notwendig", "expected": "Marketing",
|
||||
"remediation": "Als § 25 einstufen."},
|
||||
{"vendor": "Google", "cookie": "_ga", "type": "excessive_lifetime",
|
||||
"severity": "LOW", "declared": "Session", "expected": "730 Tage",
|
||||
"remediation": "Laufzeit prüfen."},
|
||||
{"vendor": "Meta", "cookie": "_fbp", "type": "missing_purpose",
|
||||
"severity": "MEDIUM", "declared": "(kein Zweck)", "expected": "Tracking",
|
||||
"remediation": "Zweck ergänzen."},
|
||||
# Hinweis-Typ ohne Library-Soll → NICHT im Diff.
|
||||
{"vendor": "Google", "cookie": "_ga", "type": "third_country",
|
||||
"severity": "MEDIUM", "declared": "US"},
|
||||
],
|
||||
}
|
||||
out = build_declaration_diff(analysis)
|
||||
assert out["coverage"] == {"total": 100, "checked": 32, "discrepant": 2}
|
||||
ga = next(r for r in out["rows"] if r["cookie"] == "_ga")
|
||||
assert {d["field"] for d in ga["diffs"]} == {"Kategorie", "Laufzeit"}
|
||||
assert ga["severity"] == "HIGH" # höchste der beiden
|
||||
assert ga["diffs"][0]["severe"] is True
|
||||
assert out["rows"][0]["cookie"] == "_ga" # HIGH zuerst sortiert
|
||||
|
||||
|
||||
def test_no_discrepancies_yields_empty_rows():
|
||||
out = build_declaration_diff(
|
||||
{"summary": {"checked": 10, "in_library": 4}, "findings": []})
|
||||
assert out["coverage"] == {"total": 10, "checked": 4, "discrepant": 0}
|
||||
assert out["rows"] == []
|
||||
Reference in New Issue
Block a user