881e9c28de
- _scanner_run reicht browser_profile an run_consent_test durch (statt Single-Chromium-Shim) - neue scan_matrix_summary.matrix_scan_dict: ConsentTestResult -> schlanke Matrix-dict-Form (phases fuer _extract_dimensions + kompakter `summary`: cookies_before_consent/after_reject, reject_respected-Heuristik [keine Verstoesse UND kein neuer Tracker], surface, screenshot) - multi_browser_scanner._run_one hebt summary + engine + is_mobile an die Zeile, verwirft die vollen Cookie-Listen (JSONB-Persistenz schlank) - consent_scanner: _ctx_base mit Mobile-Device-Emulation (iPhone-Profil -> echtes Mobile-Viewport/Touch), alle 5 new_context auf **_ctx_base - Tests: test_scan_matrix_summary (6) inkl. _extract_dimensions-Vertrag Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
74 lines
2.9 KiB
Python
74 lines
2.9 KiB
Python
"""Per-Engine-Projektion der Browser-Matrix (`scan_matrix_summary`).
|
|
|
|
Sichert: ConsentTestResult → schlanke Matrix-dict-Form mit (a) phases, die
|
|
`multi_browser_scanner._extract_dimensions` lesen kann, und (b) kompaktem
|
|
`summary` (cookies_before/after_reject, reject_respected-Heuristik, Surface).
|
|
"""
|
|
|
|
from types import SimpleNamespace
|
|
|
|
from services.scan_matrix_summary import matrix_scan_dict
|
|
from services.multi_browser_scanner import _extract_dimensions
|
|
|
|
|
|
def _result(**kw):
|
|
base = dict(
|
|
banner_detected=True, banner_provider="Usercentrics",
|
|
before_cookies=[], reject_cookies=[],
|
|
before_violations=[], reject_violations=[], reject_new_tracking=[],
|
|
banner_text_violations=[],
|
|
banner_has_impressum_link=True, banner_has_dse_link=True,
|
|
banner_screenshot_b64="iVBOR_fake",
|
|
)
|
|
base.update(kw)
|
|
return SimpleNamespace(**base)
|
|
|
|
|
|
def test_cookie_counts_and_names_capped():
|
|
r = _result(before_cookies=[f"c{i}" for i in range(50)],
|
|
reject_cookies=["a", "b"])
|
|
out = matrix_scan_dict(r)
|
|
s = out["summary"]
|
|
assert s["cookies_before_consent"] == 50
|
|
assert s["cookies_after_reject"] == 2
|
|
assert len(s["cookies_before_names"]) == 40 # gedeckelt
|
|
assert s["cookies_after_reject_names"] == ["a", "b"]
|
|
|
|
|
|
def test_reject_respected_true_when_no_violation_no_tracking():
|
|
r = _result(reject_cookies=["consent_choice"]) # essentielles Cookie bleibt
|
|
out = matrix_scan_dict(r)
|
|
# Verbleibendes essentielles Cookie allein darf NICHT als Verstoß zählen.
|
|
assert out["summary"]["reject_respected"] is True
|
|
|
|
|
|
def test_reject_respected_false_on_reject_violation():
|
|
r = _result(reject_violations=[SimpleNamespace(severity="HIGH", text="x")])
|
|
assert matrix_scan_dict(r)["summary"]["reject_respected"] is False
|
|
|
|
|
|
def test_reject_respected_false_on_new_tracking():
|
|
r = _result(reject_new_tracking=["google-analytics"])
|
|
assert matrix_scan_dict(r)["summary"]["reject_respected"] is False
|
|
|
|
|
|
def test_surface_and_screenshot_passthrough():
|
|
r = _result(banner_has_impressum_link=False,
|
|
banner_text_violations=[SimpleNamespace(severity="LOW", text="y")])
|
|
out = matrix_scan_dict(r)
|
|
assert out["summary"]["surface"]["has_impressum_link"] is False
|
|
assert out["summary"]["surface"]["has_dse_link"] is True
|
|
assert out["summary"]["surface"]["banner_text_issues"] == 1
|
|
assert out["summary"]["banner_screenshot_b64"] == "iVBOR_fake"
|
|
|
|
|
|
def test_phases_shape_readable_by_extract_dimensions():
|
|
# Vertrag: die Projektion MUSS von _extract_dimensions konsumierbar sein.
|
|
r = _result(before_cookies=["a", "b", "c"], reject_cookies=["d"])
|
|
out = matrix_scan_dict(r)
|
|
dims = _extract_dimensions(out)
|
|
assert set(dims) == {"pre_consent", "reject_respect", "banner_design"}
|
|
# 3 Pre-Cookies → pre_consent < 1.0; weniger Reject-Cookies → höher.
|
|
assert 0.0 <= dims["pre_consent"] <= 1.0
|
|
assert dims["reject_respect"] <= 1.0
|