From harness-claude
Automates accessibility testing with axe-core, jest-axe, and Playwright, including CI pipeline integration. Helps catch a11y regressions in component and full-page tests.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:a11y-testing-automationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Automate accessibility testing with axe-core, jest-axe, Playwright, and CI pipeline integration
Automate accessibility testing with axe-core, jest-axe, Playwright, and CI pipeline integration
npm install -D jest-axe @types/jest-axe
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
describe('LoginForm', () => {
it('should have no accessibility violations', async () => {
const { container } = render(<LoginForm />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
it('should have no violations in error state', async () => {
const { container } = render(<LoginForm errors={{ email: 'Required' }} />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
});
const states = [
{ name: 'default', props: {} },
{ name: 'loading', props: { isLoading: true } },
{ name: 'error', props: { error: 'Something went wrong' } },
{ name: 'empty', props: { items: [] } },
];
states.forEach(({ name, props }) => {
it(`should have no a11y violations in ${name} state`, async () => {
const { container } = render(<DataTable {...props} />);
expect(await axe(container)).toHaveNoViolations();
});
});
npm install -D @axe-core/playwright
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('homepage should have no a11y violations', async ({ page }) => {
await page.goto('/');
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21aa'])
.analyze();
expect(results.violations).toEqual([]);
});
test('checkout flow should have no a11y violations', async ({ page }) => {
await page.goto('/checkout');
// Fill form to trigger validation states
await page.click('button[type="submit"]');
await page.waitForSelector('[role="alert"]');
const results = await new AxeBuilder({ page })
.exclude('.third-party-widget') // Exclude content you do not control
.analyze();
expect(results.violations).toEqual([]);
});
npm install -D eslint-plugin-jsx-a11y
{
"extends": ["plugin:jsx-a11y/recommended"],
"plugins": ["jsx-a11y"]
}
Key rules this enables:
alt-text — images must have altanchor-is-valid — <a> must have hrefclick-events-have-key-events — onClick must have onKeyDown/onKeyUplabel-has-associated-control — labels must be linked to inputsno-noninteractive-element-interactions — no click handlers on divsgetByRole, getByLabelText, and getByAltText verify accessibility as a side effect of writing tests.import { render, screen } from '@testing-library/react';
// These queries fail if accessibility is broken
const submitButton = screen.getByRole('button', { name: 'Submit' });
const emailInput = screen.getByLabelText('Email address');
const logo = screen.getByAltText('Company Logo');
const nav = screen.getByRole('navigation', { name: 'Main' });
const alert = screen.getByRole('alert');
# GitHub Actions
- name: Run a11y tests
run: npx playwright test --grep @a11y
- name: Run component a11y tests
run: npx vitest run --grep "accessibility"
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21aa'])
.disableRules(['color-contrast']) // Disable if you have a separate contrast testing workflow
.analyze();
import { createHtmlReport } from 'axe-html-reporter';
const results = await new AxeBuilder({ page }).analyze();
createHtmlReport({
results,
options: { outputDir: 'a11y-reports', reportFileName: 'homepage.html' },
});
What automated testing catches (~30-40% of issues):
What automated testing misses (~60-70% of issues):
Testing pyramid for accessibility:
Handling existing violations: When adding axe to an existing project, you may find hundreds of violations. Use disableRules or exclude selectively to establish a baseline, then fix violations incrementally and remove exclusions over time.
https://github.com/dequelabs/axe-core
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeRuns WCAG accessibility checks using axe-core with Playwright for E2E tests and jest-axe for component tests. Includes keyboard navigation and ARIA testing.
Automates accessibility testing with Playwright (@playwright/test), TypeScript, and axe-core for WCAG 2.1 AA compliance, keyboard navigation, focus management, ARIA validations, and semantic checks.