Skip to content

Commit 5ebc5f6

Browse files
committed
[2025-05-19] Poprawki do czy wiesz że
1 parent 3c17d04 commit 5ebc5f6

1 file changed

Lines changed: 211 additions & 29 deletions

File tree

_posts/pl/2025-05-19-automatyczne-testowanie-dostepnosci.md

Lines changed: 211 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,43 +11,225 @@ image: /assets/img/posts/2025-05-19-automatyczne-testowanie-dostepnosci/thumbnai
1111
tags:
1212
- wcag
1313
---
14-
Jeśli projekt wykorzystuje bibliotekę `jest`, to nie wiele wystarczy, aby dodać testy sprawdzające zgodność z WCAG.
1514

16-
`jest-axe` to biblioteka, która umożliwia testowanie dostępności w testach jednostkowych w środowisku `jest`. Pozwala sprawdzić, czy komponenty napisane w `React`, `Angular` czy innych frameworkach spełniają wytyczne WCAG.
1715

18-
Przykład dla Angular:
19-
- W pliku `test-setup.ts` należy zaimportować `jest-axe/extend-expect`
20-
- Poniższy przykład obrazuje test dla komponentu `SomeComponent`:
16+
Jeśli projekt wykorzystuje bibliotekę Jest, dodanie testów sprawdzających zgodność komponentów z WCAG jest proste i nie
17+
wymaga dużego nakładu pracy.
18+
19+
20+
# Czym jest jest-axe?
21+
Jest-axe to narzędzie do automatycznego testowania dostępności, oparte na silniku axe-core. Działa podobnie jak lintery
22+
kodu (np. eslint czy stylelint), czyli wykrywa typowe problemy, ale nie gwarantuje pełnej zgodności z wymaganiami
23+
dostępności.
24+
Integruje się z biblioteką Jest i pozwala analizować HTML komponentów pod kątem błędów dostępności, takich jak:
25+
- brakujące atrybuty alt w obrazkach,
26+
- nieprawidłowe role ARIA,
27+
- nagłówki bez odpowiedniej hierarchii,
28+
29+
30+
Dodaje do testów matcher `toHaveNoViolations`, który umożliwia prostą walidację wyników analizy.
31+
32+
<br/><br/>
33+
***Uwaga!***
34+
Jest-axe nie zastępuje ręcznego audytu dostępności. Automatyczne testy są tylko wsparciem i nie wychwycą wszystkich
35+
problemów. Pełną ocenę powinny przeprowadzać osoby posiadające wiedzę w tym zakresie.
36+
37+
# Co jest-axe może przeoczyć?
38+
Ważnym jest, aby mieć świadomość ograniczeń tego narzędzia. Jest-axe może nie wykryć m.in.:
39+
40+
- problemów z kontrastem,
41+
- pełnej oceny struktury semantycznej,
42+
- niektórych problemów z interaktywnymi elementami,
43+
- problemów z nawigacją klawiaturową,
44+
- problemów kontekstowych
45+
46+
# Integracja z Angular
47+
48+
Do projektu zawierajacego Jest należy zainstalować Jest-axe
49+
50+
## Krok 1: Instalacja
51+
52+
```bash
53+
npm install --save-dev jest-axe @types/jest-axe
54+
```
55+
56+
## Krok 2: Konfiguracja
57+
58+
Do pliku z konfiguracją testów np. `test-setup.ts`, należy dodać import
59+
60+
```typescript
61+
import 'jest-axe/extend-expect';
62+
```
63+
64+
## Krok 3: Podstawowy test dostępności komponentu
65+
66+
W pliku `test-setup.ts` należy zaimportować `jest-axe/extend-expect`
67+
68+
# Testy
69+
70+
Kiedy wszystko zostało już skonfigurowanie, nie pozostaje nic innego jak użycie narzędzia w testach.
71+
W pliku z testami należy dodać import `import { axe } from 'jest-axe';`. Następnie dzięki `axe(fixture.nativeElement)`,
72+
uruchomiona zostanie analiza dostępności dla wygenerowanego HTMLa komponentu.
73+
Wynik analizy musi zostać sprawdzony przy użyciu metody `toHaveNoViolations`, w następujący sposób:
74+
`expect(results).toHaveNoViolations()`.
75+
76+
## Przypadki testowe
77+
78+
Dla przypadkach testowych zostały utworzone dwa komponent. Dla pierwszego HTML, nie spełni audytu, a dla drugiego
79+
spełni.
80+
81+
### Pierwszy scenariusz
82+
83+
Komponent posiada następujący kod HTML:
84+
85+
```html
86+
<div class="container">
87+
<!-- Błąd: Nieprawidłowa kolejność nagłówków (h4 po h2 bez h3) -->
88+
<h2>Główny nagłówek</h2>
89+
<h4>Polecane akcesoria</h4>
90+
91+
<!-- Błąd: Obraz bez atrybutu alt -->
92+
<img src="product.jpg" class="banner-image">
93+
94+
<!-- Błąd: Link bez treści (pusty link) -->
95+
<a href="/home" class="home-link"></a>
96+
97+
<!-- Błąd: Element select bez etykiety -->
98+
<select>
99+
<option value="">Wybierz temat...</option>
100+
<option value="question">Pytanie</option>
101+
<option value="complaint">Reklamacja</option>
102+
</select>
103+
104+
<!-- Błąd: Atrybut ARIA z nieprawidłową wartością -->
105+
<div aria-hidden="falsy">Ukryta treść</div>
106+
</div>
107+
```
108+
109+
Test wykonujący audyt:
21110

22111
```typescript
23-
import { ComponentFixture, TestBed } from "@angular/core/testing";
24-
import { axe } from "jest-axe";
25-
26-
import { SomeComponent } from "./some.component";
27-
28-
describe("SomeComponent", () => {
29-
let fixture: ComponentFixture<SomeComponent>;
30-
31-
beforeEach(() => {
32-
TestBed.configureTestingModule({
33-
declarations: [SomeComponent],
112+
import {ComponentFixture, TestBed} from '@angular/core/testing';
113+
114+
import {MyComponent} from './my.component';
115+
import {axe} from 'jest-axe';
116+
117+
describe('MyComponent', () => {
118+
let component: MyComponent;
119+
let fixture: ComponentFixture<MyComponent>;
120+
121+
beforeEach(async () => {
122+
await TestBed.configureTestingModule({
123+
imports: [MyComponent]
124+
})
125+
.compileComponents();
126+
127+
fixture = TestBed.createComponent(MyComponent);
128+
component = fixture.componentInstance;
129+
fixture.detectChanges();
130+
});
131+
132+
it('should pass accessibility tests', async () => {
133+
const results = await axe(fixture.nativeElement);
134+
expect(results).toHaveNoViolations()
34135
});
35-
36-
fixture = TestBed.createComponent(SomeComponent);
37-
});
38-
39-
it("should have no violations", async () => {
40-
const results = await axe(fixture.nativeElement);
41-
expect(results).toHaveNoViolations();
42-
});
43136
});
137+
44138
```
45139

46-
Dla powyższego:
47-
- `axe(fixture.nativeElement)` - uruchamia analizę dostępności dla wygenerowanego HTMLa komponentu
48-
- `expect(results).toHaveNoViolations();` - sprawdza, czy nie znaleziono żadnych błędów związanych z dostępnością (czy np. brakujące atrybutu alt dla obrazków)
140+
Po uruchomieniu testu, zwrócony został następujące komunikaty błędów
141+
142+
```
143+
expect(received).toHaveNoViolations(expected)
144+
Expected the HTML found at $('div[aria-hidden="falsy"]') to have no violations:
145+
<div aria-hidden="falsy">Ukryta treść</div>
146+
147+
Received:
148+
"ARIA attributes must conform to valid values (aria-valid-attr-value)"
149+
150+
Fix all of the following:
151+
Invalid ARIA attribute value: aria-hidden="falsy"
152+
153+
You can find more information on this issue here:
154+
https://dequeuniversity.com/rules/axe/4.10/aria-valid-attr-value?application=axeAPI
155+
────────
156+
...
157+
158+
Received:
159+
"Heading levels should only increase by one (heading-order)"
160+
161+
...
162+
────────
163+
...
164+
165+
Received:
166+
"Images must have alternative text (image-alt)"
167+
168+
...
169+
────────
170+
...
171+
172+
Received:
173+
"Links must have discernible text (link-name)"
174+
175+
...
176+
────────
177+
...
178+
179+
Received:
180+
"Select element must have an accessible name (select-name)"
181+
182+
```
183+
184+
Jak widać nie tylko zostały zwrócone komunikaty błędów, ale też podpowiedzi jak naprawić konkretne błędy.
185+
186+
Powyższe błędy dotyczą:
187+
- nieprawidłowej kolejność nagłówków - użycie `h4` bezpośrednio po `h2` bez `h3` pomiędzy nimi
188+
- obrazu bez atrybutu alt - brak tekstu alternatywnego dla obrazu z klasą "banner-image"
189+
- linku bez treści - pusty znacznik `<a>` bez żadnej zawartości ani atrybutów dostępności
190+
- elementu select bez etykiety - rozwijana lista bez powiązanej etykiety
191+
- nieprawidłowej wartość atrybutu ARIA - użycie "falsy" zamiast "false" dla aria-hidden
192+
193+
194+
### Drugi scenariusz
195+
196+
W tym scenariuszu komponent posiada już prawidłowy, poprawiony HTML.
197+
198+
```html
199+
<div class="container">
200+
<!-- Poprawna hierarchia nagłówków -->
201+
<h2 id="main-heading">Główny nagłówek</h2>
202+
<h3 id="recommended-heading">Polecane akcesoria</h3>
203+
204+
<!-- Dodany atrybut alt dla obrazu -->
205+
<img src="product.jpg" class="banner-image" alt="Zdjęcie produktu">
206+
207+
<!-- Link zawiera teraz tekst -->
208+
<a href="/home" class="home-link">Strona główna</a>
209+
210+
<!-- Element select z właściwą etykietą -->
211+
<label for="topic-select">Wybierz temat:</label>
212+
<select id="topic-select" name="topic">
213+
<option value="">Wybierz temat...</option>
214+
<option value="question">Pytanie</option>
215+
<option value="complaint">Reklamacja</option>
216+
</select>
217+
218+
<!-- Poprawna wartość atrybutu ARIA -->
219+
<div aria-hidden="true">Ukryta treść</div>
220+
</div>
221+
```
222+
Wywołanie testu jest takie samo jak w poprzednim przykładzie, a sam test będzie pozytywny.
223+
224+
225+
# Podsumowanie
226+
Jest-axe łatwo integruje się z Jest, pozwala wykrywać proste błędy dostępności w HTML i działa z popularnymi
227+
frameworkami (Angular, React, Vue).
228+
Nie wspiera on jednak pełnego wsparcia audytorskiego pod kątem dostępności.
229+
49230

50-
Dzięki kilku linijkom kodu przeprowadzenie audytu całego systemu projektowego pod kątem problemów z dostępnością staje się wykonalne! Warto pamiętać, że testy automatyczne wykryją tylko część problemów. **Nie gwarantują** one, że komponent jest w pełni dostępny.
231+
Dlatego jest-axe powinien być traktowany jako wsparcie, a nie zastępstwo dla ręcznych testów dostępności i audytów z
232+
udziałem osób z niepełnosprawnościami.
51233

52234
## Przydatne linki
53-
- [Repozytorium biblioteki jest-axe](https://github.com/nickcolley/jest-axe)
235+
- [Repozytorium biblioteki jest-axe](https://github.com/nickcolley/jest-axe)

0 commit comments

Comments
 (0)