Skip to content
Back to skills

A11y Testing Automation

ASecurity

> Automate accessibility testing with axe-core, jest-axe, Playwright, and CI pipeline integration

  • 20 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 11, 2026
testingtypescriptgobashreacttestinggit

Works with

  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned September 11, 2026

npx -y skills add Intense-Visions/harness-engineering --skill a11y-testing-automation --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of A11y Testing Automation?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for A11y Testing Automation
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/intense-visions-a11y-testing-automation/badge)](https://www.skillsdirectory.com/skills/intense-visions-a11y-testing-automation)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Accessibility Testing Automation

> Automate accessibility testing with axe-core, jest-axe, Playwright, and CI pipeline integration

## When to Use

- Setting up automated accessibility testing for a project
- Adding a11y checks to existing unit or integration tests
- Catching accessibility regressions in CI before they reach production
- Complementing manual screen reader testing with automated scans
- Enforcing accessibility standards across a team

## Instructions

1. **Add axe-core to component tests with jest-axe.** This catches common violations (missing labels, invalid ARIA, contrast issues) in rendered components.

```bash
npm install -D jest-axe @types/jest-axe
```

```typescript
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();
  });
});
```

2. **Test all component states.** Accessibility violations often appear in specific states — error states, loading states, empty states, expanded states. Test each variation.

```typescript
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();
  });
});
```

3. **Add axe to Playwright for full-page accessibility testing.**

```bash
npm install -D @axe-core/playwright
```

```typescript
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([]);
});
```

4. **Use eslint-plugin-jsx-a11y for static analysis in React projects.** This catches violations at authoring time, before tests run.

```bash
npm install -D eslint-plugin-jsx-a11y
```

```json
{
  "extends": ["plugin:jsx-a11y/recommended"],
  "plugins": ["jsx-a11y"]
}
```

Key rules this enables:

- `alt-text` — images must have `alt`
- `anchor-is-valid` — `<a>` must have `href`
- `click-events-have-key-events` — `onClick` must have `onKeyDown`/`onKeyUp`
- `label-has-associated-control` — labels must be linked to inputs
- `no-noninteractive-element-interactions` — no click handlers on divs

5. **Use Testing Library's accessible queries by default.** Queries like `getByRole`, `getByLabelText`, and `getByAltText` verify accessibility as a side effect of writing tests.

```typescript
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');
```

6. **Run accessibility checks in CI as a required gate.** Fail the build on new violations.

```yaml
# GitHub Actions
- name: Run a11y tests
  run: npx playwright test --grep @a11y

- name: Run component a11y tests
  run: npx vitest run --grep "accessibility"
```

7. **Configure axe to match your target WCAG level.** Focus on WCAG 2.1 AA for most projects. Filter by tags to avoid noise from rules you are not targeting.

```typescript
const results = await new AxeBuilder({ page })
  .withTags(['wcag2a', 'wcag2aa', 'wcag21aa'])
  .disableRules(['color-contrast']) // Disable if you have a separate contrast testing workflow
  .analyze();
```

8. **Generate accessibility reports for tracking progress.**

```typescript
import { createHtmlReport } from 'axe-html-reporter';

const results = await new AxeBuilder({ page }).analyze();
createHtmlReport({
  results,
  options: { outputDir: 'a11y-reports', reportFileName: 'homepage.html' },
});
```

## Details

**What automated testing catches (~30-40% of issues):**

- Missing alt text, labels, and accessible names
- Invalid ARIA (wrong roles, missing required attributes)
- Color contrast violations (for static content)
- Duplicate IDs
- Missing document language
- Missing form field associations

**What automated testing misses (~60-70% of issues):**

- Logical heading hierarchy (tools detect missing headings, not poor hierarchy)
- Meaningful alt text (tools check presence, not quality)
- Focus management in dynamic content
- Keyboard interaction patterns for custom widgets
- Screen reader announcement quality and timing
- Touch target size on mobile

**Testing pyramid for accessibility:**

1. **Linting (eslint-plugin-jsx-a11y):** Instant feedback, catches ~15% of issues
2. **Component tests (jest-axe):** Fast, catches ~25% of issues per component state
3. **Integration tests (Playwright + axe):** Full page context, catches ~35% of issues
4. **Manual testing (screen reader + keyboard):** Catches the remaining ~60-70%

**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.

## Source

https://github.com/dequelabs/axe-core

## Process

1. Read the instructions and examples in this document.
2. Apply the patterns to your implementation, adapting to your specific context.
3. Verify your implementation against the details and edge cases listed above.

## Harness Integration

- **Type:** knowledge — this skill is a reference document, not a procedural workflow.
- **No tools or state** — consumed as context by other skills and agents.

## Success Criteria

- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.

Files in this skill

  • SKILL.md6.8 KB
  • skill.yaml831 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…