Debug Test
When to use
- When a Playwright test fails after generate-tests
- When running as part of
run-testing-sessionpipeline (after generate-tests FAIL) - When a previously passing test starts failing after a UI change
Inputs
- Failing test file path
- Full error output from the test run
docs/playwright-spec-testing/exploration/[SCENARIO_SLUG].md— original selectorsdocs/playwright-spec-testing/test-plan.md— scenario contextdocs/playwright-spec-testing/project-context.md— for baseURL
What it does
Diagnose the failure and apply a minimal fix. Debug in this order:
- Is the app running?
curl [BASE_URL]If connection refused, report NEEDS_CONTEXT — the orchestrator must ask the user to start the app. - Has the selector changed? Open the browser, find the element, check if the selector in the test still matches.
npx playwright open [BASE_URL] - Timing wrong? Look for non-standard loading patterns (SSR hydration, lazy routes).
- Wrong assertion? Navigate to the final state and check the actual URL/text.
- Exploration stale? Compare the exploration report against the current DOM for each failing step.
Apply minimal fix:
- Stale selector: Update only the broken line with the correct selector from the live browser
- Timing: Add
waitForonly if Playwright auto-waiting is genuinely insufficient - Wrong assertion value: Update only the assertion with the correct observed value
- Strict mode violation: Make selector more specific using
.first()or a better role/name combination - App not running: Report NEEDS_CONTEXT
After fixing, run the test:
npx playwright test [TEST_FILE_PATH] --headed --reporter=listIf test passes, update test-plan.md:
### Status
- [x] Planned
- [x] Explored
- [x] Generated
- [x] PassingKey Rules
- NEVER rewrite the whole test — minimal fix only
- NEVER add page.waitForTimeout()
- NEVER change passing assertions while fixing failing ones
- If the fix requires re-exploring the scenario from scratch, report BLOCKED
Output
- Updated test file (minimal changes)
- Updated
docs/playwright-spec-testing/test-plan.md(if test now passes)
Report when done:
- Status: DONE | BLOCKED | NEEDS_CONTEXT
- Root cause identified
- What was changed (file:line)
- Test result after fix: PASS or FAIL (include error if still failing)