"""ЭТАП 4 B2C launch — consent-text sync guard (part D). WHY: _CONSENT_TEXT_SNAPSHOT in app/api/v1/lead.py is a durable 152-ФЗ proof-of-consent: it must be the EXACT text a user actually saw and agreed to. Before this test, the only thing keeping it in sync with the real frontend checkbox label (LeadForm.tsx) was a code COMMENT ("Должен ДОСЛОВНО совпадать с чекбоксом в LeadForm.tsx"). A comment cannot fail CI -- a frontend copy edit could silently drift from the backend snapshot, and every future lead's "proof" would then misrepresent what the user actually saw. WHAT: Extract the actual consent-checkbox label text straight out of LeadForm.tsx (regex, no JSX parser needed -- there is exactly one in the file today) and assert it matches _CONSENT_TEXT_SNAPSHOT byte-for- byte after whitespace normalisation (JSX text nodes wrap across source lines; the DOM-rendered text collapses that to single spaces). If someone edits ONE side without the other, this test fails. NOTE: the NEW anonymous-estimate consent text (_ESTIMATE_CONSENT_TEXT_SNAPSHOT in app/services/estimator.py, ЭТАП 4 part A) has NO frontend counterpart yet -- the anonymous /estimate flow isn't live (rbac_guard still requires X-Authenticated-User on every non-public path, see app/core/rbac.py). When that flow ships its own consent checkbox, add a second sync test here mirroring this one -- do NOT rely on a comment for that pairing either. """ from __future__ import annotations import os import re from pathlib import Path os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://test:test@localhost:5432/test") _FRONTEND_LEAD_FORM = ( Path(__file__).resolve().parents[2] / "frontend" / "src" / "components" / "trade-in" / "v2" / "LeadForm.tsx" ) def _extract_span_text(tsx_source: str) -> str: """Pull the text content of the (single) ... in LeadForm.tsx, whitespace-normalised the same way a browser collapses JSX text-node whitespace when rendering (multiple lines/indentation -> single spaces). """ match = re.search(r"\s*(.*?)\s*", tsx_source, re.DOTALL) assert match is not None, "no found in LeadForm.tsx -- consent label markup changed" return re.sub(r"\s+", " ", match.group(1)).strip() def test_frontend_lead_form_exists() -> None: assert _FRONTEND_LEAD_FORM.is_file(), f"missing frontend file: {_FRONTEND_LEAD_FORM}" def test_backend_consent_snapshot_matches_frontend_checkbox_label() -> None: """The whole point: this FAILS if lead.py._CONSENT_TEXT_SNAPSHOT and LeadForm.tsx's checkbox label ever diverge -- no longer just a comment.""" from app.api.v1.lead import _CONSENT_TEXT_SNAPSHOT frontend_text = _extract_span_text(_FRONTEND_LEAD_FORM.read_text(encoding="utf-8")) backend_text = re.sub(r"\s+", " ", _CONSENT_TEXT_SNAPSHOT).strip() assert frontend_text == backend_text, ( "consent text drift detected between app/api/v1/lead.py._CONSENT_TEXT_SNAPSHOT " "and frontend/src/components/trade-in/v2/LeadForm.tsx checkbox label -- the " "152-ФЗ proof-of-consent snapshot no longer matches what users actually see. " "Bump _CONSENT_POLICY_VERSION and update _CONSENT_TEXT_SNAPSHOT together with " "any frontend copy change.\n" f" frontend: {frontend_text!r}\n" f" backend: {backend_text!r}" ) def test_extract_span_text_helper_is_whitespace_insensitive() -> None: """Sanity check on the extraction helper itself, independent of the real file.""" sample = """ Line one Line two """ assert _extract_span_text(sample) == "Line one Line two"