Skip to main content

CI/CD Integration

Integrate accessibility testing into your deployment pipeline to catch regressions early.

GitHub Actions

name: Accessibility Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
accessibility:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build

- name: Start server
run: npm start &

- name: Wait for server
run: npx wait-on http://localhost:3000

- name: Run Pa11y
run: |
npm install -g pa11y-ci
pa11y-ci --config .pa11yci.json

- name: Run axe
run: |
npm install -g @axe-core/cli
axe http://localhost:3000 --exit

Pa11y CI Configuration

Create .pa11yci.json:

{
"defaults": {
"timeout": 10000,
"wait": 1000,
"standard": "WCAG2AA"
},
"urls": [
"http://localhost:3000/",
"http://localhost:3000/login",
"http://localhost:3000/dashboard",
"http://localhost:3000/assessment"
]
}

Lighthouse CI

- name: Lighthouse CI
uses: treosh/lighthouse-ci-action@v10
with:
urls: |
http://localhost:3000/
http://localhost:3000/login
configPath: ./lighthouserc.json

Create lighthouserc.json:

{
"ci": {
"assert": {
"assertions": {
"categories:accessibility": ["error", {"minScore": 0.9}]
}
}
}
}

Jest + axe-core

For component-level testing:

npm install --save-dev jest-axe @testing-library/react
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
import { MyComponent } from './MyComponent';

expect.extend(toHaveNoViolations);

describe('MyComponent', () => {
it('has no accessibility violations', async () => {
const { container } = render(<MyComponent />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
});

Cypress + axe-core

npm install --save-dev cypress-axe axe-core
// cypress/support/e2e.js
import 'cypress-axe';

// cypress/e2e/accessibility.cy.js
describe('Accessibility', () => {
beforeEach(() => {
cy.visit('/');
cy.injectAxe();
});

it('homepage has no detectable a11y violations', () => {
cy.checkA11y();
});

it('login page has no detectable a11y violations', () => {
cy.visit('/login');
cy.injectAxe();
cy.checkA11y();
});
});

Pre-commit Hook

Add to package.json:

{
"scripts": {
"a11y": "pa11y-ci"
},
"husky": {
"hooks": {
"pre-push": "npm run a11y"
}
}
}

Tools Summary

ToolUse CaseIntegration
Pa11y CIPage-level automated testingGitHub Actions, CLI
axe-coreComponent & page testingJest, Cypress, CLI
Lighthouse CIPerformance + accessibilityGitHub Actions
jest-axeReact component testingJest
cypress-axeE2E accessibility testingCypress