SKILL.md
Arguments: $FEATURE (or "all" to test entire app)
Read CLAUDE.md before doing anything else. Read docs/PRD.md for acceptance criteria. Read docs/SCREENS.md for the full screen inventory. If wireframes/ exists, read wireframes/INDEX.html for expected layouts.
PREREQUISITE CHECK: 1. Confirm the dev server is running (if not, start it) 2. Confirm Playwright MCP is available (browser_navigate tool exists) 3. If $FEATURE is specified, identify every screen and flow for that feature 4. If "all", use docs/SCREENS.md as the full checklist
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PHASE 1 — SCREEN-BY-SCREEN VISUAL WALKTHROUGH ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
For EVERY screen listed in docs/SCREENS.md (or the feature subset):
1. browsernavigate to the screen's URL 2. browsertakescreenshot — save as qa/browser-tests/$FEATURE/[screen]-initial.png 3. browsersnapshot — capture the accessibility tree 4. VERIFY against the wireframe or PRD: - Are all expected elements present? (buttons, inputs, links, text) - Is the layout correct? (sidebar on left, header at top, etc.) - Are labels and text content correct? - Is the navigation functional? (links go where they should) 5. Log findings to qa/browser-tests/$FEATURE/walkthrough.md: | Screen | URL | Status | Missing Elements | Layout Issues | Notes |
DO NOT SKIP SCREENS. Every screen in the inventory must be visited.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PHASE 2 — INTERACTION TESTING (every clickable element) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
For EVERY screen, systematically test every interactive element:
BUTTONS: - browser_click every button on the page - Verify: correct action happens (navigation, modal, form submit, state change) - Verify: button is visible, has accessible name, is not disabled unexpectedly
FORMS: - browser_type into every input field - Test valid data → verify success state - Test empty submission → verify validation messages appear - Test invalid data (wrong format, too long, special characters) → verify error handling - Test form reset / cancel
NAVIGATION: - browserclick every link - Verify: correct destination screen loads - browsernavigateback → verify you return to the previous screen - browsernavigate_forward → verify forward works
DROPDOWNS / SELECT: - browserselectoption for each dropdown - Verify: correct option selected, dependent UI updates
MODALS / OVERLAYS: - Trigger every modal (click the button that opens it) - Verify: modal appears with correct content - browserpresskey Escape → verify modal closes - Click outside modal → verify it closes (if designed to) - Test modal form submission
KEYBOARD NAVIGATION: - browserpresskey Tab through the entire page - Verify: focus order is logical (top to bottom, left to right) - Verify: all interactive elements receive focus - browserpresskey Enter on focused buttons → verify they activate - browserpresskey Space on checkboxes → verify they toggle
Log every interaction result to qa/browser-tests/$FEATURE/interactions.md: | Element | Action | Expected Result | Actual Result | Pass/Fail |
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PHASE 3 — HAPPY PATH END-TO-END FLOWS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Read the P0 Happy Path from docs/PRD.md. For EACH Given/When/Then:
1. Navigate to the starting point 2. Execute the exact user journey described: - browsertype to fill forms - browserclick to submit / navigate - browserwaitfor expected outcomes 3. browsertakescreenshot at each step 4. Verify the "Then" condition is met: - browserverifytextvisible for expected messages - browserverifyelementvisible for expected UI changes - browser_snapshot to confirm state changes in the a11y tree 5. Save screenshots as flow sequence: qa/browser-tests/$FEATURE/flow-[name]-step-[N].png
ALSO TEST THESE VARIANTS OF EACH HAPPY PATH: - What happens if the user refreshes mid-flow? - What happens if the user navigates away and comes back? - What happens with the minimum valid input? - What happens with the maximum valid input?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PHASE 4 — EMPTY STATES & ERROR STATES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
EMPTY STATES (for every screen that displays a list or data): 1. Navigate to the screen with no data (new user or cleared state) 2. browsertakescreenshot 3. Verify: helpful empty state message is shown (not a blank page or error) 4. Verify: there is a clear call-to-action to add first item 5. browser_click the CTA → verify it works
ERROR STATES: 1. Network error: Use browserevaluate to intercept fetch and simulate offline ``javascript window.originalFetch = window.fetch; window.fetch = () => Promise.reject(new Error('Network error')); ` 2. Trigger an action that requires network → verify graceful error message 3. Restore network: `javascript window.fetch = window.originalFetch; `` 4. Server error: Use browserevaluate to mock 500 responses 5. Auth error: Navigate to a protected route without auth → verify redirect to login
browsertakescreenshot for every error state. Verify: no raw error messages, stack traces, or blank screens shown to user.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PHASE 5 — RESPONSIVE TESTING (3 viewports) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
For the 3 most important screens (identified from PRD P0 features):
DESKTOP (1440 × 900): browserresize width=1440 height=900 Navigate to each screen browsertakescreenshot → qa/browser-tests/$FEATURE/responsive/[screen]-desktop.png browsersnapshot → verify all elements visible Verify: layout uses full width appropriately
TABLET (768 × 1024): browserresize width=768 height=1024 Navigate to each screen browsertakescreenshot → qa/browser-tests/$FEATURE/responsive/[screen]-tablet.png browsersnapshot → verify all elements still accessible Verify: navigation adapts (hamburger menu if applicable) Verify: no horizontal scrollbar Verify: text is readable, buttons are tappable size (≥44px)
MOBILE (375 × 812): browserresize width=375 height=812 Navigate to each screen browsertakescreenshot → qa/browser-tests/$FEATURE/responsive/[screen]-mobile.png browsersnapshot → verify all elements still accessible Verify: no content cut off or overlapping Verify: forms are usable (inputs full-width, keyboard doesn't obscure) Verify: touch targets are ≥44px Test the happy path on mobile — complete the main flow at this viewport
ALSO CHECK: - Landscape mobile (812 × 375): browserresize and screenshot - Very narrow (320px): browserresize width=320 and check nothing breaks
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PHASE 6 — ACCESSIBILITY AUDIT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
For EVERY screen:
1. browser_snapshot — capture the full accessibility tree 2. Analyze the tree for: - Every image must have alt text (or role="presentation" if decorative) - Every form input must have an associated label - Every button must have an accessible name - Heading hierarchy must be logical (h1 → h2 → h3, no skipping) - Color contrast: if design tokens exist, verify text/background ratios - ARIA roles are used correctly (not aria-label on divs that should be buttons) - Focus indicators are visible (Tab through and verify)
3. Log accessibility findings to qa/browser-tests/$FEATURE/accessibility.md: | Screen | Issue | Severity | Element | Recommendation |
Severity levels: CRITICAL — screen reader users cannot complete the task MAJOR — significantly degraded experience for assistive tech users MINOR — best practice violation, not blocking
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PHASE 7 — CONSOLE & NETWORK HEALTH CHECK ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
While on each screen during testing:
browserconsolemessages — check for: - Any JavaScript errors (red) → log as bugs - Any unhandled promise rejections → log as bugs - Deprecation warnings → log as technical debt - Any sensitive data logged to console → log as security issue
browsernetworkrequests — check for: - Any failed requests (4xx, 5xx) → log as bugs - Any requests to unexpected domains → log as security concern - Any excessively large responses (>1MB for API calls) → log as performance issue - Any requests without proper auth headers when auth is required
Save to: qa/browser-tests/$FEATURE/health.md
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PHASE 8 — AUTO-GENERATE PLAYWRIGHT TEST FILES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
THIS IS THE KEY STEP. Convert every interaction you just tested into permanent, repeatable Playwright test files.
For each flow and interaction tested above:
1. Use browsergenerateplaywright_test to create a .spec.ts file from the browser session
2. If the generated test needs refinement, manually write it using the selectors discovered via browsersnapshot and browsergenerate_locator
3. Save generated tests to: tests/e2e/$FEATURE-ui.spec.ts — happy path + interaction tests tests/e2e/$FEATURE-responsive.spec.ts — responsive viewport tests tests/e2e/$FEATURE-a11y.spec.ts — accessibility assertions tests/e2e/$FEATURE-errors.spec.ts — error state tests
4. EVERY test must use semantic locators only: ALLOWED: getByRole('button', { name: 'Submit' }) ALLOWED: getByLabel('Email') ALLOWED: getByText('Welcome back') ALLOWED: getByTestId('transaction-list') FORBIDDEN: page.$('.class-name') FORBIDDEN: page.$('#id') FORBIDDEN: page.$x('//xpath')
5. Run every generated test: npx playwright test tests/e2e/$FEATURE-ui.spec.ts npx playwright test tests/e2e/$FEATURE-responsive.spec.ts npx playwright test tests/e2e/$FEATURE-a11y.spec.ts npx playwright test tests/e2e/$FEATURE-errors.spec.ts
6. Fix any failing tests — the test should pass since you just verified the behavior interactively. If it fails: - Selector issue → use browsergeneratelocator to find stable selector - Timing issue → add proper await and toBeVisible() waits - Real bug → log to qa/bugs/
7. Run the FULL test suite to confirm nothing else broke: npx playwright test
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PHASE 9 — COVERAGE REPORT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Generate qa/browser-tests/$FEATURE/REPORT.md:
## UI Test Report: $FEATURE Generated: [date]
### Summary
| Metric | Count | Pass | Fail |
|---|---|---|---|
| Screens tested | |||
| Interactive elements | |||
| Happy path flows | |||
| Empty states | |||
| Error states | |||
| Responsive viewports | |||
| Accessibility issues | |||
| Console errors found | |||
| Tests generated | |||
| Tests passing |
### Generated Test Files - tests/e2e/$FEATURE-ui.spec.ts ([N] tests) - tests/e2e/$FEATURE-responsive.spec.ts ([N] tests) - tests/e2e/$FEATURE-a11y.spec.ts ([N] tests) - tests/e2e/$FEATURE-errors.spec.ts ([N] tests)
### Issues Found [List every bug, accessibility issue, or UI problem discovered]
### Screenshots [Reference all screenshots taken during testing]
### Coverage Assessment - Screens with 100% element coverage: [list] - Screens with gaps: [list with what's missing] - Flows fully tested: [list] - Flows partially tested: [list with what's missing]
━━━ FINAL OUTPUT ━━━
If all tests pass: "UI testing complete for $FEATURE. [N] screens tested, [N] interactions verified, [N] test files generated. All [N] generated Playwright tests passing. Report: qa/browser-tests/$FEATURE/REPORT.md Next: run /qa-run $FEATURE for the full QA loop."
If issues found: "UI testing complete for $FEATURE. Found [N] bugs, [N] accessibility issues, [N] console errors. [N] tests generated, [N] passing, [N] failing. Report: qa/browser-tests/$FEATURE/REPORT.md Fix issues first, then run /qa-run $FEATURE."