Accessibility testing (a11y) with Scout
Scout includes built-in support for automated accessibility (a11y) checks in UI tests via page.checkA11y.
Use automated a11y checks to augment, not replace, manual accessibility reviews and assistive technology testing.
Behind the scenes, page.checkA11y runs an axe-core scan of the current page state. It analyzes the DOM for accessibility violations and returns results you can assert on. Configuration is unified with Cypress and FTR.
We recommend adding page.checkA11y to:
- Key happy-path flows (for example, landing pages, dashboards, wizards)
- Important interaction states (for example, flyouts, modals, menus, toasts)
- Pages with frequent UI changes where regressions are likely
Avoid running a11y checks on every interaction. Pick a few high-value checkpoints per test or suite to keep runs fast and reduce flakiness.
Run page.checkA11y() once the page is fully loaded and the UI has settled:
test('Dashboard listing page has no basic accessibility violations', async ({
pageObjects,
page,
}) => {
await pageObjects.dashboard.gotoApp();
// Wait for the page to be ready (example helper)
await pageObjects.dashboard.waitForListingTableToLoad();
const { violations } = await page.checkA11y();
expect(violations).toHaveLength(0);
});
Prefer running checkA11y with include set to the root element you are testing. This keeps the scan isolated and reduces runtime.
test('Modal dialog is accessible', async ({ page }) => {
await page.goto('/app/my-plugin');
await page.testSubj.click('open-modal');
const modal = page.locator('[role="dialog"]');
await expect(modal).toBeVisible();
const { violations } = await page.checkA11y({
include: ['[role="dialog"]'],
});
expect(violations).toHaveLength(0);
});
test('should load dashboard from listing page', async ({ pageObjects, page }) => {
await pageObjects.dashboard.gotoApp();
await pageObjects.dashboard.waitForListingTableToLoad();
await test.step('no basic accessibility violations on the listing page', async () => {
const { violations } = await page.checkA11y();
expect(violations).toHaveLength(0);
});
// continue with the flow...
});
If a failure isn’t caused by your change and there isn’t a quick fix, don’t disable the entire a11y check. Prefer excluding the specific problematic element so the suite still provides coverage:
test('Form components are accessible', async ({ page }) => {
await page.goto('/app/my-plugin/create');
const { violations } = await page.checkA11y({
exclude: ['[data-test-subj="problematic-element"]'],
});
expect(violations).toHaveLength(0);
});
When page.checkA11y detects violations, the returned violations array includes details such as:
id(rule id, for examplecolor-contrast)impact(critical,serious,moderate,minor)descriptionnodes(elements that violate the rule)helpUrl
Violations appear in the Scout HTML report.
- Use
includeto target specific regions - Wait for page readiness before scanning
- Focus on critical paths and key interaction states
- Assert
violations.length === 0 - Combine with manual testing