Skip to content

Accessibility Testing — Automated Coverage

FieldValue
TypeAgent Reference
Source~/.copilot/agents/_refs/senior-qa/accessibility-testing.md
DescriptionNot specified

Source Content

Accessibility Testing — Automated Coverage

axe in Component Tests

Run axe on every component. This catches ~57% of WCAG issues automatically:

// Setup — vitest.setup.ts
import { toHaveNoViolations } from 'jest-axe'
expect.extend(toHaveNoViolations)
// In any component test
import { render } from '@testing-library/react'
import { axe } from 'jest-axe'
it('has no axe violations', async () => {
const { container } = render(<MyComponent {...mockProps} />)
expect(await axe(container)).toHaveNoViolations()
})

Run axe on every meaningful state:

describe('UserCard accessibility', () => {
const defaultProps = { user: mockUser, onEdit: vi.fn(), onDelete: vi.fn() }
it('default state has no violations', async () => {
const { container } = render(<UserCard {...defaultProps} />)
expect(await axe(container)).toHaveNoViolations()
})
it('deleting state has no violations', async () => {
const { container } = render(<UserCard {...defaultProps} isDeleting />)
expect(await axe(container)).toHaveNoViolations()
})
it('error state has no violations', async () => {
const { container } = render(<UserCard {...defaultProps} error="Failed to load" />)
expect(await axe(container)).toHaveNoViolations()
})
})

Targeting specific rules:

// Only check specific WCAG rules (for known partial test contexts)
expect(
await axe(container, {
rules: {
// Disable color-contrast in a context where background is unknown
'color-contrast': { enabled: false },
},
})
).toHaveNoViolations()

Never globally disable rules — always disable at the test level with a comment explaining why.

E2E accessibility checks

No prescribed E2E framework. If a project adopts one (Cypress, WebdriverIO, Vitest browser mode, etc.), run axe at the page level using that framework’s axe integration. Cover the same WCAG tag set used at the component layer (wcag2a, wcag2aa, wcag21aa, wcag22aa).

Keyboard Contract Tests

Test keyboard flows at the component layer with RTL + @testing-library/user-event — dialogs, selects, menus, comboboxes. Cover: open with Enter/Space, focus moves into the widget, Tab cycles inside (focus trap), Escape closes and returns focus to the trigger. If an E2E suite exists, repeat the same contracts there using its keyboard primitives.

Focus Ring Visual Test

Verify focus rings are visible with a Lost Pixel snapshot:

// In Storybook story
export const KeyboardFocused: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
// Tab to the interactive element
await userEvent.tab()
// Screenshot is taken in this state — verifies focus ring is visible
},
parameters: {
// Lost Pixel will snapshot this story showing the focused state
lostpixel: { threshold: 0 }, // zero tolerance for focus ring regressions
},
}

WCAG 2.2 Automated Coverage Map

WCAG CriterionAutomated?How
1.1.1 Non-text contentPartialaxe checks missing alt text
1.3.1 Info and relationshipsPartialaxe checks semantic structure
1.3.2 Meaningful sequenceManualReading order requires human review
1.3.3 Sensory characteristicsManual”the button on the right” — manual
1.4.1 Use of colorPartialaxe checks some cases; manual for complex
1.4.3 Contrast (minimum)Yesaxe color-contrast rule
1.4.11 Non-text contrastPartialaxe partially; manual for UI components
2.1.1 KeyboardPartialRTL + userEvent keyboard tests (component layer)
2.1.2 No keyboard trapYesRTL focus trap tests (or E2E equivalent if present)
2.4.3 Focus orderPartialRTL tab sequence tests
2.4.7 Focus visiblePartialLost Pixel focus ring snapshots
2.5.3 Label in namePartialaxe label checks
3.3.1 Error identificationYesaxe aria-invalid + error message tests
3.3.2 Labels or instructionsYesaxe label association checks
4.1.1 ParsingYesaxe HTML validity checks
4.1.2 Name, role, valuePartialaxe ARIA checks
4.1.3 Status messagesYesaxe aria-live region checks

What automated testing cannot catch (manual required):

  • Meaningful sequence / reading order
  • Color used as the only visual signal in complex layouts
  • Focus visible in non-standard themes
  • Screen reader announcement quality
  • Cognitive load and plain language
  • Mobile touch target size (3mm minimum)