cypress-debugger
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.
More from dididy/e2e-test-reviewer
e2e-test-reviewer
Use when reviewing, auditing, or improving existing E2E test specs. Triggers on tasks like "review tests", "improve test quality", "audit specs", "check test scenarios", "check coverage gaps". Detects naming-assertion mismatch, missing Then, error swallowing, always-passing assertions, boolean traps, conditional bypass, raw DOM queries, render-only tests, duplicate scenarios, misleading names, over-broad assertions, subject-inversion, hard-coded timeouts, flaky patterns, and YAGNI violations in Page Objects.
12e2e-reviewer
Use when reviewing, auditing, or improving E2E test specs for Playwright or Cypress — static code analysis of existing test files, not diagnosing runtime failures. Triggers on "review my tests", "audit test quality", "find weak tests", "my tests always pass but miss bugs", "tests pass CI but miss regressions", "improve playwright tests", "improve cypress tests", "check test coverage gaps", "my tests are fragile", "tests break on every UI change", "test suite is hard to maintain", "we have coverage but bugs still slip through", "flaky tests", "test anti-patterns", "check my e2e tests", "tests pass locally but fail in CI". Detects 13 anti-patterns -- name-assertion mismatch, missing Then, error swallowing (.catch in POM via grep; try/catch in specs via LLM; Cypress uncaught:exception suppression), always-passing assertions (one-shot booleans, Locator-as-truthy, toBeAttached, timeout:0, one-shot URL), bypass patterns (conditional assertions + force:true), raw DOM queries, focused test leak (test.only committed), missing assertions (dangling locators + boolean result discarded), hard-coded sleeps (P1), flaky test patterns (positional selectors + serial ordering), YAGNI + zombie specs (unused POM members, single-use Util wrappers, zombie spec files), expect.soft() overuse. Also runs supplementary grep checks for general code quality issues (missing auth setup, inconsistent POM usage, hardcoded credentials, missing await, deprecated page API, networkidle).
10playwright-debugger
Use when Playwright tests have actually failed and you need to diagnose runtime failures — from a playwright-report directory, local or CI. Triggers on "debug playwright tests", "why did playwright tests fail", "playwright CI failure", "flaky playwright test failures", "playwright timeout error", "tests pass locally but fail in CI", "analyze playwright-report", "PR failing in CI". Classifies runtime failures into root causes (not static code analysis) and suggests concrete fixes.
8playwright-test-generator
Use when generating new Playwright E2E tests from scratch. Triggers on "generate playwright tests", "write e2e tests for X", "add playwright coverage for X", "create test for X page", "generate tests for the login page". Autonomous mode starts from coverage gap analysis when no target is specified; argument mode targets a specific page or feature directly. Explores the live app via Playwright CLI or agent-browser, designs scenarios with user approval via Plan Mode, auto-detects project structure (POM vs flat spec), runs YAGNI audit and e2e-reviewer after generation, and hands off to playwright-debugger after 3 failed fix attempts.
1