Episode ini membedah arsitektur Playwright: peran Browser, BrowserContext, dan Page, perbedaan test runner dengan standalone API, test lifecycle dari launch hingga close, serta struktur project dan konfigurasi dasar yang menjadi fondasi seluruh series.

Episode 1 menjelaskan mengapa Playwright dipilih. Sekarang saatnya memahami bagaimana dia bekerja. Episode 2 ini membedah arsitektur Playwright dari komponen paling kecil sampai struktur project, agar kalian tahu persis apa yang terjadi di belakang layar saat sebuah test berjalan.
Pemahaman arsitektur bukan sekadar teori. Ketika nanti kalian menghadapi bug aneh — misalnya state yang bocor antar test, atau context yang tidak sengaja tertukar — jawabannya hampir selalu ada di level arsitektur: siapa yang memiliki browser, context mana yang dipakai, dan bagaimana siklus hidup tiap komponen. Mari kita bangun fondasi itu sekarang.
Browser adalah tingkat teratas: instance dari Chromium, Firefox, atau WebKit yang diluncurkan dari chromium.launch(). Satu instance browser bisa membuka banyak context. Meluncurkan browser adalah operasi berat, jadi Playwright secara default menjalankan browser per file test, bukan per test.
BrowserContext adalah kontainer terisolasi di dalam browser. Setiap context memiliki session penyimpanan, cookies, localStorage, dan service worker sendiri yang benar-benar terpisah dari context lain. Inilah kunci isolasi di Playwright: dua context di browser yang sama tidak bisa saling melihat data satu sama lain. Kita akan memanfaatkan isolasi ini untuk paralelisme dan keamanan di episode 13.
Page adalah tab atau halaman web di dalam sebuah context. Setiap aksi — klik, isi form, navigasi — beroperasi di level page. Sebuah context bisa membuka banyak page, misalnya untuk menangani popup atau multiple tabs. Alur hierarkinya:
Browser
└── BrowserContext
└── Page
└── DOM + Network + JSSelain browser web, Playwright juga bisa mengontrol aplikasi Electron via class _electron.launch(). Ini berguna untuk menguji aplikasi desktop yang dibangun dengan Electron — aplikasi yang memakai Chromium sebagai runtime. Dukungan ini membuat Playwright melayani tidak hanya web, tapi juga aplikasi hybrid desktop.
Sejak versi 1.0, Playwright menyediakan test runner bawaan dari package @playwright/test. Runner ini menyediakan fixtures seperti test, expect, page, dan request, plus fitur paralelisme, retries, report, dan integrations CI. Mayoritas series ini memakai test runner.
Playwright juga bisa dipakai sebagai library standalone lewat package playwright tanpa test runner — ideal untuk script automation, scraping, atau tooling non-test. Kedua mode memakai API inti yang sama, tapi test runner menambahkan lapisan orchestration.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close();
})();Perhatikan urutan browser.launch() → browser.newContext() → context.newPage() → browser.close(). Urutan ini adalah test lifecycle yang akan kita bahas berikutnya.
Dalam test runner, lifecycle diotomatiskan melalui fixtures. Saat sebuah test meminta page, runner akan meluncurkan browser, membuat context baru, membuka page baru, menjalankan test, lalu membersihkan semuanya setelah selesai — termasuk menutup context dan browser.
Tahapan lengkapnya:
Untuk skenario khusus, kalian bisa mengontrol lifecycle secara eksplisit memakai fixtures browser dan context:
import { test, expect } from '@playwright/test';
test('context manual', async ({ browser }) => {
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example/);
await context.close();
});Memakai browser.newContext() di dalam test memberi kalian kendali penuh — termasuk membuat beberapa context sekaligus atau menutup context lebih awal. Default test runner tetap paling aman untuk kebanyakan kasus.
Sebuah project Playwright yang rapi biasanya tersusun seperti ini:
playwright-project
├── tests/
│ ├── login.spec.ts
│ └── checkout.spec.ts
├── playwright.config.ts
├── package.json
└── .gitignoreFile test diletakkan di direktori tests, dan file konfigurasi playwright.config.ts berdiri di root. Ekstensi .spec.ts dan .spec.js dikenali otomatis oleh runner.
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30000,
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
],
});testDir menentukan tempat test berada, timeout mengatur batas waktu per test, dan use.baseURL menjadi dasar URL untuk page.goto(). Detail lengkap konfigurasi, termasuk retries dan webServer, akan kita bedah di episode 3.
Episode 2 memberi kalian fondasi arsitektur: hierarki Browser → BrowserContext → Page yang menjadi model mental semua operasi Playwright, dukungan Electron untuk aplikasi desktop, perbedaan test runner dengan standalone API, test lifecycle dari launch hingga close, serta struktur project dan konfigurasi dasar.
Inti yang harus dibawa pulang:
playwright.config.ts mengontrol testDir, timeout, dan project browser.Di episode 3 selanjutnya kita akan membahas instalasi dan konfigurasi dasar — menginstall Playwright dan browser dependencies, menyiapkan playwright.config.ts secara lengkap, menjalankan test pertama melalui CLI, serta mengelola timeout dan retries agar test suite kalian stabil sejak awal.