Belajar QA Automation Engineer - Web Automation (Playwright)
Episode 5 of 28

Belajar QA Automation Engineer - Web Automation (Playwright)

Menguasai Playwright untuk web automation: navigation, interaction, assertions, fixtures, dan test suite yang terstruktur dan maintainable

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Setelah di episode 4 kita mempelajari locators, pada episode ini kita mendalami Playwright — tool utama QA automation engineer. Playwright modern, cepat, dan punya fitur yang sangat membantu untuk E2E testing.

javascript
// Basic navigation
await page.goto('http://localhost:3000');
 
// Wait for specific load state
await page.goto('http://localhost:3000', { waitUntil: 'networkidle' });
 
// Reload
await page.reload();
 
// Navigate back/forward
await page.goBack();
await page.goForward();

Interaction

Form Interaction

javascript
// Fill input
await page.fill('#email', 'user@test.com');
await page.fill('#password', 'password123');
 
// Alternative: getByLabel
await page.getByLabel('Email').fill('user@test.com');
 
// Select dropdown
await page.selectOption('#country', 'ID');
 
// Checkbox
await page.check('#terms');
await page.uncheck('#terms');
 
// Radio button
await page.check('#option-1');
 
// File upload
await page.setInputFiles('#file', 'path/to/file.pdf');
 
// Date picker
await page.fill('#date', '2026-01-15');

Click & Hover

javascript
// Click
await page.click('#submit-button');
await page.getByRole('button', { name: 'Submit' }).click();
 
// Double click
await page.dblclick('.item');
 
// Right click
await page.click('.item', { button: 'right' });
 
// Hover
await page.hover('.dropdown-trigger');
await page.locator('.dropdown-menu').toBeVisible();
 
// Drag and drop
await page.dragAndDrop('#source', '#target');

Keyboard

javascript
// Type text
await page.keyboard.type('Hello World');
 
// Special keys
await page.keyboard.press('Enter');
await page.keyboard.press('Tab');
await page.keyboard.press('Escape');
 
// Key combinations
await page.keyboard.press('Control+a');
await page.keyboard.press('Control+c');

Fixtures

Built-in Fixtures

javascript
// page, browser, context — built-in
test('my test', async ({ page, browser, context }) => {
  // page: current page
  // browser: browser instance
  // context: browser context (isolated session)
});

Custom Fixtures

javascript
// fixtures.ts
import { test as base } from '@playwright/test';
 
type MyFixtures = {
  loginPage: LoginPage;
  dashboardPage: DashboardPage;
};
 
export const test = base.extend<MyFixtures>({
  loginPage: async ({ page }, use) => {
    const loginPage = new LoginPage(page);
    await use(loginPage);
  },
  dashboardPage: async ({ page }, use) => {
    const dashboardPage = new DashboardPage(page);
    await use(dashboardPage);
  },
});
 
export { expect } from '@playwright/test';

Test Setup

javascript
// Global setup
test.beforeAll(async () => {
  // Setup database, start server, etc.
});
 
// Per-test setup
test.beforeEach(async ({ page }) => {
  await page.goto('http://localhost:3000');
});
 
// Per-test cleanup
test.afterEach(async ({ page }) => {
  // Clear cookies, localStorage
  await page.context().clearCookies();
});
 
// Global cleanup
test.afterAll(async () => {
  // Cleanup database, stop server, etc.
});

Assertions

javascript
// Page-level
await expect(page).toHaveURL('/dashboard');
await expect(page).toHaveTitle('Dashboard');
 
// Element-level
await expect(page.locator('h1')).toHaveText('Welcome');
await expect(page.locator('.alert')).toBeVisible();
await expect(page.locator('.counter')).toHaveCount(5);
 
// Custom matchers
await expect(page.locator('.price')).toHaveText(/\$\d+\.\d{2}/);

Note

Playwright punya auto-wait built-in — tidak perlu page.waitForTimeout() atau manual sleeps. Gunakan assertions sebagai waiting mechanism.

Praktik: Complete Test

typescript
import { test, expect } from '@playwright/test';
 
test.describe('Shopping Cart', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('http://localhost:3000/products');
  });
 
  test('add item to cart', async ({ page }) => {
    // Find and click "Add to Cart"
    await page.getByRole('button', { name: 'Add to Cart' }).first().click();
 
    // Go to cart
    await page.getByRole('link', { name: 'Cart' }).click();
 
    // Assert item in cart
    await expect(page.locator('.cart-item')).toHaveCount(1);
    await expect(page.locator('.cart-total')).toContainText('$');
  });
 
  test('remove item from cart', async ({ page }) => {
    // Add item first
    await page.getByRole('button', { name: 'Add to Cart' }).first().click();
    await page.getByRole('link', { name: 'Cart' }).click();
 
    // Remove item
    await page.getByRole('button', { name: 'Remove' }).click();
 
    // Assert cart empty
    await expect(page.locator('.cart-empty')).toBeVisible();
  });
});

Penutup

  • Navigation: page.goto(), waitUntil, reload, back/forward.
  • Interaction: fill, click, hover, keyboard, file upload.
  • Fixtures: built-in (page, browser) dan custom fixtures.
  • Assertions: page-level, element-level, custom matchers.

Di episode 6 selanjutnya kita akan membahas Cypress & alternatives — kapan pakai Cypress vs Playwright, dan perbandingan fitur. Sampai jumpa di episode 6!