Skip to main content
Version: Current

Accessibility Testing

Introduction​

Happo provides powerful accessibility testing capabilities that work similarly to our visual regression testing. You can use Happo to automatically detect accessibility violations and generate ARIA snapshots of your components. This is useful as it helps ensure your application remains accessible as it evolves. Just like with screenshot testing, Happo will track changes over time and help you maintain accessibility standards across your codebase.

Setup​

To run accessibility tests with Happo, you need to set up one of our existing integrations. Once you have a working integration, it's a matter of a small configuration tweak where you add an accessibility target to your Happo configuration file.

  1. Integrate Happo with one of our supported testing frameworks:

  2. Add an accessibility target to your Happo configuration file:

happo.config.ts
import { defineConfig } from 'happo';

export default defineConfig({
targets: {
// ... Your existing screenshot targets

accessibility: {
type: 'accessibility',
viewport: '1200x768',
},
},
});

You can run accessibility tests alongside your screenshot tests, or use them independently. Once you have at least one accessibility target in your configuration, you'll start seeing accessibility checks in your Happo reports.

Violation Tracking​

In the Happo dashboard there's an accessibility graph that helps you track progress over time. The graph shows the number of violations across your components and pages, making it easy to identify trends and measure improvements.

Happo updates its accessibility checks from time to time, for example to a newer version of axe-core, and an update can find more violations, or fewer, in the same code. When Happo can measure that an update changed the counts in your project's snapshots, the graph marks the day with a dashed line and explains what changed below the graph, so a jump there isn't mistaken for a change to your code. Updates that didn't change your counts aren't marked.

Accessibility Graph

Checks​

Happo uses axe-core® to perform comprehensive accessibility checks. Some examples of the checks we perform include:

We support multiple WCAG conformance levels:

Configuring axe options​

Happo workers read an optional window.happoAxeOptions object before running accessibility checks. When present, the options you specify are merged in on top of the Happo defaults, which lets you tweak the axe-core run without replacing the defaults wholesale. See the axe-core API reference for the full list of supported options.

A typical configuration might disable a rule that produces noise for your app, or narrow the run to a specific set of WCAG tags:

window.happoAxeOptions = {
runOnly: {
type: 'tag',
values: ['wcag2a', 'wcag2aa'],
},
rules: {
'color-contrast': { enabled: false },
},
};

Where you define window.happoAxeOptions depends on your testing framework.

Storybook​

Set the options in .storybook/preview.js so they are defined before any story is rendered:

.storybook/preview.js
window.happoAxeOptions = {
rules: {
'color-contrast': { enabled: false },
},
};

Playwright​

Use page.addInitScript to make sure the options are defined on every page before Happo captures accessibility snapshots:

tests/test.spec.js
import { test } from 'happo/playwright';

test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
window.happoAxeOptions = {
runOnly: {
type: 'tag',
values: ['wcag2a', 'wcag2aa'],
},
};
});
});

test('start page', async ({ page, happoScreenshot }) => {
await page.goto('http://localhost:7676');
await happoScreenshot(page.locator('.hero-image'), {
component: 'Hero Image',
});
});

Cypress​

Register a window:before:load listener in cypress/support/e2e.js so the options are set on every page load, before any app code runs:

cypress/support/e2e.js
import 'happo/cypress';

Cypress.on('window:before:load', (win) => {
win.happoAxeOptions = {
rules: {
'color-contrast': { enabled: false },
},
};
});

Below is an example of how violations appear in a Happo report. When you make changes that add or remove violations, the comparison report page will show you the before and after violation count. Each violation has a section that explains why the violation was found and gives you pointers on how to fix it.

New accessibility violations in a Happo report

Click a violation type in the sidebar to filter the report to only show the accessibility snapshots containing that particular violation.

Seeing where violations are​

Along with its violations, an accessibility snapshot comes with a screenshot of the part of the page they are in. On the comparison and report pages, the snapshot opens on an Annotated view of that screenshot: every failing element is outlined and numbered, in the color of its violation's impact. Click a number to see what is wrong with the element and how to fix it (hovering one names the rule it breaks). In a comparison, the numbers point at the violations that changed, and the unchanged ones join them when you show them.

The List view has the violations one by one, as above, and gives each failing element a close-up cut from the screenshot, with the same number.

An element that takes up no room on the page, or one that is the whole page (<html> or <body>), gets no number, so a snapshot with only those has no screenshot. Neither do snapshots taken before Happo started saving one: they show the list alone.

The MCP server gives AI assistants the same screenshot.

A Happo report filtered to one violation type

ARIA Snapshots​

ARIA snapshots are another feature of Happo's accessibility testing. They provide a text-based representation of how screen readers would interpret your interface, making it easier to understand the accessibility structure of your components and pages.

An ARIA snapshot diff in a Happo report

These snapshots help verify that the semantic structure is correct and that screen readers will present the interface in an understandable way.

Why Happo?​

Happo's approach to accessibility testing offers several advantages over traditional methods:

Compared to Linting​

While linting tools are valuable for catching issues during development, they often run in isolation and don't capture the full context of how components interact. Happo's integration with your testing framework ensures accessibility is checked in a runtime/in-browser environment.

Compared to Snapshot Testing​

Traditional snapshot testing requires committing test results to source control, which can lead to large diffs and merge conflicts. Happo's asynchronous approval workflow allows teams to review and approve changes in a dedicated UI, making it easier to manage accessibility updates. You'll also have better reporting capabilities and track how your application improves over time.

Compared to Manual Tools​

Manual accessibility testing is time-consuming and prone to human error. Happo automates the process while still maintaining the human review element through our approval workflow. This combination of automation and human oversight has proven very useful for screenshot testing, and the same model works equally well for accessibility testing.

Happo's model of asynchronous approval is particularly well-suited for accessibility testing because:

  • It allows teams to review and approve accessibility changes separately from code changes
  • It provides a clear audit trail of accessibility improvements
  • It enables gradual improvements without blocking development
  • It integrates accessibility testing into the existing development workflow
  • It makes accessibility testing a natural part of the development process

axe-core® is a trademark of Deque Systems, Inc. in the US and other countries.