CI(ui): make sidebar click_nav() locate via data-sidebar=menu-button + has-text

The Chat UI Tests CI run failed at "nav 'New Chat' not found": the
get_by_role("button", name="New Chat") path doesn't always match
because SidebarMenuButton wraps the visible label in a <span> that
the accessibility-name calculation can lose track of when the sidebar
is in a collapsed/icon-only state.

Try, in order:
  1. [data-sidebar="menu-button"]:has-text("New Chat") -- the
     shadcn-ui SidebarMenuButton renders with this attribute.
  2. role=button, name=re.compile(...) -- the existing path.
  3. button:has-text("New Chat") -- last-resort.

The first locator works regardless of sidebar collapse state because
data-sidebar="menu-button" is part of the component contract, not
the visual layout.
This commit is contained in:
Daniel Han 2026-05-07 05:19:35 +00:00
commit 99f4efefdd

View file

@ -635,13 +635,33 @@ with sync_playwright() as p:
# 10. Sidebar nav: New Chat, Compare, Search, Recipes.
# ─────────────────────────────────────────────────────
def click_nav(label, expected_url_pat = None):
btn = page.get_by_role(
"button", name = re.compile(rf"^\s*{label}\s*$", re.I)
).first
if btn.count() == 0:
# Try, in order: data-sidebar=menu-button with text, role+name,
# button with text. Sidebar items render as SidebarMenuButton
# (data-sidebar="menu-button") containing a <span> with the
# label; the role+name path fails when the sidebar collapses
# to icon-only mode and the visible text gets visually hidden.
candidates = [
page.locator(
f'[data-sidebar="menu-button"]:has-text("{label}")'
).first,
page.get_by_role(
"button", name = re.compile(rf"^\s*{label}\s*$", re.I),
).first,
page.locator(f'button:has-text("{label}")').first,
]
btn = None
for c in candidates:
if c.count() > 0:
btn = c
break
if btn is None:
soft_fail(f"nav '{label}' not found")
return False
btn.click()
try:
btn.click()
except Exception as exc:
soft_fail(f"nav '{label}' click failed: {exc!r}")
return False
page.wait_for_timeout(800)
if expected_url_pat and not re.search(expected_url_pat, page.url):
soft_fail(