Skip to content

Accessibility Testing in Playwright

Accessibility testing ensures your app works for keyboard, screen reader, and assistive technology users. Integrate @axe-core/playwright to run automated WCAG rule checks inside your existing E2E specs.

axe-core Integration

@axe-core/playwright wraps Deque's axe engine. After navigating to a page, run new AxeBuilder({ page }).analyze() and assert violations is empty — or allowlist known issues temporarily with tickets to fix them.

Combine axe scans with Playwright's native getByRole locators: if your tests already use roles, you are aligned with accessibility best practices for element targeting.

import AxeBuilder from '@axe-core/playwright';

test('homepage has no a11y violations', async ({ page }) => {
  await page.goto('/');
  const results = await new AxeBuilder({ page }).analyze();
  expect(results.violations).toEqual([]);
});

Install with npm i -D @axe-core/playwright.

AxeBuilder Options

new AxeBuilder({ page })
  .include('#main-content')
  .exclude('.third-party-widget')
  .withTags(['wcag2a', 'wcag2aa'])
  .analyze()
  • .include() scopes scan to part of the page.
  • .exclude() skips known third-party embeds.
  • .withTags() filters WCAG level rules.
  • Assert on violations array length or specific rule IDs.

Accessibility Testing Reference

axe-core + Playwright patterns.

API Purpose
AxeBuilder({ page }) Create scanner for current page
.analyze() Run rules and return violations
.include(selector) Limit scan scope
.exclude(selector) Skip known problem areas
getByRole locators Tests aligned with a11y tree
Keyboard tests page.keyboard.press('Tab') flows

Keyboard Navigation Tests

Automated axe scans catch many issues but not focus order quality. Supplement with Tab-key tests that assert focus moves to logical elements and Enter activates controls.

await page.keyboard.press('Tab');
await expect(page.getByRole('link', { name: 'Skip to content' })).toBeFocused();

Handling Known Violations

For legacy issues being fixed incrementally, exclude specific selectors or filter violation rule IDs — but track each allowlist entry in your issue tracker with a removal deadline.

Common Mistakes

  • Scanning the entire page including third-party iframes without excludes.
  • Relying only on axe — manual screen reader testing still matters.
  • Using CSS-only locators while claiming accessibility coverage.
  • Allowlisting violations permanently instead of fixing them.

Key Takeaways

  • @axe-core/playwright runs WCAG rule scans inside E2E tests.
  • Scope scans with include/exclude for meaningful results.
  • Pair automated scans with keyboard navigation tests.
  • getByRole locators align tests with the accessibility tree.

Pro Tip

Add one axe scan per critical page template in smoke tests — catches regressions when shared layout components change.