Belajar Playwright - Accessibility Testing
Episode 17 of 23

Belajar Playwright - Accessibility Testing

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.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Pendahuluan

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.

Automated Accessibility Checks dengan axe-core

Menginstall dan Menyiapkan Axe

@axe-core/playwright menyediakan integrasi langsung dengan halaman Playwright:

Install axe-core untuk Playwright
npm install -D @axe-core/playwright

Package ini mengekspos API AxeBuilder yang memindai halaman dan mengembalikan daftar pelanggaran.

Menjalankan Audit Pertama

JSAudit aksesibilitas dengan axe
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.

Menafsirkan Hasil Audit

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.

Validating ARIA Roles, Labels, dan Keyboard Navigation

Memverifikasi Role dan Label

Assertion Playwright bekerja sangat baik dengan ARIA karena getByRole dan accessible name adalah intinya. Kalian bisa memverifikasi struktur aksesibilitas secara langsung:

JSVerifikasi role dan name
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.

Setiap Input Butuh Label

Input form tanpa label adalah pelanggaran yang sangat umum. Assertion role textbox yang diakses via nama yang benar menegakkan aturan ini:

JSInput terasosiasi dengan label
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.

Menguji Keyboard Navigation

Pengguna keyboard-only menavigasi dengan Tab dan Enter. Playwright bisa mensimulasikan alur ini:

JSNavigasi dengan keyboard
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.

Testing Contrast, Focus State, dan Semantic HTML

Focus State yang Terlihat

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:

JSVerifikasi focus state
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.

Contrast dan Warna

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.

Semantic HTML

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:

JSCek urutan heading
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.

Menambahkan Accessibility Assertions ke Regression Suite

Memisahkan Audit Berat

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.

Memakai Test Data yang Stabil

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.

Membuat Helper Audit

Bungkus audit dalam helper agar mudah dipakai dan konsisten:

JSHelper audit aksesibilitas
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.

Jalankan audit aksesibilitas
npx playwright test tests/aksesibilitas.spec.ts

Penutup

Episode 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.
  • Simulasikan navigasi keyboard dengan keyboard.press untuk alur tanpa mouse.
  • Jangan disable aturan axe tanpa alasan yang terdokumentasi.
  • Audit halaman inti terlebih dahulu, lalu perluas cakupan secara bertahap.

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.

Belajar Playwright - Accessibility Testing | Belajar Playwright