Browser start and close
Start real browsers like Chromium, Chrome, Edge, Firefox, or WebKit, then close them to free resources.
const { chromium } = require('playwright');
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
await browser.close();Context management
Create an isolated context for clean cookies and storage, then close it when done.
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
await context.close();Page / tab management
Open a tab, wait for popups, list tabs, switch focus, close tabs, and confirm a tab is closed.
const page = await context.newPage();
const [popup] = await Promise.all([
page.waitForEvent('popup'),
page.click('a[target="_blank"]'),
]);
const pages = context.pages();
await page.close();Page information
Get current URL and page title information.
const url = page.url();
const title = await page.title();Page assertions
Assert page URL and title with various matching options.
await expect(page).toHaveURL('https://example.com');
await expect(page).toHaveURL(/.*checkout/);
await expect(page).toHaveTitle('My Page');
await expect(page).toHaveTitle(/My.*/);Element selection
Select elements using various locator strategies for reliable automation.
page.getByRole('button', { name: 'Submit' });
page.getByText('Welcome');
page.getByLabel('Email');
page.getByPlaceholder('Enter email');
page.getByTestId('submit-btn');
page.locator('.my-class');
page.locator('#my-id');Waiting for element states
Wait for elements to be in specific states before interacting with them.
await page.locator('.spinner').waitFor({ state: 'visible' });
await page.locator('.spinner').waitFor({ state: 'hidden' });
await page.locator('.item').waitFor({ state: 'attached' });
await page.locator('.slow').waitFor({ timeout: 10000 });Element state getters
Get various properties and states of elements for validation and debugging.
const visible = await page.locator('.el').isVisible();
const enabled = await page.locator('.el').isEnabled();
const checked = await page.locator('.el').isChecked();
const text = await page.locator('.el').textContent();
const value = await page.locator('input').inputValue();
const attr = await page.locator('.el').getAttribute('href');Element assertions
Assert element states, content, and properties for comprehensive test validation.
await expect(page.locator('.el')).toBeVisible();
await expect(page.locator('.el')).toBeHidden();
await expect(page.locator('.el')).toBeEnabled();
await expect(page.locator('.el')).toBeDisabled();
await expect(page.locator('.el')).toHaveText('Hello');
await expect(page.locator('.el')).toContainText('Hel');
await expect(page.locator('.el')).toHaveAttribute('href', '/home');
await expect(page.locator('.el')).toHaveClass(/active/);
await expect(page.locator('.el')).toHaveCount(3);Click / hover / drag and drop
Perform mouse interactions including clicks, double-clicks, right-clicks, hover, and drag-and-drop.
await page.locator('#btn').click();
await page.locator('#btn').dblclick();
await page.locator('#btn').click({ button: 'right' });
await page.locator('#menu').hover();
await page.dragAndDrop('#source', '#target');Input
Type text, clear fields, and fill form inputs.
await page.locator('#name').fill('John');
await page.locator('#name').clear();
await page.locator('#name').pressSequentially('Hello', { delay: 100 });Form input
Work with select dropdowns, checkboxes, and radio buttons.
await page.locator('select#color').selectOption('blue');
await page.locator('select#color').selectOption({ label: 'Blue' });
await page.locator('#agree').check();
await page.locator('#agree').uncheck();
await page.locator('#option-a').check();Keyboard
Simulate keyboard input, shortcuts, and key combinations.
await page.keyboard.press('Enter');
await page.keyboard.press('Control+A');
await page.keyboard.type('Hello World');
await page.keyboard.down('Shift');
await page.keyboard.up('Shift');File upload and download
Handle file uploads via input elements and intercept file downloads.
await page.locator('input[type="file"]').setInputFiles('file.pdf');
await page.locator('input[type="file"]').setInputFiles([]);
const [download] = await Promise.all([
page.waitForEvent('download'),
page.click('#download-btn'),
]);
const path = await download.path();Evaluate JavaScript
Execute JavaScript in the browser context and retrieve results.
const result = await page.evaluate(() => document.title);
const el = await page.evaluate(() => {
return document.querySelector('.el').textContent;
});
await page.evaluate((name) => {
localStorage.setItem('user', name);
}, 'John');Dialog / alert / prompt / confirm
Handle browser dialogs including alerts, confirms, and prompts.
page.on('dialog', async dialog => {
console.log(dialog.message());
await dialog.accept(); // or dialog.dismiss()
});
// For prompt:
page.on('dialog', dialog => dialog.accept('my answer'));Viewport / window size
Set viewport dimensions and emulate device screen sizes.
const context = await browser.newContext({
viewport: { width: 1280, height: 720 }
});
await page.setViewportSize({ width: 375, height: 812 });Screenshots
Capture full page or element screenshots.
await page.screenshot({ path: 'page.png' });
await page.screenshot({ path: 'full.png', fullPage: true });
await page.locator('.card').screenshot({ path: 'card.png' });Test runner assertions
Use Playwright Test's built-in expect assertions for robust test validation.
const { test, expect } = require('@playwright/test');
test('homepage has title', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example/);
await expect(page.locator('h1')).toBeVisible();
});Fixtures, describe, config
Organize tests with fixtures, describe blocks, and before/after hooks.
const { test } = require('@playwright/test');
test.describe('Login flow', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/login');
});
test.afterEach(async ({ page }) => {
await page.close();
});
test('valid login', async ({ page }) => {
// ...
});
});Network interception
Intercept, modify, and mock network requests and responses.
await page.route('**/api/users', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([{ name: 'John' }]),
});
});
await page.route('**/*.png', route => route.abort());Local storage and session
Read and write localStorage and sessionStorage values.
await page.evaluate(() => {
localStorage.setItem('key', 'value');
});
const val = await page.evaluate(() => {
return localStorage.getItem('key');
});Frame / iframe
Interact with content inside iframes and nested frames.
const frame = page.frameLocator('#my-iframe');
await frame.locator('#btn').click();
await frame.locator('input').fill('Hello');Multiple contexts and cookies
Run multiple browser contexts simultaneously for multi-user testing.
const userCtx = await browser.newContext();
const adminCtx = await browser.newContext();
const userPage = await userCtx.newPage();
const adminPage = await adminCtx.newPage();API testing via UI
Make direct API requests using the Playwright request context.
const response = await page.request.get('/api/users');
expect(response.ok()).toBeTruthy();
const body = await response.json();
await page.request.post('/api/login', {
data: { email: '[email protected]', password: '123' }
});Auto-wait and actionability
Understand Playwright's built-in auto-waiting and how to customize timeouts.
// Playwright auto-waits for elements by default
await page.locator('#btn').click(); // waits until actionable
// Custom timeout per action
await page.locator('#btn').click({ timeout: 5000 });
// Global timeout in config
// playwright.config.ts: timeout: 30000Tracing, video, screenshots in config
Enable trace recording, video capture, and automatic screenshots on failure.
// playwright.config.ts
module.exports = {
use: {
trace: 'on-first-retry',
video: 'retain-on-failure',
screenshot: 'only-on-failure',
},
};Codegen and recording
Use Playwright's code generator to record user interactions as test scripts.
# Run from terminal
npx playwright codegen https://example.com
# With specific viewport
npx playwright codegen --viewport-size=1280,720 https://example.com
# With device emulation
npx playwright codegen --device="iPhone 13" https://example.comBrowser storage state
Save and reuse authentication state across tests to skip login flows.
// Save storage state
await context.storageState({ path: 'auth.json' });
// Reuse in new context
const context = await browser.newContext({
storageState: 'auth.json'
});Locator chaining and filtering
Chain and filter locators for precise element targeting.
page.locator('.list').locator('.item').first();
page.locator('.item').filter({ hasText: 'Buy' });
page.locator('.item').filter({ has: page.locator('.price') });
page.locator('.item').nth(2);Accessibility
Run accessibility audits and check ARIA attributes.
const snapshot = await page.accessibility.snapshot();
console.log(snapshot);
await expect(page.locator('#btn')).toHaveAttribute('aria-label', 'Close');
await expect(page.locator('#nav')).toHaveRole('navigation');Reporters
Configure test reporters for HTML, JSON, and custom output formats.
// playwright.config.ts
module.exports = {
reporter: [
['html', { open: 'never' }],
['json', { outputFile: 'results.json' }],
['list'],
['@testdino/playwright', { apiKey: process.env.TESTDINO_KEY }],
],
};Parallel and serial
Control test execution order - run tests in parallel or sequentially.
// Parallel (default)
test.describe.parallel('parallel suite', () => {
test('test A', async ({ page }) => {});
test('test B', async ({ page }) => {});
});
// Serial - tests depend on each other
test.describe.serial('serial suite', () => {
test('step 1', async ({ page }) => {});
test('step 2', async ({ page }) => {});
});Retry and flaky
Configure test retries to handle flaky tests automatically.
// playwright.config.ts
module.exports = {
retries: 2, // retry failed tests up to 2 times
retries: process.env.CI ? 2 : 0, // only retry in CI
};
// Per-test retry
test('flaky test', { retries: 3 }, async ({ page }) => {});Global setup and teardown
Run setup and teardown scripts before/after all tests in the project.
// playwright.config.ts
module.exports = {
globalSetup: require.resolve('./global-setup'),
globalTeardown: require.resolve('./global-teardown'),
};
// global-setup.ts
async function globalSetup() {
// seed database, start services, etc.
}
module.exports = globalSetup;