Accessibility Tests in Drupal
The accessibility implementation is owned by
@lullabot/playwright-testing.
The Drupal package keeps the established imports and adds Drupal-specific
defaults through its adapter.
import {
checkAccessibility,
takeAccessibleScreenshot,
test,
} from '@packages/playwright-drupal';
test('home page accessibility', async ({ page }, testInfo) => {
await page.goto('/');
await checkAccessibility(page, testInfo);
});
test('home page screenshot and accessibility', async ({ page }, testInfo) => {
await page.goto('/');
await takeAccessibleScreenshot(page, testInfo);
});
test('home page via the fixture', async ({ page, a11y }) => {
await page.goto('/');
await a11y.check();
});
Drupal preset
Calls through @lullabot/playwright-drupal apply the historical Drupal
behavior:
- known skip-link, landmark, footer, and media-preview selectors are excluded from the applicable axe scan;
- lazy images that initially error can be requested again, which accommodates Stage File Proxy;
- Drupal's fixed administration toolbar is allowed to settle after scrolling; and
- the legacy Firefox and Safari project-name thresholds remain in effect.
Caller options still win over preset defaults. Set
accessibility.disableDefaultExclusions: true on a screenshot, or
disableDefaultExclusions: true on a11y.check(), to scan Drupal's default
exclusions too.
test('scan every element', async ({ page, a11y }) => {
await page.goto('/');
await a11y.check({ disableDefaultExclusions: true });
});
The a11y fixture is Drupal-package functionality. It exposes:
a11y.check(options)as shorthand forcheckAccessibility(page, testInfo, options); anda11y.screenshot(options, scrollLocator, locator)as shorthand fortakeAccessibleScreenshot(page, testInfo, options, scrollLocator, locator).
Baselines and reports
Baseline files, first-run seeding, accessibility annotations, violation
screenshots, shared in-code baselines, and scan options behave as documented in
the canonical accessibility guide.
The Drupal package re-exports defineAccessibilityBaseline and the associated
types, so existing code does not need to change.
import {
defineAccessibilityBaseline,
test,
} from '@packages/playwright-drupal';
const baseline = defineAccessibilityBaseline([
{
rule: 'color-contrast',
targets: ['#footer .legal'],
reason: 'Waiting for the approved brand palette update.',
willBeFixedIn: 'https://example.com/issues/123',
},
]);
test('about page', async ({ page, a11y }) => {
await page.goto('/about');
await a11y.check({ baseline });
});
Direct generic imports
Drupal projects can import a helper from @lullabot/playwright-testing when a
specific test must use neutral defaults. The generic call does not apply the
Drupal preset and does not provide the Drupal a11y fixture.
import { test } from '@playwright/test';
import { checkAccessibility } from '@lullabot/playwright-testing';
test('neutral scan', async ({ page }, testInfo) => {
await page.goto('/');
await checkAccessibility(page, testInfo);
});
GitHub annotations
The legacy playwright-drupal-a11y-summary executable remains available and
uses the same report implementation as
playwright-testing-a11y-summary. Existing workflows can continue to use it:
- name: Accessibility summary
if: always()
run: ddev exec npx playwright-drupal-a11y-summary --mode=summary
- name: Accessibility annotations
if: always()
run: ddev exec npx playwright-drupal-a11y-summary --mode=annotations
The JSON reporter configured by definePlaywrightDrupalConfig() provides the
input automatically. For command options, neutral library imports, and new
non-Drupal workflows, see the canonical
GitHub reporting guide.