Episode ini membahas pemeriksaan aksesibilitas otomatis dengan integrasi axe-core, validasi ARIA roles, labels, dan keyboard navigation, pengujian contrast dan focus state, serta menambahkan assertion aksesibilitas ke regression suite.

Aplikasi yang tidak bisa dipakai oleh pengguna dengan disabilitas bukan hanya masalah etika — ia adalah masalah bisnis, dan semakin sering menjadi masalah hukum. Episode 17 ini membahas accessibility testing: memastikan aplikasi bisa dinavigasi dan dipahami oleh semua orang, termasuk pengguna screen reader dan keyboard-only.
Dua pendekatan saling melengkapi di sini. axe-core memberikan audit otomatis terhadap aturan aksesibilitas yang terstandar, sementara assertion Playwright memverifikasi struktur ARIA, focus state, dan alur keyboard secara eksplisit. Keduanya bisa menjadi bagian dari regression suite yang berjalan setiap hari.
@axe-core/playwright menyediakan integrasi langsung dengan halaman Playwright:
npm install -D @axe-core/playwrightPackage ini mengekspos API AxeBuilder yang memindai halaman dan mengembalikan daftar pelanggaran.
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('halaman login bebas dari pelanggaran aksesibilitas', async ({ page }) => {
await page.goto('/login');
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});new AxeBuilder({ page }).analyze() memindai halaman dan mengembalikan results.violations — daftar pelanggaran beserta dampak dan solusinya. Assertion expect(results.violations).toEqual([]) memaksa halaman bersih dari pelanggaran.
Setiap violation berisi informasi lengkap: id aturan, dampak (critical, serious, moderate), deskripsi, dan node yang bermasalah. Jangan buru-buru men-disable aturan; lebih baik perbaiki akar masalahnya. Untuk pelanggaran yang memang tidak relevan dengan konteks aplikasi, gunakan disableRules dengan catatan yang jelas.
Assertion Playwright bekerja sangat baik dengan ARIA karena getByRole dan accessible name adalah intinya. Kalian bisa memverifikasi struktur aksesibilitas secara langsung:
import { test, expect } from '@playwright/test';
test('navigasi utama memiliki role navigation', async ({ page }) => {
await page.goto('/beranda');
const nav = page.getByRole('navigation');
await expect(nav).toBeVisible();
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});page.getByRole('navigation') mencari elemen dengan peran navigation. Jika navigasi utama tidak memakai <nav> atau role="navigation", assertion ini gagal — persis yang kalian inginkan dari test aksesibilitas.
Input form tanpa label adalah pelanggaran yang sangat umum. Assertion role textbox yang diakses via nama yang benar menegakkan aturan ini:
await page.getByLabel('Alamat Email').fill('user@example.com');
await page.getByRole('textbox', { name: 'Kata Sandi' }).fill('rahasia123');getByLabel('Alamat Email') hanya menemukan input jika ada label yang benar-benar terasosiasi — baik lewat elemen <label> maupun atribut aria-label. Test ini secara tidak langsung memverifikasi aksesibilitas form.
Pengguna keyboard-only menavigasi dengan Tab dan Enter. Playwright bisa mensimulasikan alur ini:
test('login bisa diselesaikan hanya dengan keyboard', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').focus();
await page.keyboard.press('Tab');
await page.keyboard.type('rahasia123');
await page.keyboard.press('Enter');
await expect(page).toHaveURL(/dashboard/);
});page.keyboard.press('Tab') memindahkan focus ke elemen berikutnya dalam urutan tab. Alur keyboard di atas memverifikasi bahwa form bisa diisi dan dikirim tanpa mouse sama sekali.
Elemen interaktif wajib memiliki focus indicator yang terlihat. Cara sederhana memverifikasinya adalah dengan focus lalu memeriksa apakah style berubah — atau lebih praktis, pastikan elemen mendapatkan focus dan bisa dipakai:
await page.getByRole('link', { name: 'Menu' }).focus();
await expect(page.getByRole('link', { name: 'Menu' })).toBeFocused();toBeFocused() memastikan elemen menerima focus. Kombinasi dengan alur keyboard menegaskan bahwa elemen interaktif benar-benar bisa di-focus, bukan sekadar ada di DOM.
Kontras warna adalah aturan yang kompleks dan bergantung pada perhitungan warna. Meski bisa diperiksa manual, cara yang paling andal adalah lewat aturan axe (misalnya color-contrast) yang sudah kita aktifkan di audit otomatis. Pastikan aturan contrast tidak di-disable.
Struktur semantik — heading yang benar, list, tombol yang bukan div — adalah fondasi aksesibilitas. Audit axe mencakup banyak aturan ini secara otomatis. Sebagai lapisan tambahan, assertion struktur bisa diperiksa eksplisit:
const headings = page.getByRole('heading');
expect(await headings.count()).toBeGreaterThan(0);
await expect(headings.first()).toHaveText('Dashboard');Memastikan halaman memiliki heading yang benar membantu screen reader user menavigasi dokumen. Audit otomatis plus assertion eksplisit memberi dua lapis pertahanan.
Audit axe pada setiap halaman menambah waktu suite. Strategi sehat: jalankan audit lengkap pada halaman-halaman inti (login, checkout, beranda), bukan pada setiap halaman kecil. Fokus pada alur kritis dulu, lalu perluas cakupan bertahap.
Snapshot visual dan audit aksesibilitas sama-sama sensitif terhadap konten. Gunakan mock data yang stabil (episode 12) agar hasil audit konsisten di setiap lari — bukan data acak yang mengubah jumlah node bermasalah.
Bungkus audit dalam helper agar mudah dipakai dan konsisten:
import AxeBuilder from '@axe-core/playwright';
export async function assertAccessible(page) {
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
}assertAccessible(page) memindai halaman dan melempar error jika ada pelanggaran. Satu baris ini bisa dipanggil di akhir setiap test penting, menjaga lapisan aksesibilitas selalu terjaga.
npx playwright test tests/aksesibilitas.spec.tsEpisode 17 membuat aksesibilitas menjadi bagian dari definisi "selesai": audit axe-core otomatis mendeteksi pelanggaran standar, assertion role dan label memverifikasi struktur ARIA, alur keyboard menguji navigasi tanpa mouse, dan helper assertAccessible mengintegrasikan semua itu ke regression suite yang berjalan setiap hari.
Inti yang harus dibawa pulang:
AxeBuilder memberikan audit otomatis terhadap aturan aksesibilitas standar.getByRole dan getByLabel memverifikasi ARIA roles dan label secara alami.keyboard.press untuk alur tanpa mouse.Di episode 18 selanjutnya kita akan membahas custom tooling dan extensions — membuat custom test fixtures dan helpers, memperluas Playwright dengan plugins dan reporters, integrasi dengan test utilities dan codegen scripts, serta berbagi utilities antar project.