Czy wiesz, że za pomocą jest możesz automatycznie testować dostępność (a11y)?

Wojciech Stolarski
Opublikowano 19 maja 2025 r.

Standard WCAG (Web Content Accessibility Guidelines) to zbiór wytycznych mających na celu zapewnienie dostępności treści cyfrowych dla wszystkich użytkowników, w tym osób z niepełnosprawnościami. Istnieje kilka narzędzi, które można wykorzystać do sprawdzenia zgodności z tym standardem – jednym z nich jest „jest axe”. W tym artykule pokażemy, jak to działa, krok po kroku przeprowadzimy Cię przez test dostępności i podpowiemy, na co zwrócić uwagę podczas korzystania z niego.

Bardziej szczegółowe informacje na temat tego, czym jest WCAG, kiedy i jak należy go stosować, a także wyzwań, jakie przyniesie przyszłość w zakresie zapewnienia użytkownikom dostępności cyfrowej, można znaleźć tutaj w tym miejscu.

Czym jest jest-axe?

Jeśli projekt wykorzystuje bibliotekę jest, łatwo jest dodać testy sprawdzające zgodność komponentów z wytycznymi WCAG.

Jest-axe to zautomatyzowane narzędzie do testowania dostępności oparte na silniku Axe-Core. Działa podobnie do linterów kodu (takich jak ESLint czy Stylelint) i wykrywa typowe problemy, choć nie gwarantuje pełnej zgodności z wymaganiami dostępności.

Integruje się z biblioteką jest i umożliwia analizę kodu HTML komponentów pod kątem problemów z dostępnością, takich jak:

  • brak atrybutów alt w obrazach,
  • nieprawidłowe role ARIA,
  • nagłówki z nieprawidłową hierarchią.

Dodaje toHaveNoViolations dopasowuje się do testów, umożliwiając łatwą walidację wyników analizy.

Proszę zanotować!

Jest-axe nie zastępuje ręcznego audytu dostępności. Testy automatyczne stanowią jedynie narzędzie pomocnicze i nie wykryją wszystkich problemów. Pełna ocena powinna zostać przeprowadzona przez osoby posiadające doświadczenie w tej dziedzinie.

Co może przegapić topór żartobliwy?

Ważne jest, aby zdawać sobie sprawę z ograniczeń tego narzędzia. Jest-axe może nie wykryć między innymi:

  • problemy z kontrastem,
  • pełna ocena struktury semantycznej,
  • pewne problemy z elementami interaktywnymi,
  • problemy z nawigacją za pomocą klawiatury,
  • kwestie kontekstowe.

Integracja z Angularem

Aby zintegrować Jest z jest-axe w projekcie, który już korzysta z Jest, wykonaj następujące kroki:

Krok 1: instalacja

npm install –save-dev jest-axe @types/jest-axe

Krok 2: Konfiguracja

W pliku konfiguracji testu, np. test-setup.ts, dodaj następujący import:

import 'jest-axe/extend-expect';

Krok 3: Podstawowy test dostępności komponentu

W test-setup.ts plik, który musisz zaimportować `jest-axe/extend-expect`

Testy

Gdy wszystko zostanie skonfigurowane, pozostaje już tylko użycie narzędzia w testach. W pliku testowym dodaj import import { axe } from 'jest-axe';. Następnie, używając axe(fixture.nativeElement), zostanie przeprowadzona analiza dostępności dla wygenerowanego kodu HTML komponentu. Wynik analizy należy zweryfikować za pomocą toHaveNoViolations method, w następujący sposób: expect(results).toHaveNoViolations().

Przypadki testowe

Do celów testowych przygotowano dwa komponenty. Pierwszy zawiera kod HTML, który nie spełnia wymagań audytu dostępności, a drugi je spełnia.

Pierwszy scenariusz

Komponent zawiera następujący kod HTML:

<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="/pl/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>

Test wykonujący audyt:
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()
    });
});

Po uruchomieniu testu zwrócono następujące komunikaty o błędach:
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)"

Jak widać, zwrócono nie tylko komunikaty o błędach, ale także sugestie dotyczące rozwiązania każdego konkretnego problemu. Powyższe błędy dotyczą:
  • Nieprawidłowa kolejność nagłówków – użycie h4 bezpośrednio po h2 bez pośredniego h3
  • Obraz bez atrybutu alt – brak tekstu alternatywnego dla obrazu z klasą „banner-image”
  • Link bez zawartości tekstowej - pusty <a> tag bez atrybutów zawartości lub dostępności
  • Wybierz element bez etykiety – lista rozwijana bez powiązanej etykiety
  • Nieprawidłowa wartość atrybutu ARIA — użyto „falsy” zamiast prawidłowej wartości „false” dla aria-hidden

Drugi scenariusz

W tym scenariuszu komponent zawiera teraz poprawny, stały kod HTML.
<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="/pl/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>

Aby uzyskać więcej informacji na temat testowania dostępności i szczegółowych scenariuszy użycia różnych narzędzi, zobacz nasz ostatni artykuł

Podsumowanie

Jest-axe łatwo integruje się z Jest i umożliwia wykrywanie podstawowych problemów z dostępnością w HTML. Działa również z popularnymi frameworkami, takimi jak Angular, React i Vue.

Nie zapewnia jednak kompleksowego wsparcia w zakresie audytu dostępności.

Dlatego też Jest-axe powinno być wykorzystywane jako dodatkowe narzędzie wspomagające, obok ręcznego testowania dostępności i audytów obejmujących osoby niepełnosprawne, a nie jako narzędzie je zastępujące.

Przydatne linki

- repozytorium bibliotek jest-axe

  • UX
  • WCAG

Autorzy

Wojciech Stolarski
Regularny programista Fullstack
Regularny programista Fullstack w Consdata od 2022 roku.