Skip to content

Commit 6e43345

Browse files
committed
test: add Playwright accessibility testing POC for Badge and Status Light
Implements automated accessibility testing using two complementary approaches: 1. ARIA Snapshot Testing - Captures and validates accessibility tree structure - Detects unintended changes to component semantics - Serves as living documentation of expected a11y structure 2. aXe Rule Validation - Automated WCAG 2.0/2.1 Level A/AA compliance checking - Excludes best-practice rules (focused on component testing) - Validates color contrast, ARIA attributes, and more Test Coverage (14/14 passing, ~6s runtime): - Badge: default, icons, semantic variants, color contrast - Status Light: sizes (s/m/l), disabled state, color contrast Key Implementation Details: - Integrated with existing Storybook stories (no duplication) - Element visibility waits (reliable, fast) - WCAG-only scanning (appropriate for isolated components) - HTML report generation for debugging Files Added: - first-gen/playwright.config.ts - Playwright configuration - first-gen/test/playwright-a11y/aria-snapshots.spec.ts - ARIA tests - first-gen/test/playwright-a11y/axe-validation.spec.ts - aXe tests - first-gen/test/playwright-a11y/README.md - Documentation - RFC_A11Y_TESTING.md - Comprehensive RFC with scaling plan - README.A11Y.md - Quick start guide Usage: yarn test:a11y # Run all accessibility tests yarn test:a11y:ui # Open Playwright UI for debugging yarn test:a11y:1st # Run only 1st gen yarn test:a11y:2nd # Run only 2nd gen
1 parent 502ffc8 commit 6e43345

18 files changed

+1130
-1
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ chromatic-build-*.xml
137137
chromatic-diagnostics*.json
138138
chromatic.config.json
139139

140+
# Playwright test reports (generated)
141+
first-gen/test/playwright-a11y/report/
142+
143+
# Playwright test results (generated)
144+
playwright-report/
145+
test-results/
146+
140147
# yarn
141148
.pnp.*
142149
.yarn/*

README.A11Y.md

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Playwright Accessibility Testing - Proof of Concept
2+
3+
Branch: `cdransfeldt/test-playwright-aria-snapshots`
4+
5+
## What This Demonstrates
6+
7+
Two complementary approaches to accessibility testing using Playwright:
8+
9+
1. **ARIA Snapshots** - Test accessibility tree structure for regressions
10+
2. **aXe-core Validation** - Automated WCAG 2.0/2.1/2.2 compliance checking
11+
12+
Focused on **Badge** and **Status Light** components as proof of concept.
13+
14+
## Quick Start
15+
16+
```bash
17+
cd first-gen
18+
19+
# Install Playwright
20+
npx playwright install chromium
21+
22+
# Run tests (starts Storybook automatically)
23+
yarn test:a11y
24+
25+
# View results
26+
open test/playwright-a11y/report/index.html
27+
```
28+
29+
## What's Included
30+
31+
### Test Files
32+
33+
- `aria-snapshots.spec.ts` - Accessibility tree regression tests
34+
- `axe-validation.spec.ts` - Automated WCAG rule validation
35+
36+
### Components Tested
37+
38+
- Badge (default, variants, with icons, color contrast)
39+
- Status Light (status variants, disabled states, ARIA)
40+
- Additional examples (Button, Checkbox, Tabs, etc.)
41+
42+
### Configuration
43+
44+
- Updated `playwright.config.ts` to support a11y tests
45+
- Added `test:a11y` and `test:a11y:ui` npm scripts
46+
- Auto-starts Storybook on port 8080
47+
48+
## Example Tests
49+
50+
### ARIA Snapshot (Regression Test)
51+
52+
```typescript
53+
test('badge accessibility tree should not change', async ({ page }) => {
54+
await page.goto(
55+
'http://localhost:8080/iframe.html?id=badge--positive&viewMode=story'
56+
);
57+
const badge = page.locator('sp-badge').first();
58+
await expect(badge).toMatchAriaSnapshot();
59+
});
60+
```
61+
62+
### aXe Validation (Rule Check)
63+
64+
```typescript
65+
test('badge should pass WCAG checks', async ({ page }) => {
66+
await page.goto(
67+
'http://localhost:8080/iframe.html?id=badge--positive&viewMode=story'
68+
);
69+
const results = await new AxeBuilder({ page }).analyze();
70+
expect(results.violations).toEqual([]);
71+
});
72+
```
73+
74+
## Commands
75+
76+
```bash
77+
yarn test:a11y # Run all tests
78+
yarn test:a11y:ui # Interactive UI mode
79+
yarn test:a11y --update # Update snapshots
80+
```
81+
82+
## Files Changed
83+
84+
```
85+
first-gen/
86+
├── playwright.config.ts (scans all packages for *.a11y.spec.ts)
87+
└── package.json (added scripts)
88+
89+
packages/badge/test/
90+
├── badge.a11y.spec.ts (Badge tests: ARIA + aXe)
91+
├── badge.a11y.spec.ts-snapshots/ (ARIA baselines)
92+
├── a11y-helpers.ts (shared helpers)
93+
└── README-A11Y.md (guide)
94+
95+
packages/status-light/test/
96+
├── status-light.a11y.spec.ts (Status Light tests)
97+
└── status-light.a11y.spec.ts-snapshots/
98+
99+
(Pattern works for 1st and 2nd gen components)
100+
```
101+
102+
## Why This Approach?
103+
104+
-**Automated** - Catches issues before they ship
105+
-**Regression tests** - ARIA snapshots prevent breaking changes
106+
-**Standards-based** - aXe-core checks against WCAG guidelines
107+
-**CI-ready** - Integrates into existing pipelines
108+
-**Lightweight** - Minimal setup, maximum value
109+
110+
## Next Steps
111+
112+
1. Run the tests: `yarn test:a11y`
113+
2. Review the examples in `test/playwright-a11y/`
114+
3. Add tests for other components using the same patterns
115+
4. Integrate into CI/CD pipeline
116+
117+
## Resources
118+
119+
- [Playwright ARIA Snapshots](https://playwright.dev/docs/aria-snapshots)
120+
- [Playwright Accessibility Testing](https://playwright.dev/docs/accessibility-testing)
121+
- [aXe-core Documentation](https://github.com/dequelabs/axe-core)

RFC_A11Y_TESTING.md

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# RFC: Playwright accessibility testing POC
2+
3+
## Overview
4+
5+
This RFC proposes adding automated accessibility testing to Spectrum Web Components using Playwright. This POC demonstrates two complementary approaches:
6+
7+
1. **ARIA snapshot testing** - Captures and validates the accessibility tree structure
8+
2. **aXe rule validation** - Automated WCAG compliance checking
9+
10+
## Motivation
11+
12+
- **Catch regressions early**: Automated tests prevent accessibility issues from reaching production
13+
- **Shift left**: Identify accessibility problems during development, not after release
14+
- **Complement manual testing**: Automation covers ~30-40% of WCAG rules, freeing QA for complex scenarios
15+
- **Living documentation**: ARIA snapshots serve as accessibility specifications
16+
17+
## Implementation
18+
19+
### Components tested (POC)
20+
21+
- **Badge**: Simple component with semantic variants
22+
- **Status Light**: Component with size variants and states
23+
24+
### Test structure
25+
26+
```
27+
first-gen/
28+
├── playwright.config.ts # Playwright configuration
29+
├── package.json # Added @axe-core/playwright + test scripts
30+
└── test/playwright-a11y/
31+
├── README.md # Quick start guide
32+
├── aria-snapshots.spec.ts # ARIA tree snapshot tests
33+
└── axe-validation.spec.ts # aXe WCAG compliance tests
34+
```
35+
36+
### Key decisions
37+
38+
**1. WCAG-only scanning**
39+
40+
- Excludes best-practice rules (e.g., "page must have h1")
41+
- Focuses on WCAG 2.0/2.1 Level A/AA compliance
42+
- Reasoning: We test isolated components, not full pages
43+
44+
**2. Element visibility waits**
45+
46+
- Waits for specific elements before testing
47+
- More reliable than `waitForLoadState('networkidle')`
48+
- Faster test execution
49+
50+
**3. Storybook integration**
51+
52+
- Tests run against existing Storybook stories
53+
- No duplication of component setup
54+
- Leverages existing isolation
55+
56+
## Running tests
57+
58+
```bash
59+
# Install dependencies (if needed)
60+
cd first-gen && yarn install
61+
62+
# Run all accessibility tests
63+
yarn test:a11y
64+
65+
# Run with UI (great for debugging)
66+
yarn test:a11y:ui
67+
68+
# Run specific test file
69+
yarn test:a11y aria-snapshots.spec.ts
70+
```
71+
72+
## Test results
73+
74+
### Current POC status
75+
76+
**14/14 tests passing**
77+
78+
- 6 ARIA snapshot tests
79+
- Badge (default, icons, semantic variants)
80+
- Status Light (sizes, disabled state)
81+
- 8 aXe validation tests
82+
- Badge (default, semantic, icons, color contrast)
83+
- Status Light (sizes, disabled, color contrast)
84+
85+
### Example ARIA snapshot
86+
87+
```yaml
88+
- text: Default
89+
```
90+
91+
On first run, Playwright creates baseline snapshots. Subsequent runs compare against these baselines, failing if the accessibility tree changes unexpectedly.
92+
93+
### Example aXe validation
94+
95+
```typescript
96+
const accessibilityScanResults = await new AxeBuilder({ page })
97+
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
98+
.analyze();
99+
100+
expect(accessibilityScanResults.violations).toEqual([]);
101+
```
102+
103+
Automatically checks ~50+ accessibility rules per component.
104+
105+
## Benefits
106+
107+
### For developers
108+
109+
- **Fast feedback**: Catch issues in seconds, not days
110+
- **Clear failures**: Tests explain what's wrong and how to fix it
111+
- **No setup needed**: Tests use existing Storybook stories
112+
113+
### For QA
114+
115+
- **Focus on complex scenarios**: Automation handles repetitive checks
116+
- **Regression prevention**: Tests run on every PR
117+
- **Documentation**: ARIA snapshots show expected structure
118+
119+
### For the project
120+
121+
- **Scalable**: Easy to add new components
122+
- **CI-ready**: Runs in headless mode on CircleCI
123+
- **Low maintenance**: Tests update with component changes
124+
125+
## Scaling plan
126+
127+
### Phase 1: Core components (POC) ✅
128+
129+
- Badge
130+
- Status Light
131+
132+
### Phase 2: High-priority components
133+
134+
- Button (all variants)
135+
- Textfield, Checkbox, Radio (form controls)
136+
- Dialog, Tooltip (overlays)
137+
138+
### Phase 3: Complex components
139+
140+
- Action Menu (interactive)
141+
- Tabs (keyboard navigation)
142+
- Tables (ARIA grid patterns)
143+
144+
### Phase 4: Integration
145+
146+
- Add to CI pipeline
147+
- Set up Playwright test reporting
148+
- Create accessibility dashboard
149+
150+
## Testing approach comparison
151+
152+
| Method | Coverage | Speed | Setup | Best for |
153+
| ------------------ | -------- | ----- | ----- | -------------------- |
154+
| **Manual** | 100% | Slow | High | Complex interactions |
155+
| **ARIA snapshots** | ~40% | Fast | Low | Structure validation |
156+
| **aXe validation** | ~50% | Fast | Low | WCAG compliance |
157+
| **Screen readers** | 100% | Slow | High | User experience |
158+
159+
**Recommendation**: Use all four methods for comprehensive coverage.
160+
161+
## Open questions
162+
163+
1. **Should we test all Storybook stories or create dedicated a11y stories?**
164+
- Current: Using existing stories
165+
- Pro: No duplication
166+
- Con: Stories may not cover all a11y scenarios
167+
168+
2. **How do we handle components that require user interaction?**
169+
- Current: Manual clicks in tests (e.g., Action Menu)
170+
- Alternative: Playwright interactions built into tests
171+
172+
3. **Should ARIA snapshot failures block PRs?**
173+
- Pro: Prevents unintentional accessibility changes
174+
- Con: May be too strict for rapid iteration
175+
176+
4. **Integration with existing test suite?**
177+
- Option A: Keep separate (`yarn test:a11y`)
178+
- Option B: Integrate with main test suite (`yarn test`)
179+
180+
## Next steps
181+
182+
1. **Review this POC** - Get feedback from team
183+
2. **Expand to Phase 2 components** - Button, form controls
184+
3. **Add to CI** - Run on every PR
185+
4. **Document patterns** - Create guide for adding new tests
186+
5. **Train team** - Workshop on writing accessibility tests
187+
188+
## Resources
189+
190+
- [Playwright Accessibility Testing](https://playwright.dev/docs/accessibility-testing)
191+
- [ARIA Snapshots Documentation](https://playwright.dev/docs/aria-snapshots)
192+
- [aXe-core Rules](https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md)
193+
- [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
194+
195+
## Success metrics
196+
197+
- **Coverage**: % of components with automated a11y tests
198+
- **Violations caught**: # of issues found before reaching QA
199+
- **Test stability**: % of test runs that pass consistently
200+
- **Developer adoption**: # of PRs including new a11y tests
201+
202+
## Conclusion
203+
204+
This POC demonstrates that automated accessibility testing with Playwright is:
205+
206+
-**Feasible**: 14 tests running successfully
207+
-**Fast**: ~6 seconds for full suite
208+
-**Maintainable**: Tests use existing Storybook stories
209+
-**Valuable**: Catches real accessibility issues
210+
211+
**Recommendation**: Proceed with Phase 2 expansion to high-priority components.

first-gen/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@
7070
"storybook:quick": "run-p build:watch storybook:run",
7171
"storybook:run": "web-dev-server --config wds-storybook.config.js",
7272
"test": "yarn test:focus unit",
73+
"test:a11y": "playwright test",
74+
"test:a11y:ui": "playwright test --ui",
75+
"test:a11y:1st": "playwright test --project=1st-gen",
76+
"test:a11y:2nd": "playwright test --project=2nd-gen",
7377
"test:bench": "yarn build:tests && node test/benchmark/cli.js",
7478
"test:changed": "node ./scripts/test-changes.js",
7579
"test:ci": "yarn test:start",
@@ -96,6 +100,7 @@
96100
"react/*"
97101
],
98102
"devDependencies": {
103+
"@axe-core/playwright": "^4.11.0",
99104
"@changesets/changelog-github": "0.5.1",
100105
"@changesets/cli": "2.29.7",
101106
"@commitlint/cli": "19.8.1",

0 commit comments

Comments
 (0)