Automated Accessibility Testing Guide
Overview
This guide explains how to use the automated accessibility testing integrated into the Fawkes platform CI/CD pipeline. The system uses axe-core and Lighthouse CI to ensure WCAG 2.1 AA compliance for all components.
Table of Contents
- Quick Start
- Testing Tools
- Running Tests Locally
- CI/CD Integration
- Understanding Test Results
- Fixing Violations
- Dashboard and Metrics
- Troubleshooting
Quick Start
Run All Accessibility Tests
cd design-system
npm run accessibility:full
Run Only Axe-Core Tests
cd design-system
npm run test:a11y
Run Only Lighthouse CI
cd design-system
npm run build-storybook
npm run lighthouse:ci
Testing Tools
Axe-Core
axe-core is a fast, lightweight accessibility testing engine that runs automated WCAG 2.0, 2.1, and Section 508 accessibility tests.
What it tests:
- Color contrast
- ARIA attributes
- Semantic HTML
- Keyboard navigation
- Form labels
- Image alt text
- And 90+ other rules
Lighthouse CI
Lighthouse CI provides automated auditing, performance metrics, and best practices for web pages.
What it tests:
- Accessibility score (0-100)
- WCAG compliance
- Best practices
- SEO fundamentals
Running Tests Locally
Prerequisites
cd design-system
npm install
Run Axe-Core Tests
# Run all accessibility tests
npm run test:a11y
# Run in watch mode for development
npm run test:watch -- --testPathPattern=a11y
# Run with coverage report
npm run test:coverage
Run Lighthouse CI
# Build Storybook first
npm run build-storybook
# Run Lighthouse CI
npm run lighthouse:ci
# Or run individual commands
npm run lighthouse:collect
npm run lighthouse:assert
Writing Accessibility Tests
Create tests for your components using jest-axe:
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
import { MyComponent } from './MyComponent';
expect.extend(toHaveNoViolations);
describe('MyComponent Accessibility', () => {
it('should have no accessibility violations', async () => {
const { container } = render(<MyComponent />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
it('should be keyboard accessible', async () => {
const { container } = render(<MyComponent />);
const results = await axe(container, {
rules: {
'keyboard-access': { enabled: true }
}
});
expect(results).toHaveNoViolations();
});
});
CI/CD Integration
GitHub Actions
Accessibility tests run automatically on:
- Every pull request
- Push to main branch
- Daily at 9 AM UTC (scheduled)
- Manual workflow dispatch
Workflow: .github/workflows/accessibility-testing.yml
Jenkins Pipeline
For services using the Golden Path pipeline, add accessibility testing:
@Library('fawkes-pipeline-library') _
goldenPathPipeline {
appName = 'my-service'
language = 'node'
// ... other config
}
// Add accessibility stage after unit tests
stage('Accessibility Tests') {
steps {
accessibilityTest {
runAxeCore = true
runLighthouse = true
wcagLevel = 'AA'
failOnViolations = true
lighthouseScoreThreshold = 90
}
}
}
Quality Gates
The pipeline enforces these quality gates:
| Gate | Threshold | Action |
|---|---|---|
| Axe-Core Tests | 0 violations | ❌ Fail build |
| Lighthouse Score | ≥ 90/100 | ❌ Fail build |
| WCAG 2.1 AA | Must comply | ❌ Fail build |
| Color Contrast | 4.5:1 text, 3:1 large | ❌ Fail build |
Understanding Test Results
Axe-Core Results
Violations are categorized by severity:
- Critical: Serious accessibility issues that must be fixed immediately
- Serious: Major accessibility problems that significantly impact users
- Moderate: Noticeable accessibility issues
- Minor: Small accessibility improvements
Example output:
❌ 2 violations found:
1. color-contrast (serious)
- Element: <button class="btn-primary">Submit</button>
- Description: Element's background color could not be determined due to a background image
- Fix: Ensure sufficient color contrast (4.5:1 for normal text)
- More info: https://dequeuniversity.com/rules/axe/4.8/color-contrast
2. label (critical)
- Element: <input type="text" id="email">
- Description: Form element does not have an associated label
- Fix: Add a <label> element or aria-label attribute
- More info: https://dequeuniversity.com/rules/axe/4.8/label
Lighthouse Results
Lighthouse provides a score from 0-100:
- 90-100: ✅ Good (meets WCAG 2.1 AA)
- 70-89: ⚠️ Needs improvement
- 0-69: ❌ Poor (does not meet requirements)
Reports include:
- Overall accessibility score
- Detailed audit results
- Opportunities for improvement
- Passed audits
Fixing Violations
Common Violations and Fixes
1. Missing Alt Text
Problem:
<img src="logo.png" />
Fix:
<img src="logo.png" alt="Company logo" />
2. Poor Color Contrast
Problem:
.text {
color: #999;
background: #fff;
/* Contrast ratio: 2.85:1 (fails) */
}
Fix:
.text {
color: #666;
background: #fff;
/* Contrast ratio: 5.74:1 (passes) */
}
3. Missing Form Labels
Problem:
<input type="email" id="email" />
Fix:
<label htmlFor="email">Email Address</label> <input type="email" id="email" />
Or use aria-label:
<input type="email" aria-label="Email Address" />
4. Invalid ARIA Attributes
Problem:
<div role="button" aria-pressed="yes">Click me</div>
Fix:
<button aria-pressed="true">Click me</button>
5. Missing Keyboard Access
Problem:
<div onClick="{handleClick}">Clickable</div>
Fix:
<button onClick="{handleClick}">Clickable</button>
Or make div keyboard accessible:
<div role="button" tabindex="{0}" onClick="{handleClick}" onKeyPress="{(e)" ="">
e.key === 'Enter' && handleClick()} > Clickable
</div>
Testing Your Fixes
- Make the fix in your component
- Run tests locally:
npm run test:a11y - Verify the specific test passes
- Commit and push
- Check CI results
Dashboard and Metrics
Grafana Dashboard
Access the accessibility dashboard at:
https://grafana.fawkes.idp/d/accessibility
Dashboard features:
- Overall accessibility score trend
- Test pass/fail rate
- Violations by severity
- Violations by component
- WCAG 2.1 AA compliance status
- Historical metrics
Prometheus Metrics
Query these metrics in Prometheus:
# Accessibility score
lighthouse_accessibility_score
# Test pass rate
sum(accessibility_tests_passed) / sum(accessibility_tests_total)
# Critical violations
sum(axe_critical_violations)
# Violations by component
sum by (component) (axe_component_violations)
# WCAG compliance status
wcag_aa_compliance_status
Troubleshooting
Tests Pass Locally But Fail in CI
Cause: Environment differences, missing dependencies, or timing issues.
Solution:
- Check CI logs for specific errors
- Ensure all dependencies are in
package.json - Run tests with CI flag locally:
npm run test:a11y:ci - Check for race conditions in async tests
Lighthouse Score is Lower Than Expected
Cause: Storybook build issues, network problems, or threshold too high.
Solution:
- Build Storybook locally and inspect:
npm run build-storybook npx http-server storybook-static - Check Lighthouse report for specific issues
- Review
lighthouserc.jsonconfiguration - Temporarily lower threshold while fixing issues
False Positives
Cause: Axe-core might flag valid patterns as violations.
Solution:
- Review the violation carefully
- Check if it's a legitimate issue
- If it's a false positive, add to
.axerc.json:{ "rules": { "rule-id": { "enabled": false } } } - Document why you disabled the rule
GitHub Actions Workflow Failing
Cause: Workflow configuration issues or missing secrets.
Solution:
- Check workflow logs in GitHub Actions
- Verify all required secrets are set
- Check file paths are correct
- Ensure Node version is compatible
- Re-run workflow after fixes
Jenkins Pipeline Hanging
Cause: Lighthouse might be waiting for user input or timing out.
Solution:
- Check Jenkins console output
- Increase timeout in
lighthouserc.json:{ "ci": { "collect": { "numberOfRuns": 1 } } } - Use headless mode in Jenkins agent
Resources
WCAG Guidelines
Tools Documentation
Learning Resources
Browser Extensions
Getting Help
If you need help with accessibility testing:
- Check this documentation
- Review existing test examples in
design-system/src/ - Check the A11y Project
- Ask in
#accessibilitySlack channel - Create an issue with the
accessibilitylabel
Contributing
To improve accessibility testing:
- Add more comprehensive tests
- Update test utilities
- Improve documentation
- Share learnings with the team
- Propose new quality gates
Last Updated: 2025-12-24 Maintained By: Fawkes Platform Team