feat(ui): rename nav items — "Sources" becomes "RAG", "Git sources" becomes "Sources"

Owner request (2026-08-28): the two admin-only nav items read like the
same thing, so they are relabeled — the document-catalog link
(#nav-sources, /sources.html) becomes "RAG" and the source-manager link
(#nav-git-sources, /git-sources.html) becomes "Sources".

Phase 48 (48_nav_rename_sources), label-only per the locked decision:
- all six pages (index, sources, git-sources, tuning, document, login):
  the two <a> texts swap; ids, hrefs, hidden defaults, is-active /
  aria-current placement, and nav order (Chat, RAG, Sources, Tuning)
  are byte-unchanged otherwise.
- header.js: comment/docstring label mentions only — the reveal-by-id
  logic is untouched (ship-hidden/reveal contract intact).
- test_git_sources_admin.py / test_mobile_hamburger_nav.py: the two
  suites that asserted the old label text are updated; comment-only
  label fixes in test_shared_header.py / test_nav_consistency.py.
- tests/e2e/test_nav_rename_sources.py: the story E2E (green in
  isolation) — renamed labels + unchanged hrefs/order/markers on all
  six pages, click navigation with the active marker, the anonymous
  ship-hidden contract, and regression guards for the untouched
  controls (#sync-label "Sync sources", viewer #doc-back "Sources").
- All eight surrounding header/nav suites stay green in isolation;
  unit+integration green, app/ coverage 99% (frontend-only change),
  ruff + pyright clean.

Note: per this phase file-level staging, the six page files and
header.js also carry the same-day in-flight owner rework that was
already in the working tree when phase 48 ran (mobile sign-in dropdown
copy, sync button ship-hidden on the Sources page); the label rename
itself is the two-text swap on each page.
This commit is contained in:
2026-08-28 12:33:18 -04:00
parent 03bead092c
commit 872a07cee7
17 changed files with 785 additions and 118 deletions
+19 -10
View File
@@ -32,7 +32,7 @@ Test → story mapping (Playwright Mapping Rule):
3. ``test_admin_menu_contents`` — admin at 375px: the menu shows all
four links (the whoami reveal works inside the menu).
4. ``test_link_click_navigates_and_closes`` — admin at 375px: clicking
"Sources" navigates to /sources.html and the menu on the arrival
"RAG" navigates to /sources.html and the menu on the arrival
page ships closed.
5. ``test_esc_and_outside_close`` — Esc closes AND returns focus to the
toggle; an outside click does NOT close (accepted — see the test
@@ -58,7 +58,7 @@ MOBILE: ViewportSize = {"width": 375, "height": 812} # the story's phone viewpo
DESKTOP: ViewportSize = {"width": 1280, "height": 800} # the conftest page size
NAV_LINKS = ("#app-nav a[href='/']", "#nav-sources", "#nav-git-sources", "#nav-tuning")
LINK_TEXTS = ("Chat", "Sources", "Git sources", "Tuning")
LINK_TEXTS = ("Chat", "RAG", "Sources", "Tuning")
def _mobile_page(browser: Browser) -> Page:
@@ -67,16 +67,25 @@ def _mobile_page(browser: Browser) -> Page:
def _wait_settled_anonymous(page: Page) -> None:
"""Wait until whoami has resolved for the anonymous visitor (Sign in
visible — the phase-16 settled state the header pins)."""
expect(page.locator("#sign-in-link")).to_be_visible(timeout=10_000)
"""Wait until whoami has resolved for the anonymous visitor: the bar
Sign in copy (``#sign-in-link``) loses its ship-hidden attribute —
the phase-16 settled state, probed by attribute (not visibility):
at ≤640px the bar copy is CSS-hidden behind the ``#sign-in-link-mobile``
dropdown copy (phase 46), so visibility is viewport-dependent."""
page.wait_for_function(
"() => !document.querySelector('#sign-in-link').hasAttribute('hidden')",
timeout=10_000,
)
def _wait_settled_admin(page: Page) -> None:
"""Wait until whoami has resolved for the admin (Sign out visible)
AND the whoami reveal has un-hidden the admin-only nav links (the
menu-contents assertions must run on a settled auth state)."""
expect(page.locator("#sign-out-btn")).to_be_visible(timeout=10_000)
"""Wait until whoami has resolved for the admin: the whoami reveal
has un-hidden the admin-only nav links (the menu-contents assertions
must run on a settled auth state). The nav link is the
viewport-independent settled signal — the sign-out control is the
bar copy on desktop but the #sign-out-btn-mobile dropdown copy at
≤640px (phase-46 UX revision), so it is not a cross-viewport
probe."""
page.wait_for_function(
"() => !document.querySelector('#nav-sources').hasAttribute('hidden')",
timeout=10_000,
@@ -205,7 +214,7 @@ def test_admin_menu_contents(
browser: Browser, app_url: str, db_ready: None
) -> None:
"""AC2 (admin): at 375px the opened menu shows ALL FOUR links —
Chat / Sources / Git sources / Tuning — i.e. the whoami reveal
Chat / RAG / Sources / Tuning — i.e. the whoami reveal
works inside the menu exactly as it does inline (one <nav>, one
set of links, the same hidden attributes header.js drives)."""
page = _mobile_page(browser)