Files
brain-of-reese/tests/e2e/test_tuning_toggle_flash.py
ducoterra dbf2af26c6 refactor(agents): migrate .agent/ planning tree to .agents/
Standardize on the .agents/ directory (shared with project skills):
phases/, user_stories/, reports/, screenshots/, validate.sh, and
phase-sessions/ + pipeline.log all move to .agents/ (git mv preserves
history; runtime artifacts move alongside).

Updates every reference in AGENTS.md, README.md, .gitignore, app
docstrings, and test story headers. Historical KB content in data/
and the runtime pipeline.log transcript are left untouched.
2026-09-05 10:57:07 -04:00

178 lines
7.4 KiB
Python

"""Phase 40 E2E (Playwright): the anonymous "Tuning" flash is gone.
The owner report (``TODO.md`` L3): loading a page briefly showed the
header "Tuning" button (``#steering-toggle``, the steering-notes
toggle) to ANONYMOUS visitors — it shipped VISIBLE in all six pages'
markup and ``assets/header.js`` removed it only after ``/api/whoami``
resolved, so the button flashed for the whole whoami round-trip.
Phase 40 fixed it with the ship-hidden / reveal-for-admin contract
(the admin-only nav links). The owner then asked for the button to go
away entirely (2026-08-28): the navbar ``#steering-toggle`` is now
ABSENT from every page — for the admin AND anonymous — so the
never-visible contract holds by construction, and note management
lives on ``/tuning.html``. The anonymous end-state is unchanged: the
``#steering-panel`` is REMOVED from the DOM (phase 16 "absent, not
hidden") and ``/api/steering`` is never fetched. This suite proves the
browser-level contract:
* ``#steering-toggle`` is absent from the DOM on every page, for
anonymous AND admin — nothing can flash, because nothing ships;
* the anonymous end-state survives the removal: ``#steering-panel``
is removed from the DOM, not just hidden;
* the admin UX around the removal is intact: the header panel section
still ships hidden (never opened from the header anymore), and the
ship-hidden nav-link contract this phase relies on
(``#nav-sources`` / ``#nav-git-sources`` / ``#nav-tuning``) holds:
hidden for anonymous, revealed for admin.
Story: ``.agents/user_stories/tuning-toggle-flash.md``
Run in isolation (DB must be up: ``podman compose up -d db``):
uv run pytest tests/e2e/test_tuning_toggle_flash.py -v --no-cov
Test → story mapping (Playwright Mapping Rule):
1. ``test_anonymous_never_sees_toggle``
2. ``test_anonymous_other_pages_never_flash``
3. ``test_admin_toggle_revealed_and_working``
4. ``test_nav_contract_regression``
"""
from __future__ import annotations
from playwright.sync_api import Page, expect
from e2e.auth_helpers import login
#: The pages the contract must hold on besides the chat page (mapping
#: rule 2). document.html / git-sources.html are covered by the
#: source-level unit pins (tests/unit/test_steering_toggle_removal.py)
#: — the three pages here are the other pages an anonymous visitor
#: actually lands on.
OTHER_PAGES = ("/sources.html", "/tuning.html", "/login.html")
#: Admin-only nav links — the ship-hidden / reveal-for-admin family the
#: steering toggle belonged to (phase 19/29/35 contract).
NAV_IDS = ("#nav-sources", "#nav-git-sources", "#nav-tuning")
def _assert_no_toggle(page: Page, path: str) -> None:
"""The navbar toggle is absent from the DOM for one page — nothing
to flash, for either role."""
assert page.locator("#steering-toggle").count() == 0, (
f"{path}: #steering-toggle must be ABSENT from the DOM "
"(removed from the navbar at owner request, 2026-08-28)"
)
def _wait_header_settled_anonymous(page: Page) -> None:
"""Whoami resolved on the current document: the anonymous state
reveals the Sign in link and keeps Sign out hidden (the pair is
decided by the SAME initSharedHeader pass that removes the
steering panel)."""
page.wait_for_load_state("networkidle")
expect(page.locator("#sign-in-link")).to_be_visible(timeout=15_000)
expect(page.locator("#sign-out-btn")).to_be_hidden()
def _wait_header_settled_admin(page: Page) -> None:
"""Whoami resolved for a signed-in admin on the current document."""
page.wait_for_load_state("networkidle")
expect(page.locator("#sign-out-btn")).to_be_visible(timeout=15_000)
expect(page.locator("#sign-in-link")).to_be_hidden()
# ---------------------------------------------------------------------------
# 1. Anonymous chat load: zero toggle, panel removed (never visible)
# ---------------------------------------------------------------------------
def test_anonymous_never_sees_toggle(
page: Page, app_url: str, mock_llm: int, db_ready: None
) -> None:
page.set_default_timeout(30_000)
page.goto(app_url + "/")
_wait_header_settled_anonymous(page)
_assert_no_toggle(page, "/")
# The phase-16 end-state survives the removal: the panel is REMOVED
# from the DOM, not just hidden.
assert page.locator("#steering-panel").count() == 0, (
"/: #steering-panel must be removed from the DOM for anonymous "
"(phase 16 'absent, not hidden')"
)
# ---------------------------------------------------------------------------
# 2. Anonymous loads of the other pages: same no-toggle contract
# ---------------------------------------------------------------------------
def test_anonymous_other_pages_never_flash(
page: Page, app_url: str, mock_llm: int, db_ready: None
) -> None:
page.set_default_timeout(30_000)
for path in OTHER_PAGES:
page.goto(app_url + path)
_wait_header_settled_anonymous(page)
_assert_no_toggle(page, path)
assert page.locator("#steering-panel").count() == 0, (
f"{path}: #steering-panel must be removed from the DOM for "
"anonymous (phase 16 'absent, not hidden')"
)
# ---------------------------------------------------------------------------
# 3. Admin: the toggle is gone too — the panel still ships hidden and
# the nav links are revealed
# ---------------------------------------------------------------------------
def test_admin_toggle_revealed_and_working(
page: Page, app_url: str, mock_llm: int, db_ready: None
) -> None:
page.set_default_timeout(30_000)
login(page, app_url, next="/")
_wait_header_settled_admin(page)
# The navbar toggle was removed at owner request (2026-08-28) —
# absent for the admin as well; nothing in the header can flash
# it back, because nothing ships it anymore.
_assert_no_toggle(page, "/")
# The header panel section survives (kept fresh by the chat page's
# per-bubble Tune form) but ships hidden — no header control opens
# it anymore; note management lives on /tuning.html.
assert page.locator("#steering-panel").count() == 1
expect(page.locator("#steering-panel")).to_be_hidden()
# The surviving path to the notes: the admin-only Tuning nav link
# is revealed.
expect(page.locator("#nav-tuning")).to_be_visible()
# ---------------------------------------------------------------------------
# 4. Nav-contract regression (phase 19/34): the ship-hidden family the
# toggle used to belong to is intact
# ---------------------------------------------------------------------------
def test_nav_contract_regression(
page: Page, app_url: str, mock_llm: int, db_ready: None
) -> None:
page.set_default_timeout(30_000)
# Anonymous: every admin-only nav link stays hidden on the chat
# page (ships [hidden], never revealed).
page.goto(app_url + "/")
_wait_header_settled_anonymous(page)
for nav in NAV_IDS:
assert page.locator(nav).count() == 1, f"{nav} missing from the chat header"
expect(page.locator(nav)).to_be_hidden()
assert page.locator(nav + "[hidden]").count() == 1, (
f"{nav} must stay [hidden] for anonymous"
)
# Admin: the same links are revealed — the exact contract the
# steering toggle mirrored before it was removed.
login(page, app_url, next="/")
_wait_header_settled_admin(page)
for nav in NAV_IDS:
expect(page.locator(nav)).to_be_visible()