- 21-role-based-ui: tighten the Settings link locator. The previous
`getByRole('link', { name: /settings/i }).first().or(getByText(/.../) .first())`
chain hit a strict-mode violation once the sidebar Admin section became
default-expanded — both the section header text node and the Settings
link matched. Match the link directly with exact: true.
- 26-residential: extend smoke with two API-driven specs covering the
residential interest pipeline — create+list and detail-page render —
using preferences-string stamp + heading match for assertions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Failures were mostly stale selectors, not product regressions:
- .or() traps matching the topbar "+ New" button → use specific names
(Add Webhook, New Field, New Template)
- broad /create|add|new/ patterns → same fix
- [role="dialog"] overlay matched before content → getByRole('dialog').last()
- locator('input') picked hidden Radix Select inputs → getByPlaceholder /
getByRole('combobox', { name })
- 11-global-search rewritten for the inline topbar search (the cmdk
CommandDialog the old tests targeted was replaced)
- missing .first() causing strict-mode failures on notifications heading,
version history text, nav links
- dashboard landing test: no h1 exists, target KPI text instead
- activity-feed: items aren't anchors; match action badge text
- monitoring data-leak check scoped to <main> (sidebar has Email/Documents)
- admin API without port context returns 400 (not 403) for non-admins —
accept 400 as a valid "blocked" status in the sales-agent test
Also dropped dead imports and unused locals surfaced by lint-staged.
Full suite: 124 passed (11.2m).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>