---
name: e2e-testing-expert
description: "Expert guide for End-to-End (E2E) testing with Playwright 1.50+, Clock API, ARIA snapshots, test fixtures, and Vitest 3+ / Panduan ahli pengujian E2E dengan Playwright 1.50+, Clock API, ARIA snapshots, dan Vitest 3+."
author: "Roedy Rustam"
version: "4.4.2"
---
# E2E Testing Expert (Playwright 1.50+ & Vitest 3 Standard)
[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
---
## English
### Orchestration & Integration
- **TDD & Autonomous Debugging**: `autonomous-tdd-debugger`, `property-mutation-testing-expert`
- **Quality Gates & Anti-Slop**: `anti-slop`, `ai-code-review-autonomous`, `zero-tech-debt-auditor`
- **Accessibility & Browser Automation**: `accessibility-testing-expert`, `browser-automation-expert`
- **CI/CD & DevOps Automation**: `ci-cd-devops-architect`, `github-actions-expert`
- **Lifecycle & Governance**: `brainstorming`, `zero-to-prod-orchestrator`, `session-memory-manager`
### Description
Production-grade guide for automated browser and component testing using **Playwright 1.50+** and **Vitest 3+**. Covers virtual clock manipulation with `page.clock`, semantic accessibility assertions with `toMatchAriaSnapshot`, type-safe composable fixtures, dynamic UI banner interception (`page.addLocatorHandler`), session state reuse (`storageState`), and CI matrix sharding.
### Trigger Conditions
- Writing End-to-End (E2E) browser test suites for Next.js 15, React 19, or Svelte 5 applications.
- Testing time-sensitive UI (countdown timers, session expiries, debounced search) deterministically.
- Verifying WCAG accessibility tree structure using semantic `aria-snapshot`.
- Creating composable test fixtures with authenticated contexts and isolated database state.
- Setting up parallel CI test execution with artifact uploads on test failure.
---
### Playwright 1.50+ Core Architectural Patterns
#### 1. Deterministic Time Testing with the Clock API (`page.clock`)
Eliminate flaky `page.waitForTimeout` by freezing, fast-forwarding, or setting system time:
```typescript
// tests/e2e/timer.spec.ts
import { test, expect } from '@playwright/test';
test('advances countdown timer deterministically', async ({ page }) => {
// 1. Install virtual clock fixed at specific timestamp
await page.clock.install({ time: new Date('2026-03-01T12:00:00Z') });
await page.goto('/promotions/flash-sale');
// Verify initial state
const countdown = page.getByRole('timer');
await expect(countdown).toHaveText('24:00:00');
// 2. Fast forward 6 hours in 1 millisecond without waiting!
await page.clock.fastForward('06:00:00');
await expect(countdown).toHaveText('18:00:00');
// 3. Fast forward past expiration
await page.clock.fastForward('18:00:01');
await expect(page.getByRole('alert')).toHaveText('This promotion has ended.');
});
```
#### 2. Semantic Accessibility Assertions (`toMatchAriaSnapshot`)
Assert the rendered accessible role tree rather than fragile DOM classes:
```typescript
// tests/e2e/navigation.spec.ts
import { test, expect } from '@playwright/test';
test('navigation bar renders semantic accessible structure', async ({ page }) => {
await page.goto('/');
const header = page.locator('header');
await expect(header).toMatchAriaSnapshot(`
- banner:
- link "Brand Logo":
- /url: //
- navigation:
- link "Products"
- link "Docs"
- link "Pricing"
- button "Sign in"
`);
});
```
#### 3. Automatic Banner & Dialog Interception (`page.addLocatorHandler`)
Dismiss cookie banners or dynamic popups automatically whenever they appear:
```typescript
// tests/e2e/fixtures.ts
import { test as base, expect } from '@playwright/test';
export const test = base.extend({
page: async ({ page }, use) => {
// Automatically dismiss cookie consent modals whenever they overlay the page
const consentButton = page.getByRole('button', { name: 'Accept all cookies' });
await page.addLocatorHandler(consentButton, async () => {
await consentButton.click();
});
await use(page);
},
});
```
#### 4. Reusable Authentication State (`storageState`)
Authenticate once in a setup project and inject session cookies into all test suites:
```typescript
// tests/e2e/auth.setup.ts
import { test as setup, expect } from '@playwright/test';
const authFile = 'playwright/.auth/admin.json';
setup('authenticate admin user', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('admin@enterprise.test');
await page.getByLabel('Password').fill('VaultP@ssw0rd2026!');
await page.getByRole('button', { name: 'Sign in' }).click();
await page.waitForURL('/dashboard');
await expect(page.getByRole('heading', { name: 'Overview' })).toBeVisible();
// Persist storage state (cookies, localStorage, session tokens)
await page.context().storageState({ path: authFile });
});
```
```typescript
// tests/e2e/billing.spec.ts
import { test, expect } from '@playwright/test';
// Reuse authenticated state automatically
test.use({ storageState: 'playwright/.auth/admin.json' });
test('admin can view billing invoices', async ({ page }) => {
await page.goto('/billing/invoices');
await expect(page.getByRole('heading', { name: 'Invoices' })).toBeVisible();
});
```
#### 5. CI Test Sharding in GitHub Actions
Split Playwright test executions across parallel workers in CI:
```yaml
# .github/workflows/e2e.yml
name: Playwright Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '22', cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
- run: pnpm exec playwright install --with-deps chromium
- name: Run Playwright Tests (Shard ${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
run: pnpm exec playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-blob-${{ matrix.shardIndex }}
path: blob-report/
```
### Sovereign Execution, Token Efficiency & Invariants
| Dimension | Sovereign Mandate & Deterministic Contract |
| :--- | :--- |
| **Frontier Model Cascade** | High Fast / High (`Grok 4.7 High Fast`, `Claude Sonnet 5.5 High`, `Gemini 4 Pro`) |
| **Availability Fallback** | `Gemini 4 Pro` -> `Gemini 3.8 Flash`; `Claude Opus 5.5` -> `Claude Opus 4.6`; `Grok 4.7` -> `Grok 4.6 High Fast` (Zero unhandled missing-model errors) |
| **KV-Cache & Token Protocol** | Pin static instructions & schemas at prompt prefix (`kv-cache-prefix-optimizer`); pass surgical `CONTEXT_MAP.md` slices (<250 tokens/call) during Swarm Fan-Out |
| **SaaT CLI & MCP Dispatch** | CLI: `vibes skill exec e2e-testing-expert ` / MCP: `vibes_skill_dispatch`, `vibes_critic_validate`, `vibes_self_heal`, `vibes_eval_sandbox`, `vibes_verify_invariants` |
| **NFR & Anti-Slop Invariants** | Zero OWASP Top 10 vectors, 0 hardcoded secrets, >= 90% branch coverage on domain logic, 0 Anti-Slop violations; 100% complete zero-placeholder output verified via `node scripts/check-anti-slop.js --strict` |
---
---
## Bahasa Indonesia
### Integrasi Orkestrasi
- **TDD & Debugging Otonom**: `autonomous-tdd-debugger`, `property-mutation-testing-expert`
- **Gerbang Kualitas & Anti-Slop**: `anti-slop`, `ai-code-review-autonomous`, `zero-tech-debt-auditor`
- **Aksesibilitas & Otomasi Browser**: `accessibility-testing-expert`, `browser-automation-expert`
- **CI/CD & Otomasi DevOps**: `ci-cd-devops-architect`, `github-actions-expert`
- **Siklus Hidup & Tata Kelola**: `brainstorming`, `zero-to-prod-orchestrator`, `session-memory-manager`
### Deskripsi
Panduan produksi untuk pengujian browser dan komponen otomatis menggunakan **Playwright 1.50+** dan **Vitest 3+**. Mencakup manipulasi jam virtual deterministik dengan `page.clock`, asersi pohon aksesibilitas semantis dengan `toMatchAriaSnapshot`, pembuatan test fixture modular, penanganan banner modal dinamis (`page.addLocatorHandler`), penggunaan ulang sesi autentikasi (`storageState`), dan sharding paralel di CI.
### Kondisi Pemicu
- Menulis test suite E2E browser untuk aplikasi Next.js 15, React 19, atau Svelte 5.
- Menguji antarmuka berbasis waktu (countdown timer, kedaluwarsa sesi) secara deterministik tanpa jeda waktu riil.
- Memvalidasi struktur pohon aksesibilitas menggunakan asersi semantis `aria-snapshot`.
- Mengonfigurasi fixture pengujian dengan isolasi state autentikasi dan database.
- Menjalankan pipeline pengujian terdistribusi secara paralel di GitHub Actions.
---
### Pola Kunci Playwright 1.50+
#### 1. Pengujian Waktu Deterministik Menggunakan Clock API (`page.clock`)
Hilangkan ketergantungan pada `time.Sleep` atau `waitForTimeout` dengan memajukan jam virtual seketika:
```typescript
import { test, expect } from '@playwright/test';
test('menguji countdown diskon secara deterministik', async ({ page }) => {
// 1. Pasang jam virtual pada tanggal tertentu
await page.clock.install({ time: new Date('2026-03-01T12:00:00Z') });
await page.goto('/promo');
const timer = page.getByRole('timer');
await expect(timer).toHaveText('24:00:00');
// 2. Majukan waktu 6 jam secara instan (1 milidetik)
await page.clock.fastForward('06:00:00');
await expect(timer).toHaveText('18:00:00');
// 3. Majukan hingga waktu promo berakhir
await page.clock.fastForward('18:00:01');
await expect(page.getByRole('alert')).toHaveText('Promo ini telah berakhir.');
});
```
#### 2. Asersi Aksesibilitas Semantis (`toMatchAriaSnapshot`)
Validasi struktur aksesibilitas UI tanpa terikat pada class CSS atau tag DOM yang rapuh:
```typescript
import { test, expect } from '@playwright/test';
test('navigasi memenuhi standar aksesibilitas', async ({ page }) => {
await page.goto('/');
await expect(page.locator('header')).toMatchAriaSnapshot(`
- banner:
- link "Logo":
- /url: //
- navigation:
- link "Produk"
- link "Dokumentasi"
- link "Harga"
- button "Masuk"
`);
});
```
#### 3. Penanganan Banner Otomatis (`page.addLocatorHandler`)
Tutup banner persetujuan cookie atau modal promosi secara otomatis kapan pun elemen tersebut muncul:
```typescript
import { test as base } from '@playwright/test';
export const test = base.extend({
page: async ({ page }, use) => {
const tombolCookie = page.getByRole('button', { name: 'Setujui semua' });
await page.addLocatorHandler(tombolCookie, async () => {
await tombolCookie.click();
});
await use(page);
},
});
```
### Matriks Eksekusi Berdaulat, Efisiensi Token & Invarian
| Dimensi | Mandat Berdaulat & Kontrak Deterministik |
| :--- | :--- |
| **Kaskade Model Frontier** | High Fast / High (`Grok 4.7 High Fast`, `Claude Sonnet 5.5 High`, `Gemini 4 Pro`) |
| **Invarian Fallback Ketersediaan** | `Gemini 4 Pro` -> `Gemini 3.8 Flash`; `Claude Opus 5.5` -> `Claude Opus 4.6`; `Grok 4.7` -> `Grok 4.6 High Fast` (Bebas gagal saat model belum tersedia/kuota penuh) |
| **Protokol Hemat Token & KV-Cache** | Kunci instruksi & skema statis di prefix awal (`kv-cache-prefix-optimizer`); kirim potongan `CONTEXT_MAP.md` (<250 token/panggilan) saat Fan-Out |
| **Eksekusi SaaT CLI & MCP** | CLI: `vibes skill exec e2e-testing-expert ` / MCP: `vibes_skill_dispatch`, `vibes_critic_validate`, `vibes_self_heal`, `vibes_eval_sandbox`, `vibes_verify_invariants` |
| **Invarian NFR & Anti-Slop** | Nol celah OWASP Top 10, 0 kredensial hardcoded, cakupan pengujian >= 90% pada logika domain, 0 pelanggaran Anti-Slop; kode 100% tuntas tanpa placeholder diverifikasi melalui `node scripts/check-anti-slop.js --strict` |