new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Playwright · all subjects

accessibility-testing

15 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Accessibility testing with Playwright and axe-core

Playwright can test applications for accessibility issues using the @axe-core/playwright package, which runs the axe accessibility testing engine. This can detect problems like poor color contrast, UI controls without labels, and duplicate element IDs. Automated testing can find some common issues, but manual testing and inclusive user testing are also recommended.

AxeBuilder.analyze() scans page in current state

The AxeBuilder.analyze() method scans a page in whatever state it is currently in when the method is called. To scan parts of a page that appear after user interactions, use Locators to interact with the page and wait for elements to appear before calling analyze().

AxeBuilder methods for filtering scans

AxeBuilder supports several methods to configure scans: include(selector) constrains a scan to specific parts of a page; withTags(array) filters rules by WCAG tags such as wcag2a, wcag2aa, wcag21a, wcag21aa; exclude(selector) removes elements from scans; disableRules(array) temporarily disables specific rules by ID.

exclude() method downsides

AxeBuilder.exclude() excludes the specified elements and all their descendants from scanning. Avoid using it with components that have many children. The method prevents all rules from running against the specified elements, not just rules for known issues.

Snapshot accessibility violations with fingerprints

When using snapshots to track known accessibility issues, create a fingerprint containing only the rule ID and CSS selectors of affected elements, rather than snapshotting the entire violations array. The full violations object contains implementation details like rendered HTML that change frequently and make tests fragile.

Attach accessibility scan results to tests

Use testInfo.attach() to include full axe scan results as a test attachment for debugging. The scan results contain more than just violations—they also include information about passed rules and inconclusive results. Pass an object with body as stringified JSON and contentType as 'application/json'.

Example: scan entire page for accessibility violations

import { test, expect } from '@playwright/test'; import AxeBuilder from '@axe-core/playwright'; test.describe('homepage', () => { test('should not have any automatically detectable accessibility issues', async ({ page }) => { await page.goto('https://your-site.com/'); const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); expect(accessibilityScanResults.violations).toEqual([]); }); });

Example: scan specific page section after interaction

test('navigation menu should not have automatically detectable accessibility violations', async ({ page }) => { await page.goto('https://your-site.com/'); await page.getByRole('button', { name: 'Navigation Menu' }).click(); await page.locator('#navigation-menu-flyout').waitFor(); const accessibilityScanResults = await new AxeBuilder({ page }) .include('#navigation-menu-flyout') .analyze(); expect(accessibilityScanResults.violations).toEqual([]); });

Example: scan for WCAG A and AA violations only

test('should not have any automatically detectable WCAG A or AA violations', async ({ page }) => { await page.goto('https://your-site.com/'); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']) .analyze(); expect(accessibilityScanResults.violations).toEqual([]); });

Example: exclude element from accessibility scan

test('should not have any accessibility violations outside of elements with known issues', async ({ page }) => { await page.goto('https://your-site.com/page-with-known-issues'); const accessibilityScanResults = await new AxeBuilder({ page }) .exclude('#element-with-known-issue') .analyze(); expect(accessibilityScanResults.violations).toEqual([]); });

Example: disable specific accessibility rules

test('should not have any accessibility violations outside of rules with known issues', async ({ page }) => { await page.goto('https://your-site.com/page-with-known-issues'); const accessibilityScanResults = await new AxeBuilder({ page }) .disableRules(['duplicate-id']) .analyze(); expect(accessibilityScanResults.violations).toEqual([]); });

Example: attach scan results to test for debugging

test('example with attachment', async ({ page }, testInfo) => { await page.goto('https://your-site.com/'); const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); await testInfo.attach('accessibility-scan-results', { body: JSON.stringify(accessibilityScanResults, null, 2), contentType: 'application/json' }); expect(accessibilityScanResults.violations).toEqual([]); });

Example: create reusable AxeBuilder test fixture

import { test as base } from '@playwright/test'; import AxeBuilder from '@axe-core/playwright'; type AxeFixture = { makeAxeBuilder: () => AxeBuilder; }; export const test = base.extend<AxeFixture>({ makeAxeBuilder: async ({ page }, use) => { const makeAxeBuilder = () => new AxeBuilder({ page }) .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']) .exclude('#commonly-reused-element-with-known-issue'); await use(makeAxeBuilder); } }); export { expect } from '@playwright/test';

Example: use custom AxeBuilder fixture in test

const { test, expect } = require('./axe-test'); test('example using custom fixture', async ({ page, makeAxeBuilder }) => { await page.goto('https://your-site.com/'); const accessibilityScanResults = await makeAxeBuilder() .include('#specific-element-under-test') .analyze(); expect(accessibilityScanResults.violations).toEqual([]); });

Test fixtures for shared AxeBuilder configuration

Test fixtures are useful for sharing common AxeBuilder configuration across many tests. Use cases include applying the same set of rules to all tests, suppressing known violations in elements that appear on many pages, and consistently attaching accessibility reports for multiple scans.

Give your agent this brain