Skip to content

How to Improve Accessibility with Testing Library and jest-axe for Your Vue Application

Updated: at 

Accessibility is a critical aspect of web development that ensures your application can be used by everyone, including people with disabilities. Making your Vue apps accessible not only meets legal requirements, but provides a better experience for all users. In this post, we’ll explore how to improve accessibility in Vue applications using Testing Library and jest-axe.

Prerequisites

Before we dive in, make sure you have the following installed in your Vue project:

You can add them with:

npm install --save-dev @testing-library/vue jest-axe

Example Component

Let’s look at a simple Vue component that displays an image and some text:

<template>
  <div: HTMLAttributes & ReservedPropsdiv>
    <h2: HTMLAttributes & ReservedPropsh2>{{ title?: string | undefinedtitle }}</h2: HTMLAttributes & ReservedPropsh2>
    <p: HTMLAttributes & ReservedPropsp>{{ description?: string | undefineddescription }}</p: HTMLAttributes & ReservedPropsp>
    <img: ImgHTMLAttributes & ReservedPropsimg ImgHTMLAttributes.src?: string | undefinedsrc="sample_image.jpg" />
  </div: HTMLAttributes & ReservedPropsdiv>
</template>

<script setup lang="ts">
const defineProps: <{
    title: StringConstructor;
    description: StringConstructor;
}>(props: {
    title: StringConstructor;
    description: StringConstructor;
}) => {
    ...;
} (+2 overloads)
Vue `<script setup>` compiler macro for declaring component props. The expected argument is the same as the component `props` option. Example runtime declaration: ```js // using Array syntax const props = defineProps(['foo', 'bar']) // using Object syntax const props = defineProps({ foo: String, bar: { type: Number, required: true } }) ``` Equivalent type-based declaration: ```ts // will be compiled into equivalent runtime declarations const props = defineProps<{ foo?: string bar: number }>() ```
@see{@link https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits}This is only usable inside `<script setup>`, is compiled away in the output and should **not** be actually called at runtime.
defineProps
({
title: StringConstructortitle: var String: StringConstructor
Allows manipulation and formatting of text strings and determination and location of substrings within strings.
String
,
description: StringConstructordescription: var String: StringConstructor
Allows manipulation and formatting of text strings and determination and location of substrings within strings.
String
}) </script>

Many developers know images should have alt text for accessibility, but how can we ensure we never forget this in production?

Testing with jest-axe

This is where jest-axe comes in. Axe is a leading accessibility testing toolkit used by major tech companies.

To test our component, we can create a test file like this:

import { render } from '@testing-library/vue';
import { axe, toHaveNoViolations } from 'jest-axe';
import { describe, it, expect } from 'vitest'
import MyComponent from './MyComponent.vue';

expect.extend(toHaveNoViolations);

describe('MyComponent', () => {
  it('has no accessibility violations', async () => {
    const { container } = render(MyComponent, {
      props: {
        title: 'Sample Title',
        description: 'Sample Description',
      },
    });

    const results = await axe(container);
    expect(results).toHaveNoViolations();
  });
});

When we run this test, we’ll get an error like:

FAIL  src/components/MyComponent.spec.ts > MyComponent > has no accessibility violations

Error: expect(received).toHaveNoViolations(expected)

Expected the HTML found at $('img') to have no violations:

<img src="sample_image.jpg">

Received:

"Images must have alternate text (image-alt)"

Fix any of the following:
  Element does not have an alt attribute
  aria-label attribute does not exist or is empty
  aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty
  Element has no title attribute
  Element's default semantics were not overridden with role="none" or role="presentation"

This tells us we need to add an alt attribute to our image. We can fix the component and re-run the test until it passes.

Conclusion

By integrating accessibility testing with tools like Testing Library and jest-axe, we can catch accessibility issues early in the development process. This helps ensure our Vue applications remain usable for everyone. Making accessibility testing part of our CI pipeline allows us to maintain high standards and provide a better experience for all users.

Related Posts