Playwright Cheat Sheet
Quick reference for Playwright browser testing. Selectors, actions, assertions, page navigation, API testing, fixtures, and debugging — all in one page.
Setup & Configuration
Test Structure
Locators (Selectors)
Actions
Assertions (expect)
Waiting & Timing
Page & Navigation
Network & API Testing
Fixtures & Storage
Debugging
Setup & Configuration
| npm init playwright@latest | Initialize Playwright project |
| npx playwright test | Run all tests |
| npx playwright test --ui | Run with UI mode |
| npx playwright test --headed | Run with visible browser |
| npx playwright test --project=chromium | Run specific browser |
| npx playwright test login.spec.ts | Run specific test file |
| npx playwright test -g "login" | Run tests matching grep pattern |
| npx playwright show-report | Open HTML test report |
| npx playwright codegen example.com | Record tests interactively |
Test Structure
| import { test, expect } from "@playwright/test" | Import test & expect |
| test("description", async ({ page }) => { ... }) | Define a test |
| test.describe("group", () => { ... }) | Group tests |
| test.beforeEach(async ({ page }) => { ... }) | Before each hook |
| test.afterEach(async ({ page }) => { ... }) | After each hook |
| test.beforeAll(async () => { ... }) | Before all hook |
| test.skip("reason") | Skip a test |
| test.only("...", async () => { ... }) | Run only this test |
| test.fixme("...", async () => { ... }) | Mark as known issue |
Locators (Selectors)
| page.getByRole("button", { name: "Submit" }) | By ARIA role (preferred) |
| page.getByText("Welcome") | By visible text |
| page.getByLabel("Email") | By label text (forms) |
| page.getByPlaceholder("Enter email") | By placeholder text |
| page.getByTestId("submit-btn") | By data-testid attribute |
| page.getByTitle("Close") | By title attribute |
| page.getByAltText("Logo") | By alt text (images) |
| page.locator("css=div.card") | CSS selector |
| page.locator("xpath=//div[@class]") | XPath selector |
| locator.first() | First matching element |
| locator.nth(2) | Nth matching element (0-indexed) |
| locator.filter({ hasText: "hello" }) | Filter by text content |
Actions
| await page.goto("https://example.com") | Navigate to URL |
| await locator.click() | Click element |
| await locator.dblclick() | Double click |
| await locator.fill("text") | Fill input field (clears first) |
| await locator.type("text") | Type character by character |
| await locator.press("Enter") | Press keyboard key |
| await locator.check() | Check checkbox |
| await locator.uncheck() | Uncheck checkbox |
| await locator.selectOption("value") | Select dropdown option |
| await locator.hover() | Hover over element |
| await locator.focus() | Focus element |
| await locator.setInputFiles("file.pdf") | Upload file |
| await locator.dragTo(target) | Drag and drop |
Assertions (expect)
| await expect(locator).toBeVisible() | Element is visible |
| await expect(locator).toBeHidden() | Element is hidden |
| await expect(locator).toBeEnabled() | Element is enabled |
| await expect(locator).toBeDisabled() | Element is disabled |
| await expect(locator).toHaveText("Hello") | Has exact text |
| await expect(locator).toContainText("ello") | Contains text |
| await expect(locator).toHaveValue("input") | Input has value |
| await expect(locator).toHaveAttribute("href", "/about") | Has attribute |
| await expect(locator).toHaveClass(/active/) | Has CSS class |
| await expect(locator).toHaveCount(3) | Number of matching elements |
| await expect(page).toHaveURL(/dashboard/) | Page URL matches |
| await expect(page).toHaveTitle("Home") | Page title matches |
Waiting & Timing
| await page.waitForURL("**/dashboard") | Wait for navigation |
| await page.waitForSelector(".loaded") | Wait for selector |
| await page.waitForResponse("**/api/users") | Wait for network response |
| await page.waitForLoadState("networkidle") | Wait for network idle |
| await page.waitForTimeout(1000) | Hard wait (avoid in tests) |
| await locator.waitFor({ state: "visible" }) | Wait for element state |
| test.setTimeout(60000) | Set test timeout |
Network & API Testing
| await page.route("**/api/*", route => route.fulfill({ body: "{}" })) | Mock API response |
| await page.route("**/api/*", route => route.abort()) | Block request |
| const response = await request.get("/api/users") | Direct API request |
| const json = await response.json() | Parse JSON response |
| expect(response.ok()).toBeTruthy() | Assert response OK |
| page.on("request", req => console.log(req.url())) | Log all requests |
Fixtures & Storage
| test.use({ storageState: "auth.json" }) | Reuse authentication state |
| await page.context().storageState({ path: "auth.json" }) | Save storage state |
| const context = await browser.newContext({ storageState: "auth.json" }) | New context with state |
| test.use({ viewport: { width: 375, height: 812 } }) | Set viewport size |
| test.use({ locale: "fr-FR", timezoneId: "Europe/Paris" }) | Set locale & timezone |
Debugging
| npx playwright test --debug | Run with debugger |
| await page.pause() | Pause execution (opens inspector) |
| PWDEBUG=1 npx playwright test | Debug with env variable |
| npx playwright test --trace on | Record trace for debugging |
| npx playwright show-trace trace.zip | View recorded trace |
| test.use({ trace: "on-first-retry" }) | Trace on failure |
Step-by-Step Guide
Read Guide →