"""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()