Fragile locators in Playwright?
See your frontend's testability score.
A page.locator() that worked yesterday throws strict mode violation: resolved to 2 elements today.
The locator isn't the problem — the frontend never gave it a unique hook. selfcure reads your source,
scores every component for testability, flags locators that resolve to multiple nodes, and ships
data-testid fixes as a Pull Request — the preventive step before Playwright Test Agents take over.
Root cause
"Resolved to 2 elements" is a frontend bug
Playwright's strict mode is doing you a favor: it refuses to guess which of two matching nodes you meant. But the fix belongs in the frontend, not in a longer CSS chain. Two patterns cause most of it:
Weak locator
No data-testid, id, or role-accessible name, so you fall back to .locator('.btn') — which breaks the moment styling changes.
Ambiguous locator
The best available locator matches a sibling too. Strict mode throws; non-strict silently picks the wrong node. selfcure catches this at the AST level.
selfcure scores and fixes both before your suite — or the Planner / Generator / Healer agents — ever run.
Before / after
From CSS guesswork to getByTestId
✗ Fragile — strict mode violation waiting to happen
// resolves to 2 elements → throws, or picks wrong node
await page.locator('.btn-primary').click()
await page.locator('form input').first().fill('a@b.com')
✓ Stable — unique by contract
// data-testid added by a selfcure PR
await page.getByTestId('submit').click()
await page.getByTestId('email').fill('a@b.com')
selfcure suggests the values, dedupes collisions across siblings, and opens the PR on GitHub or GitLab.
How it works
Preventive, then hand off to the agents
Measure testability
Every interactive element gets a 0–100 score on selector stability — a quantifiable metric for your tech lead.
Find ambiguity
selfcure detects locators that resolve to multiple nodes and proposes a unique data-testid — the strict-mode failure, prevented.
Feed the agents
Once the PR lands, @playwright/mcp + Planner / Generator / Healer work against a frontend they can actually target.
Get going
Score your frontend in two commands
# From your app's root — Node 20+
npx @selfcure/cli init
npx @selfcure/cli lint # score + flag ambiguous locators
Connect it to your AI editor (free)
# MCP server — Cursor, Claude Code, VS Code, Windsurf
npx @selfcure/cli mcp
Your AI assistant can query the testability score and ambiguity findings directly — the same data the Playwright agents benefit from.
Team tier
The Team plan adds a web dashboard with score history, automatic PR comments, and branch comparison — proof that your frontend is getting more testable over time.
FAQ
Playwright + selfcure
Does selfcure replace Playwright Test Agents?
No — it feeds them. selfcure is preventive: it makes the frontend testable so the Planner, Generator, and Healer have stable selectors to work with.
Does it work with my React / Vue / Angular app?
Yes. The crawler parses .tsx, .jsx, .vue, Angular .component.ts, and plain .html.
How is this different from a longer CSS locator?
A longer locator is more brittle, not less. selfcure adds a stable data-testid at the source so the locator stays short and unique.
Is it really free?
The CLI, testability score, and MCP server are free and open source. Auto-fix, PR opening, and the history dashboard are paid.