Skip to content

Accessibility Testing Tools — Automated Audits, Playwright and AI-Powered Testing

DodaTech Updated 2026-06-22 7 min read

In this tutorial, you'll learn about Accessibility Testing Tools. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Accessibility Testing combines automated scanning, programmatic assertions, manual keyboard validation, and screen reader verification to catch all barriers that prevent users from interacting with web content.

What You'll Learn

You'll master Playwright Accessibility snapshots, axe-core deep integration with CI/CD, AI-powered visual testing for color contrast and focus indicators, custom rule creation for project-specific patterns, and a layered testing strategy that catches regression bugs before they reach production.

Why It Matters

Automated tools catch approximately 30 percent of Accessibility issues. The remaining 70 percent — meaningful alt text, logical reading order, keyboard flow, screen reader announcement quality — require manual testing. A comprehensive strategy uses automation for rapid feedback and manual testing for depth. At DodaTech, every commit to Doda Browser and the Durga Antivirus Pro management console triggers a full Accessibility pipeline including automated axe scans, Playwright a11y assertions, and Lighthouse CI score enforcement.

Real-World Use

A team ships a new checkout modal. Automated axe scans pass. But a screen reader user cannot complete the purchase because focus does not move into the modal, the close button is not labeled, and the order summary is not announced. A Playwright test checking focus management would have caught this. Combined manual and automated testing prevents these regressions.

Playwright Accessibility Testing

Playwright provides built-in Accessibility Snapshot Testing and axe-core integration.

const { test, expect } = require('@playwright/test');
const AxeBuilder = require('@axe-core/playwright');

test('checkout page has no accessibility violations', async ({ page }) => {
  await page.goto('/checkout');

  // Run axe-core scan
  const results = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa', 'wcag22aa'])
    .analyze();

  expect(results.violations).toEqual([]);
});

test('modal receives focus on open', async ({ page }) => {
  await page.goto('/products');

  // Open modal
  await page.click('[data-testid="open-modal"]');

  // Check focus moved to modal heading
  const focused = await page.evaluate(() => document.activeElement?.id);
  expect(focused).toBe('modal-heading');

  // Check tab order inside modal
  await page.keyboard.press('Tab');
  const nextFocus = await page.evaluate(() => document.activeElement?.id);
  expect(nextFocus).toBe('modal-close-button');

  // Check Escape closes modal and returns focus
  await page.keyboard.press('Escape');
  const finalFocus = await page.evaluate(() => document.activeElement?.id);
  expect(finalFocus).toBe('open-modal');
});

test('color contrast is sufficient', async ({ page }) => {
  await page.goto('/');

  // Get computed styles of body text
  const contrast = await page.evaluate(() => {
    const el = document.querySelector('body');
    const style = getComputedStyle(el);
    const color = style.color;
    const bg = style.backgroundColor;
    return { color, background: bg };
  });

  expect(contrast.color).not.toBe('rgb(153, 153, 153)');
});

Expected behavior: The first test catches WCAG violations using axe-core rules. The second test verifies focus management — focus moves into the modal, Tab cycles through controls, and Escape returns focus to the trigger button. The third test provides a quick contrast sanity check.

AI-Powered Visual Testing

Tooling like Applitools and Percy can detect Accessibility issues through visual AI.

// AI visual accessibility check
import { Eyes, Target, VisualGridRunner } from '@applitools/eyes-playwright';

async function checkVisualAccessibility(page) {
  const eyes = new Eyes(new VisualGridRunner());
  await eyes.open(page, 'DodaTech', 'Accessibility Audit', {
    width: 1280, height: 900,
  });

  await eyes.check('Home Page', Target.window()
    .layoutRegions('[data-testid="header"]')
    .floatingRegions({ element: '[data-testid="toast"]', maxUpOffset: 10 })
  );

  // AI detects:
  // - Low contrast text (below 4.5:1 ratio)
  // - Missing focus indicators
  // - Text that overflows containers at 200% zoom
  // - Elements that overlap or clip at different viewports

  const results = await eyes.close(true);
  return results;
}

Expected behavior: AI visual testing captures screenshots across viewports and detects visual Accessibility issues that traditional Dom-based tools miss, including zoom-related breakage, focus indicator visibility, and content overflow at 200 percent zoom.

Custom Axe Rule Creation

Extend axe-core with project-specific rules.

// custom-axe-rules.js
const { axe } = require('axe-core');

axe.configure({
  rules: [
    {
      id: 'dodatech-button-labels',
      selector: 'button:not([aria-label]):not([aria-labelledby])',
      matches: (node) => {
        // Exclude icon-only buttons with visible text
        return !node.textContent.trim();
      },
tags: ['dodatech', 'wcag2a'],
      metadata: {
        description: 'All buttons must have accessible labels',
        help: 'Buttons must have text content, aria-label, or aria-labelledby',
      },
      all: [],
      any: [],
      none: [],
    },
  ],
});

// Usage in tests
async function runCustomAudit(page) {
  const results = await new AxeBuilder({ page })
    .withRules(['dodatech-button-labels'])
    .analyze();

  return results.violations.filter(v => v.id === 'dodatech-button-labels');
}

Expected behavior: Custom rules enforce project-specific Accessibility patterns — for example, ensuring every button in a design system has an accessible label. These rules run alongside WCAG standards in CI/CD.

CI/CD Accessibility Pipeline

name: Accessibility Pipeline
on: [pull_request]
jobs:
  axe-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build
      - run: npx serve out &
      - uses: dequelabs/axe-github-action@v3
        with:
          urls: |
            http://localhost:3000/
            http://localhost:3000/products
            http://localhost:3000/checkout
            http://localhost:3000/account
tags: wcag2a,wcag2aa,wcag22aa
          output: axe-report.json
      - uses: actions/upload-artifact@v4
        with:
          name: axe-report
          path: axe-report.json

  playwright-a11y:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test --grep @a11y

  lighthouse-ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build
      - run: npm install -g @lhci/cli
      - run: lhci autorun
        env:
          LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_TOKEN }}

Complete Testing Checklist

## Automated (every PR)
- [ ] axe-core scan on all page templates
- [ ] Playwright accessibility snapshot tests
- [ ] Custom rule enforcement for design system components
- [ ] Lighthouse CI accessibility score >= 90
- [ ] Color contrast assertions on dynamic content

## Manual (every sprint)
- [ ] Full keyboard navigation — Tab through all interactive elements
- [ ] Focus indicator visible on all focusable elements
- [ ] Screen reader test with NVDA (Windows + Firefox)
- [ ] Screen reader test with VoiceOver (macOS + Safari)
- [ ] Zoom to 200 percent — no content loss or horizontal scroll
- [ ] Forced colors mode (Windows High Contrast) — content remains visible
- [ ] Reduced motion — animations respect prefers-reduced-motion

Common Errors

1. Relying Only on Lighthouse Scores

A 100 Lighthouse Accessibility score does not mean a site is accessible. Lighthouse only catches automated rules. Manual testing is required for the remaining 70 percent.

2. Not Testing Error States

Accessibility tests on the default page State miss modals, form errors, loading states, and empty states. Test every dynamic State that a user can encounter.

3. Testing Only One Browser-Screen Reader Combination

Different combinations behave differently. Test Chrome + NVDA, Firefox + NVDA, Safari + VoiceOver, and Edge + Narrator.

4. Missing Focus Management Tests

Playwright tests should verify that focus moves correctly on modal open, menu expand, form submission, and page navigation. This is one of the most common Accessibility bugs.

5. Ignoring Reduced Motion

Users with vestibular disorders need animations disabled. Test that all animations respect prefers-reduced-motion media query and that content is not hidden behind animations.

6. Not Customizing axe Rules

Default axe rules miss project-specific patterns. Create custom rules for your design system components.

7. Testing Too Late in the Pipeline

Catching Accessibility bugs in production is expensive. Shift left — test at the component level, integration level, and E2E level. Fail the PR build on critical or serious violations.

Practice Questions

1. What percentage of Accessibility issues do automated tools catch?

Approximately 30 percent. The remaining 70 percent require manual testing with keyboard, screen reader, and real users with disabilities.

2. How does Playwright improve on traditional axe-core testing?

Playwright enables testing Accessibility in the context of real browser interactions — focus management after modal open, ARIA State changes after button click, and live region announcements during async operations.

3. What is the difference between role="alert" and aria-live="assertive"?

Both cause immediate announcement. role="alert" is a semantic HTML role that implicitly provides assertive live region behavior. aria-live="assertive" is the underlying ARIA property. Both interrupt the screen reader's current speech.

4. When should you create custom axe rules?

When your design system has specific Accessibility patterns not covered by WCAG standards. For example, custom rule ensuring every icon button has aria-label matching a naming convention.

5. Challenge: Set up a complete Playwright Accessibility test suite that: runs axe-core scans on 5 page templates, verifies focus management for a modal and a dropdown menu, checks keyboard navigation through a form, and asserts color contrast on dynamically loaded content.

Mini Project: Automated Accessibility Dashboard

Build a dashboard that:

  1. Runs nightly axe-core scans on all production URLs
  2. Stores violation history in a time-series database
  3. Tracks trends per WCAG criterion — is the site getting more or LESS accessible?
  4. Sends alerts when new critical violations are introduced
  5. Generates a weekly Accessibility scorecard for the engineering team
  6. Includes manual testing checklists that can be checked off by QA engineers

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro