Testování přístupnosti pomocí Playwright: kontroly WCAG ve vaší sadě testů
Aktualizováno 14. října 2026 · Čtení na 6 min
Playwright ovládá skutečný prohlížeč a axe-core je open-source engine pravidel, na kterém stojí většina automatických kontrol přístupnosti. Společně promění kontroly WCAG v běžné testy: stránka, která získá tlačítko bez názvu nebo text s nízkým kontrastem, shodí build ještě dřív, než se dostane k zákazníkům. Tento průvodce ukazuje funkční příklady s @axe-core/playwright, možnosti pro komponenty React a Storybook, tipy pro CI a omezení, o kterých byste měli vědět.
Příklady vycházejí z oficiálního průvodce testováním přístupnosti v Playwright a z README @axe-core/playwright. Stejný engine používáme i v našem skeneru.
Instalace
npm install --save-dev @playwright/test @axe-core/playwright
Verze balíčku odpovídá verzi axe-core, kterou obsahuje. README uvádí, že se nedrží sémantického verzování, takže verzi zafixujte a aktualizujte ji záměrně: nové vydání axe může přidat pravidla, která najdou nové problémy.
První test WCAG
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
const WCAG_AA = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'];
test('úvodní stránka nemá žádná zjistitelná porušení WCAG A/AA', async ({ page }) => {
await page.goto('/');
const results = await new AxeBuilder({ page }).withTags(WCAG_AA).analyze();
expect(results.violations).toEqual([]);
});
withTags omezí běh na pravidla označená těmito verzemi a úrovněmi WCAG. Bez něj axe spouští i svá pravidla osvědčených postupů, která jsou užitečná, ale nejsou požadavky WCAG.
Testujte stavy, které lidé skutečně vidí
Stránka je víc než své první vykreslení. Nejdřív otevřete menu, postranní panel košíku nebo dialog s cookies a poté pomocí include zkontrolujte jen tuto část:
test('mobilní menu je po otevření přístupné', async ({ page }) => {
await page.goto('/');
await page.getByRole('button', { name: 'Menu' }).click();
const results = await new AxeBuilder({ page })
.include('#navigation-menu')
.withTags(WCAG_AA)
.analyze();
expect(results.violations).toEqual([]);
});
V e-shopu jsou dobrými kandidáty produktová stránka s vybranými variantami, košík s položkami, pokladna se zobrazenými chybami validace a přihlašovací formulář k účtu. Používání getByRole ve vašich testech je samo o sobě malý test přístupnosti: pokud Playwright nenajde tlačítko podle role a názvu, uživatel čtečky obrazovky ho pravděpodobně také nenajde.
Známé problémy bez vypínání testů
Skutečné projekty mají problémy, které dnes nevyřešíte, například uvnitř widgetu třetí strany. README nabízí tři nástroje:
const results = await new AxeBuilder({ page })
.exclude('#third-party-chat') // přeskočí prvek
.disableRules(['color-contrast']) // přeskočí pravidlo (používejte zřídka)
.withTags(WCAG_AA)
.analyze();
Lepším vzorem z průvodce Playwright je snapshot otisků: zaznamenáte, která pravidla selhávají u kterých prvků, a test selže jen tehdy, když se objeví něco nového.
const fingerprints = (results) =>
results.violations.map((v) => ({
rule: v.id,
targets: v.nodes.map((n) => n.target),
}));
expect(fingerprints(results)).toMatchSnapshot();
Dvě poznámky z README: include a exclude berou jeden selektor na volání (pro více je řetězte) a opakované volání withTags, withRules, disableRules nebo options přepíše předchozí volání.
Nejdřív selhávejte u toho, na čem záleží
Pokud je backlog velký, začněte nejzávažnějšími problémy. Každé porušení má impact minor, moderate, serious nebo critical:
const blocking = results.violations.filter((v) =>
['serious', 'critical'].includes(v.impact),
);
expect(blocking).toEqual([]);
Úplný výsledek připojte k reportu, aby ten, kdo problém opravuje, viděl každý prvek:
// uvnitř test('…', async ({ page }, testInfo) => { … })
await testInfo.attach('accessibility-scan-results', {
body: JSON.stringify(results, null, 2),
contentType: 'application/json',
});
Průvodce Playwright také ukazuje, jak AxeBuilder zabalit do testovací fixtury, takže každý test dostane stejné tagy a výjimky z jednoho místa.
Komponenty React: jest-axe a vitest-axe
Pro testy komponent vykreslovaných do JSDOM přidávají jest-axe a vitest-axe matcher toHaveNoViolations:
import { render } from '@testing-library/react';
import { axe } from 'vitest-axe';
import 'vitest-axe/extend-expect';
it('vykreslí přístupný formulář', async () => {
const { container } = render(<SignupForm />);
expect(await axe(container)).toHaveNoViolations();
});
Jsou rychlé a včas zachytí chybějící popisky a názvy. Dvě omezení z jejich README: jest-axe vypíná kontroly barevného kontrastu, protože v JSDOM nefungují, a vitest-axe nefunguje s prostředím happy-dom. Kontrast, rozvržení, zvětšení a fokus vyžadují skutečný prohlížeč, takže testy Playwright ponechte pro celé stránky.
Storybook
Doplněk přístupnosti pro Storybook spouští axe-core na každém příběhu:
npx storybook add @storybook/addon-a11y
U příběhů, které musejí zůstat čisté, nastavte parameters.a11y.test na 'error': porušení pak shodí test v rozhraní Storybooku i v CI. 'todo' je zobrazí jen jako varování a 'off' automatickou kontrolu přeskočí.
Tipy pro CI
- Spouštějte ve stejném pipeline jako ostatní testy. Průvodce CI pro Playwright používá
npm ci,npx playwright install --with-depsanpx playwright testa složkuplaywright-report/nahrává jako artefakt. - Testujte sestavenou stránku podobnou produkci, ne vývojový server s ladicími vrstvami.
- Vyberte krátký seznam klíčových URL (úvodní stránka, kategorie, produkt, košík, pokladna, přihlášení, obsahová stránka) místo procházení všeho při každém commitu.
- Držte verzi axe zafixovanou a aktualizujte ji ve vlastním pull requestu.
- Neschovávejte selhání dlouho za
disableRules; upřednostněteexcludepro jeden prvek nebo vzor se snapshotem.
Co vám automatické testy nepoví
README axe-core uvádí, že automaticky lze najít v průměru 57 % problémů WCAG, a průvodce Playwright je stejně jasný v tom, že automatizované testování nedokáže odhalit všechny typy porušení WCAG. Prázdné pole violations neznamená, že stránka splňuje WCAG 2.2 AA. Stále potřebujete projít web klávesnicí, zkontrolovat zvětšení a přizpůsobení obsahu a otestovat čtečku obrazovky. Tuto část popisuje náš průvodce testováním WCAG a checklist WCAG 2.2 označuje, které body vyžadují člověka.
Kde do toho zapadá Pandus
Testy v CI chrání kód, který měníte. Nevidí, co se děje na živém webu potom: aktualizace šablony, nová aplikace nebo plugin, marketingový banner, popis produktu vložený od dodavatele. Pandus kontroluje produkční web: každý týden všechny stránky, stejným enginem axe-core ve skutečném prohlížeči, a vytváří report, který si přečte majitel obchodu.
- API spouští kontroly a vrací výsledky jako JSON, s webhooky po dokončení kontroly nebo při nových problémech, což se hodí po nasazení.
- Rozšíření prohlížeče zkontroluje stránku tak, jak ji vidí váš prohlížeč, včetně testovacích webů a stránek za přihlášením.
- Bezplatný WCAG checker zkontroluje jednu veřejnou stránku bez účtu.
Pandus je automatizovaná kontrola, nikoli úplný audit, a není právním poradenstvím. Srovnání dalších nástrojů najdete v přehledu nástrojů pro testování přístupnosti.
Časté otázky
Jak testovat přístupnost pomocí Playwright?
Nainstalujte @axe-core/playwright, otevřete stránku v testu Playwright, spusťte new AxeBuilder({ page }).analyze() a ověřte, že pole violations je prázdné. Běh omezte na pravidla WCAG pomocí withTags, například wcag2a, wcag2aa, wcag21a, wcag21aa a wcag22aa.
Znamená úspěšný test axe, že stránka splňuje WCAG?
Ne. Automatická pravidla najdou jen část problémů WCAG. Deque, tvůrce axe-core, uvádí v průměru zhruba 57 % problémů. Ovládání klávesnicí, smysluplné alternativní texty, pořadí fokusu a srozumitelné chyby stále musí posoudit člověk.
Mohu místo toho použít jest-axe nebo vitest-axe?
Ano, pro komponenty vykreslené v JSDOM. Jsou rychlé, ale jest-axe vypíná kontroly barevného kontrastu, protože v JSDOM nefungují. Pro celé stránky ve skutečném prohlížeči, kde jde zkontrolovat kontrast, rozvržení i fokus, použijte Playwright.
Jak otestovat přístupnost komponent ve Storybooku?
Přidejte @storybook/addon-a11y. Spouští axe-core na každém příběhu; s parameters.a11y.test nastaveným na error porušení shodí test v rozhraní Storybooku i v CI.
Má build selhat při každém porušení?
Začněte tím, že selže u závažných a kritických problémů, a uchovávejte snapshot známých, takže nové problémy build shodí, zatímco staré se opravují postupně. Pravidlo zpřísněte, až bude backlog vyřešený.
Zdroje
- Playwright, Accessibility testing: https://playwright.dev/docs/accessibility-testing
- Playwright, Setting up CI: https://playwright.dev/docs/ci-intro
- Deque, @axe-core/playwright README: https://github.com/dequelabs/axe-core-npm/blob/develop/packages/playwright/README.md
- Deque, axe-core README: https://github.com/dequelabs/axe-core
- jest-axe README: https://github.com/NickColley/jest-axe
- vitest-axe README: https://github.com/chaance/vitest-axe
- Storybook, Accessibility tests: https://storybook.js.org/docs/writing-tests/accessibility-testing