Files
brain-of-reese/tests/unit/test_page_head_panel.py
T
ducoterra 9188be259b
Build and Push Containers / build-and-push-app (push) Successful in 1m56s
Build and Push Containers / build-and-push-db (push) Successful in 11s
phase: 93_theme_semantic_completion
All verification is complete. Final report:

**Phase 93 — Theme semantic completion: FINAL VERIFICATION PASS — ALL GREEN**

- Verified full implementation in tree: migration `0016` (8 nullable semantic columns, applied at head), 17-var `BUILTIN_COLORS`/`COLOR_FIELDS`/`effective_settings`, API validation, `#view-theme` State-colors fieldset (17 pickers), `theme.js` FIELDS/PAIRS (5→8), `.page-head` surface panel (6 shell views + doc-edit + shared.html; login card / document sticky header audited as already-surfaced), mock_llm `content: None` fix
- Fixed 2 pre-existing defects (both fail identically on baseline `d4f38ad`, proven via worktree A/B): `test_nav_rename_sources` — expected nav tail missing the phase-91 "Theme" link; `test_stale_ui_copy` — now truncates `saved_chats` before/after (house `test_suggestion_chips` pattern) so the seed-chip contract is deterministic on the shared dev DB (owner's 22 saved chats triggered phase-80 last-3-questions)
- Tests: `uv run pytest --cov=app --cov-report=term-missing` → **1868 passed, app/ 99%** (>90% ✓); `uv run ruff check .` → clean; `uv run pyright` → **0 errors**
- E2E: dedicated `uv run pytest tests/e2e/test_theme_semantic_completion.py -v --no-cov` → **8/8 in isolation** (all-gray 17-color theme: zero residual color on saved-result/Stale/Revoked/Local/tool-call elements, text labels intact, gray heads non-transparent, pre-paint tag, Reset → byte-identical no-tag); 15 theme/header/nav/responsive suites green in isolation; full 85-file combined run: only the 2 fixed pre-existing failures + 1 combined-run artifact (`test_sync_upload_progress`, green in isolation)
- Completion criteria: (1) monochrome E2E ✓ (2) default byte-identical, no `#bor-theme` tag ✓ (3) all page heads on solid surface ✓ (4) suite/coverage/lint/E2E green ✓ (5) phases 01–92 no behavior change ✓ (6) commit left to harness per protocol
- Notable: cleaned stray uvicorn leftovers from prior implementation pass (owner's `--reload` dev server untouched); no deviations from the phase design
- Next pending phase: `94_ls_tree_drilldown`
2026-09-10 16:43:08 -04:00

282 lines
12 KiB
Python

"""Unit: the phase-93 page-head surface panel contract (task 03 —
source pins).
Owner direction (TODO.md L3): "Also the header and description of each
page needs a background - the grid makes it hard to read." Every
page's ``h1`` + description (the shell's standard ``.page-head`` frame)
sits on a solid ``var(--surface)`` panel — the house card language —
so the 44px background grid never fights the heading text. Browser
behavior (computed ``background-color`` non-transparent on every head,
the History flex row + 360px wrap unbroken, the monochrome theme
graying the panel) is E2E-gated by ``tests/e2e/
test_theme_semantic_completion.py`` (task 04) and the existing
header/nav/responsive suites; here we pin the source-level contract
(house pattern: ``tests/unit/test_background_no_motion.py`` parses
``styles.css`` rules):
* the shared ``.page-head`` rule declares the panel — a NON-transparent
``background`` built from ``var(--surface)`` (no color literal of any
kind, no blur — the phase-08 perf anchor), the 1px ``var(--line)``
border, the house card radius, and card-rhythm padding;
* the ``#view-history`` page-head keeps its SCOPED flex row (padding
lives on the flex container — the base rule — never on the
children), and the mobile ``.page-head-row { flex-wrap: wrap; }``
survives;
* every shell view that carries a ``.page-head`` in the shell markup
is covered by the ONE rule (six views; ``#view-chat`` carries no
``.page-head`` — its head is the navbar, audited), and
``doc-edit.html`` keeps its ``.page-head``;
* the standalone pages: the shared page's head (``h1#shared-title`` +
the lede) is wrapped in the same ``.page-head`` class, while the two
heads that already sit inside a surfaced card are deliberately
UNTOUCHED (login's ``.login-card`` — surface card; document viewer's
``.doc-titlebar`` inside the sticky surface ``.doc-header``).
"""
from __future__ import annotations
import re
from pathlib import Path
FRONTEND = Path(__file__).resolve().parents[2] / "frontend"
STYLES_CSS = FRONTEND / "assets" / "styles.css"
INDEX_HTML = FRONTEND / "index.html"
SHARED_HTML = FRONTEND / "shared.html"
DOC_EDIT_HTML = FRONTEND / "doc-edit.html"
LOGIN_HTML = FRONTEND / "login.html"
DOCUMENT_HTML = FRONTEND / "document.html"
# The six shell views whose h1 + description sit in a .page-head
# (#view-chat carries none — its head is the navbar; audited).
SHELL_VIEWS_WITH_PAGE_HEAD = (
"view-tuning",
"view-rag",
"view-git-sources",
"view-history",
"view-tokens",
"view-theme",
)
def _css() -> str:
return STYLES_CSS.read_text(encoding="utf-8")
def _css_no_comments() -> str:
return re.sub(r"/\*[\s\S]*?\*/", "", _css())
def _find_rule(css: str, selector: str) -> re.Match[str] | None:
"""The first top-level ``selector { ... }`` rule (comments
stripped by the caller when prose must not interfere)."""
return re.search(r"(?m)^" + re.escape(selector) + r"\s*\{([\s\S]*?)\n\}", css)
def _rule_block(css: str, selector: str) -> str:
rule = _find_rule(css, selector)
assert rule, f"styles.css must define a {selector} rule"
return rule.group(1)
def _view_section(body: str, view_id: str) -> str:
"""The view section slice — from its opening tag to the next
sibling view (or ``</main>``). A first-``</section>`` slice would
cut short: the views nest gate sections (``<section
class="sources-gate">``) INSIDE, and the Git-sources / Theme
``.page-head`` sits after the first nested close."""
start = body.find(f'<section class="view" id="{view_id}"')
assert start != -1, f"the #{view_id} section must be in the shell"
boundaries = [
e
for e in (body.find('<section class="view"', start + 1), body.find("</main>", start))
if e != -1
]
assert boundaries, "the shell must have a closing </main>"
return body[start : min(boundaries)]
# --------------------------------------------------------------------------
# The shared .page-head rule — the surface panel
# --------------------------------------------------------------------------
def test_page_head_rule_is_the_surface_panel() -> None:
"""The one shared rule declares the panel: a non-transparent
background from ``var(--surface)`` (itself tab-controlled — a
monochrome theme grays the head automatically), the 1px
``var(--line)`` border, the house card radius, and card-rhythm
padding (the phase-93 panel: 1rem block / 1.25rem inline)."""
block = _rule_block(_css_no_comments(), ".page-head")
assert "background: var(--surface)" in block, (
"the .page-head panel must fill with var(--surface) — solid, "
"never transparent, never a literal"
)
assert "border: 1px solid var(--line)" in block, (
"the panel must carry the house 1px --line border"
)
assert "border-radius: var(--radius)" in block, (
"the panel must use the house card radius"
)
assert re.search(r"padding:\s*1rem\s+1\.25rem", block), (
"the panel must carry the card-rhythm padding (1rem 1.25rem)"
)
def test_page_head_rule_has_no_color_literal_and_no_blur() -> None:
"""Phase-92 invariant + phase-08 perf anchor: the panel rule
introduces NO new color literal (hex / rgb / hsl / color-mix —
``var(--…)`` only) and no filter/blur."""
block = _rule_block(_css_no_comments(), ".page-head")
assert not re.search(r"#[0-9a-fA-F]{3,8}\b", block), (
"no hex color literal in the .page-head panel (phase-92 invariant)"
)
for func in ("rgb(", "hsl(", "color-mix("):
assert func not in block, f"no {func}… literal in the .page-head panel"
assert "filter" not in block and "blur" not in block, (
"no filter/blur in the .page-head panel (phase-08 perf anchor)"
)
def test_page_head_background_is_solid_not_translucent() -> None:
"""The panel is SOLID — the assumption the phase locked (not
translucent, not a full-bleed band, no blur): the background
declaration names exactly the surface variable, nothing mixed."""
block = _rule_block(_css_no_comments(), ".page-head")
backgrounds = re.findall(r"(?m)^\s*background(?:-color)?:\s*([^;]+);", block)
assert backgrounds == ["var(--surface)"], (
f"the .page-head background must be exactly var(--surface), "
f"got {backgrounds}"
)
# --------------------------------------------------------------------------
# Layout safety — the History flex row and the mobile wrap
# --------------------------------------------------------------------------
def test_history_page_head_keeps_its_scoped_flex_row() -> None:
"""The ``#view-history .page-head`` flex row (title left, refresh
pill right — phase 77) survives the panel: the scoped rule keeps
its flex declarations and adds NO padding of its own (the task-03
rule — padding on the flex container, i.e. the base ``.page-head``
rule, never on the children, so space-between + align stay intact
inside the padded box)."""
scoped = _rule_block(_css_no_comments(), "#view-history .page-head")
for decl in (
"display: flex",
"flex-wrap: wrap",
"align-items: flex-start",
"justify-content: space-between",
):
assert decl in scoped, f"#view-history .page-head must keep {decl!r}"
assert not re.search(r"(?m)^\s*padding\b", scoped), (
"the scoped History rule must not add its own padding — the "
"base .page-head rule (the flex container) carries it"
)
def test_mobile_page_head_row_wrap_survives() -> None:
"""≤640px: ``.page-head-row { flex-wrap: wrap; }`` (the RAG head's
Sync pill drops below the title at full width) still exists in the
mobile block — the wrap keeps working INSIDE the panel."""
mobile = re.search(r"@media \(max-width: 640px\) \{([\s\S]*?)\n\}\n", _css())
assert mobile, "the mobile media query must exist"
assert ".page-head-row { flex-wrap: wrap; }" in mobile.group(1), (
"the mobile .page-head-row wrap must survive the panel"
)
# --------------------------------------------------------------------------
# Coverage — every head that sits on the grid gets the panel
# --------------------------------------------------------------------------
def test_every_shell_view_with_a_page_head_is_covered() -> None:
"""The ONE rule covers every shell view that carries the class:
all six do (their ``class="page-head"`` div is static markup in
the shell); #view-chat carries NO .page-head (its head is the
navbar — audited, untouched)."""
body = INDEX_HTML.read_text(encoding="utf-8")
for view_id in SHELL_VIEWS_WITH_PAGE_HEAD:
assert 'class="page-head"' in _view_section(body, view_id), (
f"#{view_id} must keep its .page-head (the shared rule panels it)"
)
assert 'class="page-head"' not in _view_section(body, "view-chat"), (
"#view-chat carries no .page-head (its head is the navbar)"
)
def test_doc_edit_page_head_is_covered() -> None:
"""doc-edit.html's head already IS a .page-head (h1 'Edit doc' +
the .page-sub lede) — the shared rule panels it with no markup
change."""
html = DOC_EDIT_HTML.read_text(encoding="utf-8")
head = re.search(
r'<div class="page-head">\s*<h1>Edit doc</h1>[\s\S]*?class="page-sub"',
html,
)
assert head, "doc-edit.html must keep its .page-head (h1 + page-sub)"
def test_shared_page_head_is_wrapped_in_page_head() -> None:
"""The shared page's head (``h1#shared-title`` + the read-only
lede) was a direct child of the grid-exposed ``.shared-shell`` —
it is now wrapped in the same ``.page-head`` class, so the shared
rule panels it (the h1 keeps the ``.page-head h1`` size per the
``#shared-title`` rule)."""
html = SHARED_HTML.read_text(encoding="utf-8")
wrapped = re.search(
r'<div class="page-head">\s*'
r"<h1 id=\"shared-title\">Shared conversation</h1>\s*"
r'<p class="shared-note">Shared via Brain of Reese — read-only\.</p>\s*'
r"</div>",
html,
)
assert wrapped, (
"shared.html must wrap the h1 + lede in a .page-head div"
)
# --------------------------------------------------------------------------
# Deliberate skips — heads already inside a surfaced card
# --------------------------------------------------------------------------
def test_login_head_is_already_carded_and_untouched() -> None:
"""login.html: h1#login-title lives inside section.login-card,
which is ALREADY the surface card (var(--surface) fill + border +
radius + shadow) — the TODO targets grid-exposed text, so the
login head gets no double panel."""
html = LOGIN_HTML.read_text(encoding="utf-8")
card = re.search(
r'<section class="login-card"[^>]*>[\s\S]*?'
r'<h1 id="login-title">Sign in</h1>',
html,
)
assert card, "the login h1 must sit inside the .login-card"
card_css = _rule_block(_css_no_comments(), ".login-card")
assert "background: var(--surface)" in card_css
assert "border: 1px solid var(--line)" in card_css
assert "border-radius: var(--radius)" in card_css
assert 'class="page-head"' not in html, (
"login.html must not gain a .page-head (the card already panels it)"
)
def test_document_head_is_already_carded_and_untouched() -> None:
"""document.html: h1#doc-title lives in the .doc-titlebar row 2
inside the STICKY .doc-header, which is already surface-filled
(var(--surface) — the two-row pinned bar) — no double panel."""
html = DOCUMENT_HTML.read_text(encoding="utf-8")
titlebar = re.search(
r'<div class="doc-titlebar">[\s\S]*?<h1 id="doc-title">', html
)
assert titlebar, "the document h1 must sit inside the .doc-titlebar"
header_css = _rule_block(_css_no_comments(), ".doc-header")
assert "background: var(--surface)" in header_css, (
"the sticky .doc-header must stay surface-filled"
)
assert 'class="page-head"' not in html, (
"document.html must not gain a .page-head (the titlebar is "
"already inside the surface header)"
)