selfcure
selfcure × Cypress

Your Cypress tests are flaky?
The problem may not be the test.

You rewrite the same cy.get() for the third time this sprint. The test isn't wrong — your frontend has no stable hook to grab. selfcure reads your React/Vue/Angular source, scores every component for testability, finds the selectors that resolve to the wrong element, and ships data-testid fixes as a Pull Request — so your Cypress suite stops guessing.

Root cause

Flaky isn't random — it's an unstable frontend

When a Cypress test fails intermittently, the instinct is to add a cy.wait() or a retry. But the recurring cause is the selector: it points at a class, an index, or text that the frontend never promised to keep stable. Two failure modes dominate:

Weak selector

The element has no data-testid, id, or aria-label. Cypress falls back to a CSS class like .btn-primary that a refactor or a styling change silently breaks.

Ambiguous selector

The selector matches more than one element in the same view. Cypress grabs the first match — until the order changes and it grabs the wrong one. This is the failure runtime retries can't fix.

selfcure catches both at the source — before they reach your Cypress run.

Before / after

From brittle CSS to a stable contract

✗ Brittle — selector breaks on refactor

// matches .btn-primary AND the sibling toolbar button
cy.get('.btn-primary').click()
cy.get('form > div:nth-child(2) input').type('a@b.com')

✓ Stable — selector survives change

// data-testid added by a selfcure PR
cy.get('[data-testid="submit"]').click()
cy.get('[data-testid="email"]').type('a@b.com')

selfcure proposes the data-testid values, dedupes collisions across siblings, and opens the PR. Your frontend team reviews and merges — the fix lives where the bug is.

How it works

Three steps, zero new test framework

01 · SCORE

Measure testability

Static AST analysis scores every interactive element 0–100 on selector stability. You get a number you can show a tech lead.

02 · FLAG

Find ambiguity

selfcure detects selectors that resolve to multiple siblings — the exact thing that makes Cypress flaky — and suggests a unique data-testid.

03 · SHIP

Open a PR

Pick the fixes in the web UI, click once. selfcure branches, commits, pushes, and opens a Pull Request on GitHub or GitLab.

Get going

Scan your frontend in two commands

# From your app's root — Node 20+
npx @selfcure/cli init
npx @selfcure/cli lint   # score + flag ambiguous selectors

Connect it to your AI editor (free)

# MCP server — Cursor, Claude Code, VS Code, Windsurf
npx @selfcure/cli mcp

Your AI assistant can now query the testability score and the ambiguous-selector findings directly.

Team tier

The Team plan adds a web dashboard with score history, automatic PR comments, and branch-to-branch comparison — so you can prove your frontend is getting more testable over time, not just today.

Read the getting-started guide →

FAQ

Cypress + selfcure

Does selfcure run or generate my Cypress tests?

No. selfcure analyzes your frontend source. Your Cypress suite stays exactly as it is — it just gets stable data-testid selectors to target.

Will 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 Cypress retries or cy.wait()?

Retries paper over the symptom. selfcure removes the cause — the unstable or ambiguous selector — at the frontend source, so the test doesn't need to retry.

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.