page.runAccessibilityTest()

Run an axe-core accessibility audit on the current page and return structured results for use in assertions or test reports.

Runs an axe-core accessibility audit on the current page and returns structured results. Use it to gate builds on accessibility compliance or to surface violations in test reports.

Signature

page.runAccessibilityTest(): Promise<AccessibilityResults>

Return type: AccessibilityResults

type AccessibilityResults = {
  violations: Result[];       // Rules that definitively failed
  incomplete: IncompleteResult[]; // Rules that need manual review
  passCount: number;          // Number of rules that passed
  ignoredRuleCount: number;   // Rules marked inapplicable to this page
  totalRuleCount: number;     // Total rules evaluated
};

violations and incomplete are standard axe-core result objects. The key fields on each entry are:

type Result = {
  id: string;           // axe-core rule ID, e.g. 'color-contrast'
  impact: 'critical' | 'serious' | 'moderate' | 'minor' | null;
  description: string;  // Human-readable description of the rule
  help: string;         // Short summary of the issue
  helpUrl: string;      // Link to the axe-core documentation for this rule
  nodes: NodeResult[];  // Elements on the page that triggered the rule
};

type IncompleteResult = Result; // Same shape; impact may be null for inconclusive checks

type NodeResult = {
  html: string;         // Outer HTML of the offending element
  target: string[];     // CSS selector path to the element
  failureSummary: string | undefined; // Why it failed (violations only)
};

Basic usage

import { test, expect } from 'donobu';

test('home page has no accessibility violations', async ({ page }) => {
  await page.goto('https://www.example.com');

  const results = await page.runAccessibilityTest();

  expect(results.violations).toHaveLength(0);
});

Filtering by impact level

const results = await page.runAccessibilityTest();

const criticalViolations = results.violations.filter(
  (v) => v.impact === 'critical',
);

if (criticalViolations.length > 0) {
  console.log('Critical violations:');
  criticalViolations.forEach((v) => {
    console.log(`  - ${v.id}: ${v.description}`);
    v.nodes.forEach((node) => console.log(`    HTML: ${node.html}`));
  });
}

expect(criticalViolations).toHaveLength(0);

Running after AI interaction

page.runAccessibilityTest() can be called at any point during a test — including after page.ai has navigated to a specific state:

test('settings page is accessible after opening a modal', async ({ page }) => {
  await page.goto('https://app.example.com/settings');
  await page.ai('Open the "Change password" modal');

  const results = await page.runAccessibilityTest();
  expect(results.violations).toHaveLength(0);
});

Notes

  • The audit runs against the full current page DOM. Dynamic content loaded after the initial navigation is included.
  • axe-core tests cover a wide range of WCAG 2.x success criteria. Refer to the axe-core documentation for the full rule list.
  • incomplete results are cases where axe-core found a potential issue but cannot definitively classify it as a violation — manual review is recommended for these.