"""Unit: the phase-51 task-03 shared page contract (anonymous, read-only, zero controls). The browser behavior itself is E2E-gated by the story suite (task 04); like the other frontend-adjacent unit files, this module pins the JS/CSS/HTML markers the shared-conversation contract depends on, so a silent regression is caught without a browser: * the page scaffold (the identical shared header — every admin-only link ships hidden, the auth pair's static fallback is ``?next=/`` — a guest signing in from a shared page returns to the app root — the steering panel, the h1 fallback, the read-only note, the invalid state, the messages section); * the token parse (a malformed path → the invalid state, NO fetch of any kind); * the 404 / network / malformed read → the invalid state (no data render, no banner); * ZERO interactive controls: ``renderSharedMessage`` never calls the chat page's interactive builders, and the rendered messages contain no button/form/link — the chips are plain spans, the source chips carry no ``href``; * the shared shell's 46rem column mapping + the static-chip and invalid-state CSS (the ≤640px squeeze included). """ from __future__ import annotations import re from pathlib import Path FRONTEND = Path(__file__).resolve().parents[2] / "frontend" ASSETS = FRONTEND / "assets" SHARED_HTML = FRONTEND / "shared.html" SHARED_JS = ASSETS / "shared.js" STYLES_CSS = ASSETS / "styles.css" def _js() -> str: return SHARED_JS.read_text(encoding="utf-8") def _css() -> str: return STYLES_CSS.read_text(encoding="utf-8") def _html() -> str: return SHARED_HTML.read_text(encoding="utf-8") def _fn(js: str, name: str) -> str: """The source of a top-level ``function (...)`` (to its close).""" start = js.find(f"function {name}(") assert start != -1, f"{name}() must exist in shared.js" return js[start : js.find("\n}\n", start) + 4] # ---------- shared.html: the page scaffold ---------- def test_shared_html_scaffold_and_landmarks() -> None: """The standard page scaffold (AGENTS.md rule 5): skip link, the shared header, the steering panel + announcer (phase 34 — ships on every page), the h1 with its static fallback, the read-only note, the invalid state (ship-hidden), the messages section, and the footer with the version span (the index.html shape).""" html = _html() assert '