Establish systematic confidence in UI behavior through the right mix of visual regression, interaction testing, and accessibility assertions.
Treat testing as a design input, not a post-ship safety net. The goal is not maximum coverage; it is catching the bugs that matter most without drowning the team in maintenance.
Consult the accessibility testing reference when the testing strategy needs automated axe checks, screen reader validation, or keyboard traversal tests.
Consult the component accessibility reference when testing custom components for focus management, ARIA correctness, and keyboard behavior.
Consult the interaction design reference when validating workflows under stress, error, or edge-case conditions.
Consult the error-recovery reference when testing validation behavior, recoverable field errors, or abandonment paths.
Consult the loading feedback and perceived performance reference when testing loading states, skeletons, stale-data cues, or perceived-performance behavior.
MANDATORY PREPARATION
Users start this workflow with /test. Once this skill is active, load $frontend-design — it contains design principles, anti-patterns, and the Context Gathering Protocol. Follow that protocol before proceeding — if no design context exists yet, you MUST load $setup first. Additionally gather: the most common UI bugs currently escaping to production, the team's tolerance for test maintenance, and which parts of the UI change most frequently.
Assess Testing Needs
Identify what is breaking and what should be caught:
Map bug escape routes:
- Visual regressions (unintended layout shifts, broken spacing, missing assets)
- Interaction failures (buttons that do nothing, broken forms, dead links)
- State bugs (stale data, race conditions, incorrect loading states)
- Accessibility defects (missing labels, keyboard traps, color contrast failures)
- Cross-browser or cross-device inconsistencies
Evaluate current coverage:
- What is already tested? What is tested but provides no signal?
- Which tests fail randomly and get ignored (flaky tests erode trust)
- How long does the test suite take? Slow suites get bypassed.
Prioritize by risk and churn:
- High-traffic user paths (checkout, signup, core workflows)
- UI surfaces that change frequently (design-system components)
- Areas with known historical bugs
- Accessibility-critical surfaces (forms, navigation, modals)
Testing Dimensions
Visual Regression
Catch unintended visual changes before they ship.
What to capture:
- Component states (default, hover, focus, active, disabled, loading, error)
- Full-page layouts at representative breakpoints
- Cross-browser rendering differences (focus styles, form controls, fonts)
Baseline discipline:
- Treat baselines as team assets, not personal screenshots
- Review intentional changes in pull requests, not after merge
- Re-baseline immediately after intentional design updates to prevent noise
Anti-flake practices:
- Wait for fonts, images, and animations to settle before capturing
- Mock or freeze dynamic content (timestamps, random data, animations)
- Use deterministic test data and fixed viewport sizes
- Isolate tests from network variability; stub API responses
Scope boundaries:
- Test design-system components exhaustively
- Test page layouts at a few key breakpoints, not every pixel width
- Do not test third-party widgets you do not control (embeds, ads)
Interaction Testing
Validate that user actions produce correct outcomes.
Component-level interactions:
- Form submission, validation, and error recovery
- Modal open/close, focus trapping, and escape behavior
- Dropdown, accordion, tab, and disclosure state transitions
- Button actions and their side effects
User flow validation:
- Multi-step workflows (checkout, onboarding, wizard flows)
- Navigation and routing behavior
- State persistence across browser back/forward
- Concurrent actions (rapid clicking, double submissions)
Test data strategy:
- Use realistic but deterministic data
- Cover edge cases (empty inputs, maximum lengths, special characters)
- Include error-state responses, not just happy-path stubs
Accessibility Assertions
Embed accessibility validation into the testing pipeline.
Automated checks (run on every build):
- axe-core or equivalent for WCAG rule violations
- Color contrast minimums (4.5:1 normal text, 3:1 large text / UI components)
- Semantic HTML validation (heading order, landmark regions, label associations)
- Focus management (visible focus indicators, logical tab order)
Keyboard traversal tests:
- Tab through entire flows without a mouse
- Validate that all interactive elements are reachable
- Confirm that focus traps in modals and escape routes work
- Test that skip links and bypass blocks function
Screen reader smoke tests (for critical paths):
- Announcement of dynamic content changes (live regions)
- Meaningful accessible names and descriptions
- State announcements (expanded/collapsed, selected, required)
- Error messaging that surfaces to assistive technology
Motion and animation:
- Verify
prefers-reduced-motion is respected
- Confirm no seizure-inducing flashing (under 3 flashes per second)
Test Pyramid for UI
Balance speed, confidence, and maintenance cost:
| Layer |
Scope |
Speed |
Purpose |
| Unit (component) |
Single component, mocked dependencies |
Fast (< 1s) |
Logic, rendering, prop handling |
| Integration (component + context) |
Component with real providers, stubs |
Medium (< 10s) |
Interaction behavior, state transitions |
| End-to-end (full browser) |
Real browser, real network or stubs |
Slow (< 30s per test) |
Critical user flows, cross-page behavior |
| Visual regression |
Screenshot comparison |
Medium (parallelizable) |
Unintended visual changes |
Guidance:
- Push tests down the pyramid when possible. A component test is faster and more precise than an E2E test for button behavior.
- Reserve E2E for user journeys that span multiple pages or require real browser behavior (routing, auth, payment).
- Run visual regression in CI on every pull request, not just before release.
Tool Selection
Match the tool to the team's stack and the testing layer:
| Need |
Strong options |
Considerations |
| Component unit/integration |
Vitest + Testing Library, Jest + Testing Library |
Framework-agnostic; prefer Testing Library queries that mirror user behavior |
| End-to-end critical flows |
Playwright, Cypress |
Playwright for speed and cross-browser parallelism; Cypress for simpler setup |
| Visual regression |
Chromatic, Loki, Playwright screenshots, Percy |
Chromatic for Storybook integration; Playwright for in-house baseline management |
| Accessibility automation |
axe-core, @axe-core/react, Playwright + axe |
Integrate into CI; treat as warnings, not blockers, until baseline is clean |
| Interaction / user flow |
Playwright, Cypress, Storybook Test Runner |
Storybook Test Runner for isolated component interactions; Playwright/Cypress for full flows |
Pragmatic rules:
- Prefer one E2E tool and one component test tool. Tool proliferation fragments expertise.
- If the project uses Storybook, add interaction tests there before adding a separate component test suite.
- Integrate accessibility checks into the existing test runner, not as a separate tool chain.
Anti-Patterns
- Test implementation details: Assert on what the user sees and does, not internal state or CSS class names.
- Ignore flaky tests: A flaky test is worse than no test. Fix or delete it immediately.
- Test everything through E2E: Slow suites discourage running tests. Push logic down to component tests.
- Snapshot everything: Snapshot tests catch changes but do not explain intent. Use them sparingly for markup stability, not for behavior.
- Separate accessibility testing from the main pipeline: Accessibility checks that run manually once per sprint find nothing consistently.
- Mock the browser environment: Use a real browser for E2E and visual regression. jsdom and happy-dom are fine for component logic, not for layout or interaction fidelity.
- Test third-party widgets: Do not baseline or assert on embeds, maps, ads, or chat widgets you do not control.
- Skip cross-browser testing: At minimum verify focus styles, form controls, and layout in the browsers your users actually use.
- Leave baselines stale: An outdated baseline hides regressions. Re-baseline after intentional visual changes.
Verify Testing Confidence
Before shipping the testing strategy:
1---
2name: test
3description: Build or improve a UI testing strategy covering visual regression, interaction testing, and accessibility assertions. Use when the user asks to add tests, set up testing, fix flaky tests, improve test coverage, validate UI behavior, catch visual bugs, or establish confidence in shipping frontend changes.
4metadata:
5 argument-hint: "[target]"
6---
7
8Establish systematic confidence in UI behavior through the right mix of visual regression, interaction testing, and accessibility assertions.
9
10Treat testing as a design input, not a post-ship safety net. The goal is not maximum coverage; it is catching the bugs that matter most without drowning the team in maintenance.
11
12Consult the [accessibility testing](../frontend-design/reference/accessibility-testing.md) reference when the testing strategy needs automated axe checks, screen reader validation, or keyboard traversal tests.
13Consult the [component accessibility](../frontend-design/reference/component-accessibility.md) reference when testing custom components for focus management, ARIA correctness, and keyboard behavior.
14Consult the [interaction design](../frontend-design/reference/interaction-design.md) reference when validating workflows under stress, error, or edge-case conditions.
15Consult the [error-recovery](../frontend-design/reference/error-recovery.md) reference when testing validation behavior, recoverable field errors, or abandonment paths.
16Consult the [loading feedback and perceived performance](../frontend-design/reference/loading-feedback-and-perceived-performance.md) reference when testing loading states, skeletons, stale-data cues, or perceived-performance behavior.
17
18## MANDATORY PREPARATION
19
20Users start this workflow with `/test`. Once this skill is active, load $frontend-design — it contains design principles, anti-patterns, and the **Context Gathering Protocol**. Follow that protocol before proceeding — if no design context exists yet, you MUST load $setup first. Additionally gather: the most common UI bugs currently escaping to production, the team's tolerance for test maintenance, and which parts of the UI change most frequently.
21
22## Assess Testing Needs
23
24Identify what is breaking and what should be caught:
25
261. **Map bug escape routes**:
27 - Visual regressions (unintended layout shifts, broken spacing, missing assets)
28 - Interaction failures (buttons that do nothing, broken forms, dead links)
29 - State bugs (stale data, race conditions, incorrect loading states)
30 - Accessibility defects (missing labels, keyboard traps, color contrast failures)
31 - Cross-browser or cross-device inconsistencies
32
332. **Evaluate current coverage**:
34 - What is already tested? What is tested but provides no signal?
35 - Which tests fail randomly and get ignored (flaky tests erode trust)
36 - How long does the test suite take? Slow suites get bypassed.
37
383. **Prioritize by risk and churn**:
39 - High-traffic user paths (checkout, signup, core workflows)
40 - UI surfaces that change frequently (design-system components)
41 - Areas with known historical bugs
42 - Accessibility-critical surfaces (forms, navigation, modals)
43
44## Testing Dimensions
45
46### Visual Regression
47
48Catch unintended visual changes before they ship.
49
50**What to capture**:
51- Component states (default, hover, focus, active, disabled, loading, error)
52- Full-page layouts at representative breakpoints
53- Cross-browser rendering differences (focus styles, form controls, fonts)
54
55**Baseline discipline**:
56- Treat baselines as team assets, not personal screenshots
57- Review intentional changes in pull requests, not after merge
58- Re-baseline immediately after intentional design updates to prevent noise
59
60**Anti-flake practices**:
61- Wait for fonts, images, and animations to settle before capturing
62- Mock or freeze dynamic content (timestamps, random data, animations)
63- Use deterministic test data and fixed viewport sizes
64- Isolate tests from network variability; stub API responses
65
66**Scope boundaries**:
67- Test design-system components exhaustively
68- Test page layouts at a few key breakpoints, not every pixel width
69- Do not test third-party widgets you do not control (embeds, ads)
70
71### Interaction Testing
72
73Validate that user actions produce correct outcomes.
74
75**Component-level interactions**:
76- Form submission, validation, and error recovery
77- Modal open/close, focus trapping, and escape behavior
78- Dropdown, accordion, tab, and disclosure state transitions
79- Button actions and their side effects
80
81**User flow validation**:
82- Multi-step workflows (checkout, onboarding, wizard flows)
83- Navigation and routing behavior
84- State persistence across browser back/forward
85- Concurrent actions (rapid clicking, double submissions)
86
87**Test data strategy**:
88- Use realistic but deterministic data
89- Cover edge cases (empty inputs, maximum lengths, special characters)
90- Include error-state responses, not just happy-path stubs
91
92### Accessibility Assertions
93
94Embed accessibility validation into the testing pipeline.
95
96**Automated checks** (run on every build):
97- axe-core or equivalent for WCAG rule violations
98- Color contrast minimums (4.5:1 normal text, 3:1 large text / UI components)
99- Semantic HTML validation (heading order, landmark regions, label associations)
100- Focus management (visible focus indicators, logical tab order)
101
102**Keyboard traversal tests**:
103- Tab through entire flows without a mouse
104- Validate that all interactive elements are reachable
105- Confirm that focus traps in modals and escape routes work
106- Test that skip links and bypass blocks function
107
108**Screen reader smoke tests** (for critical paths):
109- Announcement of dynamic content changes (live regions)
110- Meaningful accessible names and descriptions
111- State announcements (expanded/collapsed, selected, required)
112- Error messaging that surfaces to assistive technology
113
114**Motion and animation**:
115- Verify `prefers-reduced-motion` is respected
116- Confirm no seizure-inducing flashing (under 3 flashes per second)
117
118## Test Pyramid for UI
119
120Balance speed, confidence, and maintenance cost:
121
122| Layer | Scope | Speed | Purpose |
123|-------|-------|-------|---------|
124| Unit (component) | Single component, mocked dependencies | Fast (< 1s) | Logic, rendering, prop handling |
125| Integration (component + context) | Component with real providers, stubs | Medium (< 10s) | Interaction behavior, state transitions |
126| End-to-end (full browser) | Real browser, real network or stubs | Slow (< 30s per test) | Critical user flows, cross-page behavior |
127| Visual regression | Screenshot comparison | Medium (parallelizable) | Unintended visual changes |
128
129**Guidance**:
130- Push tests down the pyramid when possible. A component test is faster and more precise than an E2E test for button behavior.
131- Reserve E2E for user journeys that span multiple pages or require real browser behavior (routing, auth, payment).
132- Run visual regression in CI on every pull request, not just before release.
133
134## Tool Selection
135
136Match the tool to the team's stack and the testing layer:
137
138| Need | Strong options | Considerations |
139|------|----------------|----------------|
140| Component unit/integration | Vitest + Testing Library, Jest + Testing Library | Framework-agnostic; prefer Testing Library queries that mirror user behavior |
141| End-to-end critical flows | Playwright, Cypress | Playwright for speed and cross-browser parallelism; Cypress for simpler setup |
142| Visual regression | Chromatic, Loki, Playwright screenshots, Percy | Chromatic for Storybook integration; Playwright for in-house baseline management |
143| Accessibility automation | axe-core, @axe-core/react, Playwright + axe | Integrate into CI; treat as warnings, not blockers, until baseline is clean |
144| Interaction / user flow | Playwright, Cypress, Storybook Test Runner | Storybook Test Runner for isolated component interactions; Playwright/Cypress for full flows |
145
146**Pragmatic rules**:
147- Prefer one E2E tool and one component test tool. Tool proliferation fragments expertise.
148- If the project uses Storybook, add interaction tests there before adding a separate component test suite.
149- Integrate accessibility checks into the existing test runner, not as a separate tool chain.
150
151## Anti-Patterns
152
153- **Test implementation details**: Assert on what the user sees and does, not internal state or CSS class names.
154- **Ignore flaky tests**: A flaky test is worse than no test. Fix or delete it immediately.
155- **Test everything through E2E**: Slow suites discourage running tests. Push logic down to component tests.
156- **Snapshot everything**: Snapshot tests catch changes but do not explain intent. Use them sparingly for markup stability, not for behavior.
157- **Separate accessibility testing from the main pipeline**: Accessibility checks that run manually once per sprint find nothing consistently.
158- **Mock the browser environment**: Use a real browser for E2E and visual regression. jsdom and happy-dom are fine for component logic, not for layout or interaction fidelity.
159- **Test third-party widgets**: Do not baseline or assert on embeds, maps, ads, or chat widgets you do not control.
160- **Skip cross-browser testing**: At minimum verify focus styles, form controls, and layout in the browsers your users actually use.
161- **Leave baselines stale**: An outdated baseline hides regressions. Re-baseline after intentional visual changes.
162
163## Verify Testing Confidence
164
165Before shipping the testing strategy:
166
167- [ ] The highest-risk user flows have automated coverage
168- [ ] Visual baselines are reviewed in pull requests
169- [ ] Accessibility checks run in CI and have a clean or documented-exceptions baseline
170- [ ] Flaky tests are identified and either fixed or removed
171- [ ] The full test suite runs in under the team's patience threshold (target: < 5 minutes for CI feedback)
172- [ ] Test failures produce actionable error messages, not opaque stack traces
173- [ ] Cross-browser coverage matches actual user browser distribution
174- [ ] Team members can run tests locally without complex setup
175- [ ] Test data is deterministic and does not depend on external services during test execution