cypress-debugger
SKILL.md
Cypress Failed Test Debugger
Diagnose Cypress test failures from mochawesome or JUnit report files. Classifies root causes and provides concrete fixes.
Prerequisites: Generate Report First
Do NOT rely on Cypress stdout — use a structured reporter instead:
# mochawesome (recommended)
cypress run --reporter mochawesome --reporter-options "reportDir=cypress/reports,json=true,html=false"
# JUnit (CI-friendly)
cypress run --reporter junit --reporter-options "mochaFile=cypress/reports/results.xml"
Phase 1: Extract Failures
# Find report if path not specified
find . -name "mochawesome.json" -path "*/cypress/*" | head -5
find . -name "*.xml" -path "*/cypress/*" | head -5
# Extract failed tests from mochawesome (jq)
cat cypress/reports/mochawesome.json | jq '[
.. | objects |
select(.fail == true) |
{title: .title, fullTitle: .fullTitle, duration: .duration, error: .err.message, stack: .err.estack}
]'
# Extract failed tests (node fallback)
node -e "
const r = require('./cypress/reports/mochawesome.json');
const flat = (s) => [...(s.tests||[]), ...(s.suites||[]).flatMap(flat)];
r.results.flatMap(flat)
.filter(t => t.fail)
.forEach(t => console.log('FAIL', t.fullTitle, '\n ', t.err?.message?.slice(0,120)))
"
# Extract failed tests from JUnit XML (node)
node -e "
const fs = require('fs');
const xml = fs.readFileSync('./cypress/reports/results.xml', 'utf-8');
const failures = [...xml.matchAll(/<testcase[^>]+name=\"([^\"]+)\"[^>]*>[\s\S]*?<failure[^>]*message=\"([^\"]+)\"/g)];
failures.forEach(([,name,msg]) => console.log('FAIL', name, '\n ', msg.slice(0,120)));
"
Phase 2: Classify Root Cause
Use Phase 1 output (error message + duration) to classify. Most failures are identifiable here — only go to Phase 3 if still unclear.
| # | Category | Signals | Review Pattern |
|---|---|---|---|
| F1 | Flaky / Timing | Timed out retrying, duration near defaultCommandTimeout, passes on retry |
#9a |
| F2 | Selector Broken | Expected to find element: '...' but never found it, cy.get() failed |
#6, #10 |
| F3 | Network Dependency | cy.intercept() not matched, XHR failed, unexpected API response |
— |
| F4 | Assertion Mismatch | expected X to equal Y, AssertionError |
#4 |
| F5 | Missing Then | Action completed but wrong state remains | #2 |
| F6 | Condition Branch Missing | Element conditionally present, assertion always runs | #5 |
| F7 | Test Isolation Failure | Passes alone, fails in suite; leaked state via cy.session or cookies |
— |
| F8 | Environment Mismatch | CI vs local only; baseUrl, viewport, OS differences | — |
| F9 | Data Dependency | Missing seed data, hardcoded IDs, cy.fixture() mismatch |
— |
| F10 | Auth / Session | cy.session() expired, role-based UI not rendered |
— |
| F11 | Async Order Assumption | .then() chain order, parallel cy.request() race |
— |
| F12 | Selector Drift | DOM changed, custom command or Page Object selector not updated | #10 |
| F13 | Error Swallowing | cy.on('uncaught:exception', () => false) hiding failures |
#3 |
| F14 | Animation Race | Element visible but content not yet rendered; CSS transition not complete | #9a |
Classification steps:
- Match error message to signals above
durationneardefaultCommandTimeout(4s) → F1 or F2- CI-only failure → F7 or F8
- Passes on retry → F1
Phase 3: Screenshot & Video Analysis (only if Phase 2 is unclear)
Cypress automatically captures screenshots on failure and optionally records video.
# Find screenshots for failed tests
find cypress/screenshots -name "*.png" | head -20
# Find videos
find cypress/videos -name "*.mp4" | head -10
Progressive disclosure — stop as soon as root cause is clear:
# 1. Check screenshot path from mochawesome report
cat cypress/reports/mochawesome.json | jq '[
.. | objects | select(.fail == true) |
{title: .title, screenshots: [.context? // empty | .. | strings | select(endswith(".png"))]}
]'
# 2. Check for JS errors in report context
cat cypress/reports/mochawesome.json | jq '[
.. | objects | select(.fail == true) | .err.estack // empty
] | .[]' 2>/dev/null | head -50
# 3. Still unclear — inspect screenshot via browser agent
# → open cypress/screenshots/<spec>/<test name> (failed).png and compare
# → check cypress/videos/<spec>.mp4 for full run context
Phase 4: Fix Suggestions
## [P0/P1/P2] `test name`
- **Category:** F2 — Selector Broken
- **Error:** `Expected to find element: '.submit-btn', but never found it`
- **Root Cause:** Button selector too broad after DOM refactor
- **Fix:**
```javascript
// before
cy.get('.submit-btn').click();
// after
cy.get('[data-testid="login-submit"]').click();
**Severity:**
- **P0:** Test passes silently when feature is broken (F6, F13)
- **P1:** Intermittent or misleading failures (F1, F2, F3, F7, F11, F14)
- **P2:** Consistent failures, straightforward fix (F4, F5, F8, F9, F10, F12)
## Output Format
```markdown
## Failure Summary
- Total: N failed (M flaky, K broken, J environment)
## [P0] `test name` — F13 Error Swallowing
...
## Review Summary
| Sev | Count | Top Category | Files |
|-----|-------|-------------|-------|
| P0 | 1 | Error Swallowing | auth.cy.ts |
| P1 | 3 | Flaky / Timing | dashboard.cy.ts |
| P2 | 2 | Selector Drift | settings.cy.ts |
Fix P0 first. Run `cypress run --spec <file> --headed` to reproduce locally.
Weekly Installs
14
Repository
dididy/e2e-skillsFirst Seen
5 days ago
Security Audits
Installed on
opencode14
gemini-cli14
claude-code14
github-copilot14
codex14
kimi-cli14