feat: Phase 11 — granular cookie category testing

Tests each consent category in isolation:
- Phase D: Only "Statistics" enabled → checks if only analytics loads
- Phase E: Only "Marketing" enabled → checks if only ads load
- Phase F: Only "Functional" enabled → checks no tracking loads

CMP-specific category selectors for Cookiebot, OneTrust, Usercentrics,
Didomi. Generic fallback via toggle/checkbox keyword detection.

SERVICE_CATEGORY_MAP maps 35+ services to expected categories.
Violations: "Facebook Pixel loads with only Statistics enabled" = miscategorization.

Frontend: category test results shown below Phase A-C with
per-category violation cards.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-01 21:15:23 +02:00
parent f6536e8d08
commit 6864849115
4 changed files with 358 additions and 1 deletions
+30 -1
View File
@@ -44,6 +44,8 @@ class ConsentTestResult:
accept_cookies: list[str] = field(default_factory=list)
accept_new_tracking: list[str] = field(default_factory=list)
accept_undocumented: list[str] = field(default_factory=list)
# Phase D-F: Per-category tests
category_tests: list = field(default_factory=list) # list[CategoryTestResult]
async def run_consent_test(url: str, wait_secs: int = 10) -> ConsentTestResult:
@@ -136,14 +138,41 @@ async def run_consent_test(url: str, wait_secs: int = 10) -> ConsentTestResult:
await ctx_c.close()
# ── Phase D-F: Per-category tests ────────────────────────
try:
from services.category_tester import detect_categories, test_single_category
ctx_cat = await browser.new_context(user_agent=USER_AGENT)
page_cat = await ctx_cat.new_page()
await page_cat.goto(url, wait_until="networkidle", timeout=20000)
await page_cat.wait_for_timeout(2000)
categories = await detect_categories(page_cat, banner)
await page_cat.close()
if categories:
logger.info("Testing %d categories individually", len(categories))
for cat in categories:
cat_ctx = await browser.new_context(user_agent=USER_AGENT)
cat_result = await test_single_category(cat_ctx, url, cat, banner, wait_ms)
result.category_tests.append(cat_result)
await cat_ctx.close()
else:
logger.info("No categories detected — skipping per-category tests")
await ctx_cat.close()
except Exception as cat_err:
logger.warning("Category tests failed (non-blocking): %s", cat_err)
except Exception as e:
logger.error("Consent test failed: %s", e)
finally:
await browser.close()
logger.info(
"Consent test complete: banner=%s, violations_before=%d, violations_reject=%d",
"Consent test complete: banner=%s, violations_before=%d, violations_reject=%d, categories=%d",
result.banner_provider, len(result.before_violations), len(result.reject_violations),
len(result.category_tests),
)
return result