The WCAG (Web Content Accessibility Guidelines) standard is a set of guidelines designed to ensure that digital content is accessible to all users, including people with disabilities. There are several tools that can be used to test for compliance with this standard – one of them is the “jest axe." In this article, we’ll show you how it works, take you through a step-by-step accessibility test, and tell you what to look out for when using it.
More detailed information about what WCAG is, when and how it should be applied, as well as the challenges the future holds in ensuring digital accessibility for users, can be found here.
If a project uses the jest library, it’s easy to add tests to check the WCAG compliance of components.
Jest-axe is an automated accessibility testing tool based on the axe-core engine. It works similarly to code linters (such as ESLint or Stylelint) and detects common problems, although it does not guarantee full compliance with accessibility requirements.
It integrates with the jest library and allows you to analyze the HTML of components for accessibility issues such as:
It adds the toHaveNoViolations
matcher to your tests, enabling easy validation of the analysis results.
Please note!
Jest-axe does not replace a manual accessibility audit. Automated tests are only a support tool and will not catch all problems. A full evaluation should be performed by people with expertise in this area.
It’s important to be aware of the limitations of this tool. Jest-axe may not detect, among others:
To integrate Jest with jest-axe in a project that already uses Jest, follow these steps:
In your test setup file, e.g., test-setup.ts, add the following import:
In the test-setup.ts
file, you need to import `jest-axe/extend-expect`
When everything has been configured, the only thing left is to use the tool in your tests. In the test file, add the import import { axe } from 'jest-axe';
. Then, by using axe(fixture.nativeElement)
, an accessibility analysis will be run for the generated HTML of the component. The result of the analysis must be verified using the toHaveNoViolations method
, as follows: expect(results).toHaveNoViolations()
.
For testing purposes, two components have been prepared. The first contains HTML that does not meet accessibility audit requirements, while the second complies with them.
The component contains the following HTML code:
<div class="container">
<!-- Error: Incorrect heading order (h4 follows h2 without h3) -->
<h2>Main heading</h2>
<h4>Recommended accessories</h4>
<!-- Error: Image without alt attribute -->
<img src="product.jpg" class="banner-image">
<!-- Error: Link without content (empty link) -->
<a href="/home" class="home-link"></a>
<!-- Error: select element without label -->
<select>
<option value="">Choose a topic...</option>
<option value="question">Question</option>
<option value="complaint">Complaint</option>
</select>
<!-- Error: ARIA attribute with invalid value -->
<div aria-hidden="falsy">Hidden content</div>
</div>
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {MyComponent} from './my.component';
import {axe} from 'jest-axe';
describe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyComponent]
})
.compileComponents();
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should pass accessibility tests', async () => {
const results = await axe(fixture.nativeElement);
expect(results).toHaveNoViolations()
});
});
expect(received).toHaveNoViolations(expected)
Expected the HTML found at $('div[aria-hidden="falsy"]') to have no violations:
<div aria-hidden="falsy">Hidden content</div>
Received:
"ARIA attributes must conform to valid values (aria-valid-attr-value)"
Fix all of the following:
Invalid ARIA attribute value: aria-hidden="falsy"
You can find more information on this issue here:
https://dequeuniversity.com/rules/axe/4.10/aria-valid-attr-value?application=axeAPI
────────
...
Received:
"Heading levels should only increase by one (heading-order)"
...
────────
...
Received:
"Images must have alternative text (image-alt)"
...
────────
...
Received:
"Links must have discernible text (link-name)"
...
────────
...
Received:
"Select element must have an accessible name (select-name)"
<a>
tag with no content or accessibility attributes<div class="container">
<!-- Correct heading hierarchy -->
<h2 id="main-heading">Main heading</h2>
<h3 id="recommended-heading">Recommended accessories</h3>
<!-- Added alt attribute to image -->
<img src="product.jpg" class="banner-image" alt="Product image">
<!-- Link now contains text -->
<a href="/home" class="home-link">Home page</a>
<!-- Select element with proper label -->
<label for="topic-select">Choose a topic:</label>
<select id="topic-select" name="topic">
<option value="">Choose a topic...</option>
<option value="question">Question</option>
<option value="complaint">Complaint</option>
</select>
<!-- Correct ARIA attribute value -->
<div aria-hidden="true">Hidden content</div>
</div>
For more information on accessibility testing and detailed usage scenarios with different tools, see our recent article.
Jest-axe easily integrates with Jest and enables the detection of basic accessibility issues in HTML. It also works with popular frameworks such as Angular, React and Vue.
However, it does not provide comprehensive accessibility auditing support.
Therefore, Jest-axe should be used as an additional support tool alongside manual accessibility testing and audits involving people with disabilities, rather than as a replacement for them.