Installation
Create or initialize a Playwright project and install browsers.
npm init playwright@latest npm install npx playwright install npx playwright test
A practical quick reference for day-to-day Playwright work: browser setup, selectors, assertions, waits, debugging, network checks, device emulation, and common interview-ready patterns.
Daily automation work, interviews, revision, mentoring, and code reviews.
Readable examples that cover the commands students actually use in real Playwright projects.
Pair this page with the Playwright curriculum, programs tab, and hands-on projects in the app.
Prefer role-based locators, auto-waiting, reusable contexts, and clear assertions by default.
Create or initialize a Playwright project and install browsers.
npm init playwright@latest npm install npx playwright install npx playwright test
Use explicit browser, context, and page setup when you need direct control.
const { chromium } = require('playwright');
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
await browser.close();
Wait for a stable URL or a specific load state when the page changes after an action.
await page.goto('https://example.com');
await page.waitForURL('**/dashboard');
await page.waitForLoadState('networkidle');
const title = await page.title();
console.log(title);
Prefer resilient user-facing locators first. CSS/XPath only when necessary.
await page.getByRole('button', { name: 'Login' }).click();
await page.getByLabel('Email').fill('[email protected]');
await page.getByPlaceholder('Search').fill('Playwright');
await page.getByText('Welcome back').isVisible();
const row = page.locator('.table-row');
const legacy = page.locator('//button[text()="Save"]');
Fill, click, type, hover, drag, and extract content from the page.
await page.locator('#username').fill('promode');
await page.locator('#password').fill('secret');
await page.getByRole('button', { name: 'Sign in' }).click();
await page.locator('[data-test="menu"]').hover();
const text = await page.locator('.result').textContent();
Use `expect` with locators, URLs, and text for stable checks.
await expect(page).toHaveURL(/dashboard/);
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
await expect(page.locator('.toast')).toContainText('Saved successfully');
await expect(page.locator('.price')).toHaveText('$99');
Lean on Playwright auto-waiting, then add explicit waits for events or special cases.
page.setDefaultTimeout(15000);
page.setDefaultNavigationTimeout(30000);
await page.waitForSelector('.status', { state: 'visible' });
await page.waitForResponse('**/api/orders');
await page.waitForFunction(() => window.innerWidth > 1024);
Contexts give you isolated sessions for auth, cookies, permissions, and storage.
const context = await browser.newContext();
await context.addCookies([{
name: 'session',
value: 'abc123',
domain: '.example.com',
path: '/',
}]);
await context.storageState({ path: 'state.json' });
Capture full pages, elements, and record traces when debugging failures.
await page.screenshot({
path: 'artifacts/home.png',
fullPage: true,
});
await page.locator('.summary-card').screenshot({
path: 'artifacts/card.png',
});
await context.tracing.start({ screenshots: true, snapshots: true });
Pause locally, inspect content, and print values when a test behaves differently than expected.
await page.pause();
console.log(await page.content());
console.log(await page.locator('article').allTextContents());
npx playwright test --debug
npx playwright show-trace trace.zip
Let Playwright split tests across workers, browsers, and projects.
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
fullyParallel: true,
workers: 4,
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
],
});
These are the default recommendation for readable and reliable tests.
page.getByRole('button', { name: 'Submit' });
page.getByLabel('Password');
page.getByPlaceholder('Search products');
page.getByText('Order placed');
page.getByTestId('cart-count');
page.getByAltText('Profile image');
page.getByTitle('Open menu');
Handle browser dialogs and popup windows using explicit event waits.
page.on('dialog', async (dialog) => {
await dialog.accept();
});
const [popup] = await Promise.all([
context.waitForEvent('page'),
page.getByText('Open in new tab').click(),
]);
await popup.waitForLoadState();
Use frame locators for iframes and normal locators after entering a shadow root host.
const paymentFrame = page.frameLocator('#payment-frame');
await paymentFrame.getByLabel('Card number').fill('4111111111111111');
const host = page.locator('user-card');
await host.locator('button').click();
Test responsive layouts with preset devices or a custom viewport.
import { devices } from '@playwright/test';
const context = await browser.newContext({
...devices['iPhone 13'],
});
await page.setViewportSize({ width: 1280, height: 720 });
Observe requests, intercept calls, and control API responses during tests.
page.on('request', request => {
console.log(request.method(), request.url());
});
await page.route('**/api/orders', async (route) => {
await route.fulfill({
status: 200,
body: JSON.stringify({ success: true }),
});
});