128 lines
5.2 KiB
Python
128 lines
5.2 KiB
Python
"""Unit: the navbar steering toggle is gone (owner request, 2026-08-28).
|
|
|
|
The "Tuning" steering toggle (``#steering-toggle``) used to sit in
|
|
every page's shared header — shipped hidden (phase 40), revealed for
|
|
the admin, removed from the DOM for anonymous. The owner asked for the
|
|
button to go away entirely: note management now lives on the
|
|
standalone Tuning page (``/tuning.html``, phase 27). This file pins the
|
|
removal at source level — the toggle + count badge are ABSENT from all
|
|
six pages, the ``#steering-panel`` section still ships hidden (kept
|
|
fresh by the chat page's per-bubble Tune form through header.js), the
|
|
shared module owns no toggle wiring anymore, and the admin-only
|
|
``#nav-tuning`` link — the surviving path to the notes — still ships
|
|
hidden.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from pathlib import Path
|
|
|
|
FRONTEND = Path(__file__).resolve().parents[2] / "frontend"
|
|
ASSETS = FRONTEND / "assets"
|
|
|
|
HEADER_JS = ASSETS / "header.js"
|
|
|
|
#: All seven pages carry the shared header block (phase 34's five pages
|
|
#: + phase 35's git-sources page + phase 50's History page).
|
|
PAGES = (
|
|
FRONTEND / "index.html",
|
|
FRONTEND / "sources.html",
|
|
FRONTEND / "document.html",
|
|
FRONTEND / "git-sources.html",
|
|
FRONTEND / "login.html",
|
|
FRONTEND / "tuning.html",
|
|
FRONTEND / "history.html",
|
|
)
|
|
|
|
|
|
def _text(path: Path) -> str:
|
|
assert path.is_file(), f"missing frontend file: {path}"
|
|
return path.read_text(encoding="utf-8")
|
|
|
|
|
|
def _init_body(js: str) -> str:
|
|
"""The source of initSharedHeader in header.js."""
|
|
fn = js.find("function initSharedHeader")
|
|
assert fn != -1, "initSharedHeader must be defined"
|
|
return js[fn : js.find("\n}", fn)]
|
|
|
|
|
|
# ---------- the removal: absent from every page's navbar ----------
|
|
|
|
|
|
def test_steering_toggle_removed_from_all_six_pages() -> None:
|
|
"""The #steering-toggle button (and its #steering-count badge) is
|
|
gone from the navbar of EVERY page — absent, not hidden."""
|
|
for html in PAGES:
|
|
text = _text(html)
|
|
assert 'id="steering-toggle"' not in text, (
|
|
f"{html.name}: #steering-toggle must be removed from the navbar"
|
|
)
|
|
assert 'class="steering-toggle"' not in text, (
|
|
f"{html.name}: the .steering-toggle button must be removed"
|
|
)
|
|
assert 'id="steering-count"' not in text, (
|
|
f"{html.name}: the #steering-count badge lived inside the toggle"
|
|
)
|
|
|
|
|
|
def test_steering_panel_still_ships_hidden_on_all_six_pages() -> None:
|
|
"""The #steering-panel section survives the toggle removal (the chat
|
|
page's per-bubble Tune form keeps it fresh through header.js) and
|
|
still ships hidden, with its list / empty state / announcer."""
|
|
for html in PAGES:
|
|
text = _text(html)
|
|
tag = re.search(r'<section[^>]*id="steering-panel"[^>]*>', text)
|
|
assert tag, f"{html.name}: missing the #steering-panel section"
|
|
assert re.search(r"\bhidden\b", tag.group(0)), "the panel ships hidden"
|
|
assert 'id="steering-list"' in text, f"{html.name}: missing #steering-list"
|
|
assert 'id="steering-empty"' in text, f"{html.name}: missing #steering-empty"
|
|
assert re.search(r'<p[^>]*id="steering-announcer"[^>]*role="status"[^>]*>', text), (
|
|
f"{html.name}: missing the #steering-announcer live region"
|
|
)
|
|
|
|
|
|
# ---------- header.js: no toggle wiring left, panel contract intact ----------
|
|
|
|
|
|
def test_header_js_carries_no_toggle_wiring() -> None:
|
|
"""header.js owns no #steering-toggle reference anymore: no element
|
|
lookup, no admin unhide, no anonymous removal, no click binding, no
|
|
open/close helper, no count badge."""
|
|
js = _text(HEADER_JS)
|
|
assert 'querySelector("#steering-toggle")' not in js
|
|
assert "steeringToggle" not in js
|
|
assert "setSteeringPanel" not in js
|
|
assert 'querySelector("#steering-count")' not in js
|
|
assert "steeringCount" not in js
|
|
|
|
|
|
def test_header_js_keeps_the_panel_contract() -> None:
|
|
"""What survives: inside initSharedHeader the admin branch still
|
|
refreshes the panel list (fire-and-forget) and the anonymous branch
|
|
still REMOVES the panel from the DOM (phase-16 "absent, not hidden")
|
|
so /api/steering is never fetched for anonymous visitors."""
|
|
body = _init_body(_text(HEADER_JS))
|
|
admin = body.find("if (admin)")
|
|
refresh = body.find("if (steeringPanel) refreshSteering();")
|
|
assert admin != -1 and refresh != -1, "the admin refresh is missing"
|
|
assert admin < refresh, "the refresh must live in the admin branch"
|
|
assert "steeringPanel?.remove();" in body, (
|
|
"the anonymous remove-from-DOM path must stay intact"
|
|
)
|
|
|
|
|
|
# ---------- the surviving path to the notes ----------
|
|
|
|
|
|
def test_nav_tuning_still_ships_hidden_on_all_six_pages() -> None:
|
|
"""The admin-only Tuning NAV LINK (#nav-tuning) — the surviving path
|
|
to the steering notes now that the navbar toggle is gone — still
|
|
ships hidden on every page (the phase-19/29/35 contract)."""
|
|
for html in PAGES:
|
|
tag = re.search(r'<a[^>]*id="nav-tuning"[^>]*>', _text(html))
|
|
assert tag, f"{html.name}: missing the #nav-tuning nav link"
|
|
assert re.search(r"\bhidden\b", tag.group(0)), (
|
|
f"{html.name}: #nav-tuning must ship hidden"
|
|
)
|