""" Unit tests for vendor → CookieBannerConfig and vendor → Document pre-fill mappers (M1 + M2 of the customer-banner migration feature). """ from __future__ import annotations import pytest from compliance.services.migration_to_banner import ( build_banner_config, map_category, ) from compliance.services.migration_to_document import build_document_prefills @pytest.fixture() def sample_vendors() -> list[dict]: return [ { "name": "BMW AG", "category": "necessary", "recipient_type": "INTERNAL", "purpose": "Sicherstellung der Grundfunktionen", "cookies": [{"name": "JSESSIONID", "expiry": "Session"}], }, { "name": "Google Analytics", "category": "statistics", "recipient_type": "PROCESSOR", "purpose": "Reichweitenmessung", "country": "US", "opt_out_url": "https://tools.google.com/dlpage/gaoptout", "opt_out_ok": True, "privacy_policy_url": "https://policies.google.com/privacy", "cookies": [ {"name": "_ga", "expiry": "2 Jahre", "is_third_party": True}, {"name": "_gid", "expiry": "1 Tag", "is_third_party": True}, ], }, { "name": "YouTube", "category": "marketing", "recipient_type": "PROCESSOR", "purpose": "Eingebettete Videos", "cookies": [], }, { "name": "Broken Pixel", "category": "marketing", "recipient_type": "PROCESSOR", "purpose": "Werbung", "opt_out_url": "https://example.com/optout", "opt_out_ok": False, "opt_out_status": 404, "cookies": [{"name": "_pix", "expiry": ""}], }, ] def test_map_category_youtube_routes_to_external_media(): assert map_category("marketing", "YouTube Player") == "EXTERNAL_MEDIA" def test_map_category_unknown_falls_back_to_personalization(): assert map_category("weird-cat", "Some Vendor") == "PERSONALIZATION" def test_map_category_necessary_is_essential(): assert map_category("necessary", "JSESSIONID") == "ESSENTIAL" def test_build_banner_config_buckets_categories(sample_vendors): out = build_banner_config(sample_vendors, site_name="bmw.de") cats = {c["id"]: c for c in out["config"]["categories"]} assert "ESSENTIAL" in cats assert "PERFORMANCE" in cats assert any(c["name"] == "_ga" for c in cats["PERFORMANCE"]["cookies"]) # YouTube vendor had no cookies → it should not pollute EXTERNAL_MEDIA # but should produce a WARNING flag for the missing list assert any(f["vendor"] == "YouTube" and f["issue"] == "no_cookies_listed" for f in out["flags"]) def test_build_banner_config_flags_broken_opt_out(sample_vendors): out = build_banner_config(sample_vendors, site_name="bmw.de") errors = [f for f in out["flags"] if f["level"] == "ERROR"] assert any(f["issue"] == "broken_opt_out" and f["vendor"] == "Broken Pixel" for f in errors) def test_build_banner_config_summary_counts(sample_vendors): out = build_banner_config(sample_vendors, site_name="bmw.de") s = out["summary"] assert s["vendors_total"] == 4 assert s["vendors_with_no_cookies"] == 1 assert s["cookies_total"] == 4 # JSESSIONID + _ga + _gid + _pix def test_build_document_prefills_emits_all_three_templates(sample_vendors): out = build_document_prefills( sample_vendors, extracted_profile={ "company_profile": { "companyName": "BMW AG", "headquartersStreet": "Petuelring 130", "headquartersZip": "80809", "headquartersCity": "Muenchen", "dpoEmail": "datenschutz@bmw.de", }, }, site_name="bmw.de", ) assert set(out.keys()) == {"cookie_policy", "vvt_register", "privacy_policy"} cp = out["cookie_policy"] assert cp["templateType"] == "cookie_policy" assert "BMW AG" in cp["initialContent"] assert "Google Analytics" in cp["initialContent"] assert "Petuelring 130" in cp["initialContent"] def test_vvt_register_marks_third_country_for_us_processor(sample_vendors): out = build_document_prefills(sample_vendors, site_name="bmw.de") acts = out["vvt_register"]["activities"] ga = next(a for a in acts if a["name"] == "Google Analytics") rcat = ga["recipientCategories"][0] assert rcat["type"] == "PROCESSOR" assert rcat["country"] == "US" assert rcat["isThirdCountry"] is True def test_privacy_policy_section_groups_by_recipient_type(sample_vendors): out = build_document_prefills(sample_vendors, site_name="bmw.de") body = out["privacy_policy"]["initialContent"] assert "Eigene Verarbeitung" in body assert "Auftragsverarbeiter" in body # BMW AG (INTERNAL) must appear under Eigene, not under Auftragsverarbeiter internal_block = body.split("### Auftragsverarbeiter")[0] assert "BMW AG" in internal_block