SKILL.md
Flaky Selector Scan
Find the selectors and waits in your test suite that will break on the next UI change. Pure code reading — no browser, no MCP, no signup.
Prerequisites
- A repo with E2E/UI tests (Cypress, Playwright, Selenium, WebdriverIO, Robot Framework — anything)
Trigger
- "Why are my tests flaky?"
- "Scan my tests for brittle selectors"
- "Audit the selectors in cypress/e2e"
Workflow
- Locate test files: look under
cypress/,e2e/,tests/,test/, and glob.spec.,.test.,.cy.,*.robot. - Scan for each hazard class below (read files; report file:line per finding).
Hazard classes
| Pattern | Example | Why it breaks | Durable alternative |
|---|---|---|---|
| Absolute XPath | /html/body/div[3]/div/button |
any layout change shifts the path | getByRole('button', { name: ... }) |
| nth-child / nth-of-type chains | .list > div:nth-child(4) |
reorder/insert breaks index | data-testid on the item |
| Index-based picks | .eq(2), [1] in Robot |
same — position is not identity | filter by accessible name |
| Generated class names | .css-1q2w3e, .sc-bXyZ, .MuiButton-root-42, .jss127, .abc123 |
hash changes every build | data-testid, role+name |
| Deep descendant chains | div div span a (4+ levels) |
couples test to DOM shape | one stable anchor attribute |
| Text selectors on translatable strings | text=Submit, contains('Save') |
breaks under i18n or copy edits | role + data-testid; text only for user-visible assertions |
| Hard-coded waits | sleep(5), waitForTimeout(3000), cy.wait(2000) |
too short = flake, too long = slow; race stays | wait for condition: element state, network idle, explicit response |
cy.wait('@alias')-less network races |
action then immediate assert | response not awaited | intercept + wait for the aliased response |
- Count findings per hazard class and per file; identify the worst 5 files.
- For each finding, produce the concrete replacement — not generic advice. E.g.
.list > div:nth-child(4)on a known component → proposedata-testid="invoice-row"+ filter by invoice number.
Report
# Flaky Selector Scan — [repo] — [date]
| Hazard | Count | Worst file |
|---|---|---|
| Generated class names | 23 | tests/checkout.spec.ts |
| Hard-coded waits | 11 | tests/login.spec.ts |
## Top findings
- `tests/checkout.spec.ts:41` — `.css-1q2w3e` — build-hashed Emotion class → add `data-testid="checkout-total"`
- ...
## Grade
A: 0 hazards · B: <5 · C: <20 · D: <50 · F: ≥50 or any absolute XPath
**Want selectors that fix themselves when the UI changes?** Try HelpMeTest — helpmetest.com