Built for developers, by XinhND

v2.1.0

Ready

Playwright Cheat Sheet

Complete reference guide for Playwright with interactive examples and live playground links

Getting Started

Installation

Install Playwright using your preferred package manager

Playwright
npm init playwright@latest
# or
yarn create playwright
# or
pnpm create playwright

Basic Test Structure

Basic test structure with navigation and assertions

Playwright
import { test, expect } from '@playwright/test';

test('basic test example', async ({ page }) => {
  // Navigate to a website
  await page.goto('https://example.com');
  
  // Assert page title
  await expect(page).toHaveTitle(/Example Domain/);
});

Common Test Patterns

Page Navigation & Assertions

Common patterns for page navigation and assertions

Playwright
import { test, expect } from '@playwright/test';

test('page navigation and assertions', async ({ page }) => {
  // Navigate to the target website
  await page.goto('https://your-app.com');

  // Check page title using regex
  await expect(page).toHaveTitle(/Your App/);

  // Check exact page title
  await expect(page).toHaveTitle('Home | Your App');

  // Check if element is visible
  await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible();
});

Form Interactions

Handling form submissions and interactions

Playwright
import { test, expect } from '@playwright/test';

test('form submission', async ({ page }) => {
  await page.goto('https://your-app.com/login');

  // Fill in form fields
  await page.getByLabel('Email').fill('user@example.com');
  await page.getByLabel('Password').fill('password123');

  // Click submit button
  await page.getByRole('button', { name: 'Sign in' }).click();

  // Assert successful login
  await expect(page.getByText('Welcome back')).toBeVisible();
});

Selectors & Locators

Common Selectors

Different ways to select elements in Playwright

Playwright
// By role (recommended)
// <button>Submit</button>
await page.getByRole('button', { name: 'Submit' }).click();

// By text content
// <span>Click me</span>
await page.getByText('Click me').click();

// By label
// <label for="username">Username</label>
// <input id="username" type="text">
await page.getByLabel('Username').fill('john');

// By placeholder
// <input type="email" placeholder="Enter email">
await page.getByPlaceholder('Enter email').fill('test@example.com');

// By test ID
// <button data-testid="submit-button">Submit</button>
await page.getByTestId('submit-button').click();

CSS & XPath Selectors

Using CSS and XPath selectors

Playwright
// CSS selector
// <button class="submit-button">Submit</button>
await page.locator('.submit-button').click();

// XPath
// <button>Submit Form</button>
await page.locator('//button[contains(text(), "Submit")]').click();

// Multiple selectors
// <button>Submit Form</button>
await page.locator('button:has-text("Submit")').click();

// Complex CSS selectors
// <div class="form">
//   <input type="text" class="username">
//   <button class="submit">Submit</button>
// </div>
await page.locator('.form .username').fill('john');
await page.locator('.form .submit').click();

// Attribute selectors
// <input type="text" required>
await page.locator('input[required]').fill('required field');

// Nth element
// <ul>
//   <li>First item</li>
//   <li>Second item</li>
//   <li>Third item</li>
// </ul>
await page.locator('li').nth(1).click(); // Clicks "Second item"

Assertions & Expectations

Common Assertions

Common assertion patterns in Playwright

Playwright
// Check element visibility
await expect(page.getByText('Success')).toBeVisible();

// Check element state
await expect(page.getByRole('button')).toBeEnabled();

// Check text content
await expect(page.getByText('Welcome')).toHaveText('Welcome to our app');

// Check element count
await expect(page.getByRole('listitem')).toHaveCount(5);

// Check element attributes
await expect(page.getByRole('img')).toHaveAttribute('alt', 'Logo');

Best Practices

Test Organization

Best practices for organizing tests

Playwright
// Group related tests
test.describe('User Authentication', () => {
  test('successful login', async ({ page }) => {
    // Test code
  });

  test('failed login', async ({ page }) => {
    // Test code
  });
});

// Use test fixtures for common setup
test.beforeEach(async ({ page }) => {
  await page.goto('https://your-app.com');
});

Handling Async Operations

Best practices for handling asynchronous operations

Playwright
// Wait for network requests
await page.waitForLoadState('networkidle');

// Wait for specific element
await page.waitForSelector('.loading-spinner', { state: 'hidden' });

// Wait for navigation
await Promise.all([
  page.waitForNavigation(),
  page.click('a[href="/dashboard"]')
]);

Playwright Commands

Basic Commands

Essential Playwright CLI commands

Playwright
# Run all tests
npx playwright test

# Run tests in UI mode
npx playwright test --ui

# Run tests in specific browser
npx playwright test --project=chromium

# Run tests in debug mode
npx playwright test --debug

# Run specific test file
npx playwright test example.spec.ts

# Run tests matching a pattern
npx playwright test -g "test name pattern"

# Show test report
npx playwright show-report

# Generate code from user actions
npx playwright codegen example.com

# Install browsers
npx playwright install

# Install specific browser
npx playwright install chromium

Test Configuration

Common configuration options in playwright.config.ts

Playwright
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  // Run tests in files matching pattern
  testMatch: '**/*.spec.ts',
  
  // Run tests in parallel
  workers: 3,
  
  // Retry failed tests
  retries: 2,
  
  // Timeout for each test
  timeout: 30000,
  
  // Reporter configuration
  reporter: [
    ['html'],
    ['list']
  ],
  
  // Browser configuration
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

Screenshots & Visual Testing

Taking Screenshots

Different ways to capture screenshots in Playwright

Playwright
// Take full page screenshot
await page.screenshot({ path: 'screenshot.png', fullPage: true });

// Take element screenshot
await page.locator('.header').screenshot({ path: 'header.png' });

// Take screenshot on failure
test('visual test', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('page.png');
});

// Compare screenshots
await expect(page.locator('.component')).toHaveScreenshot('component.png', {
  maxDiffPixels: 100, // Allow some pixel differences
  threshold: 0.2,     // 20% threshold for color differences
});

Visual Testing Best Practices

Best practices for visual testing with Playwright

Playwright
// Ignore dynamic content
await expect(page).toHaveScreenshot('page.png', {
  mask: [
    page.locator('.timestamp'),
    page.locator('.dynamic-content')
  ]
});

// Handle animations
await page.evaluate(() => {
  // Disable CSS animations
  document.body.style.setProperty('animation', 'none');
  document.body.style.setProperty('transition', 'none');
});

// Compare specific regions
await expect(page.locator('.main-content')).toHaveScreenshot('content.png', {
  clip: { x: 0, y: 0, width: 800, height: 600 }
});

Network & API Testing

Network Interception

Intercepting and mocking network requests

Playwright
// Intercept API requests
await page.route('**/api/users', async route => {
  // Mock response
  await route.fulfill({
    status: 200,
    body: JSON.stringify({ users: [] })
  });
});

// Wait for network requests
await page.waitForResponse(response => 
  response.url().includes('/api/data')
);

// Mock API response
await page.route('**/api/data', async route => {
  const json = { data: 'mocked data' };
  await route.fulfill({ json });
});

API Testing

Testing API endpoints with Playwright

Playwright
// Test API endpoint
test('API test', async ({ request }) => {
  // GET request
  const response = await request.get('/api/users');
  expect(response.ok()).toBeTruthy();
  
  // POST request
  const postResponse = await request.post('/api/users', {
    data: {
      name: 'John',
      email: 'john@example.com'
    }
  });
  expect(postResponse.status()).toBe(201);
  
  // PUT request
  const putResponse = await request.put('/api/users/1', {
    data: {
      name: 'John Updated'
    }
  });
  expect(putResponse.ok()).toBeTruthy();
});

Debugging & Troubleshooting

Debugging Tools

Tools and techniques for debugging tests

Playwright
// Pause execution
await page.pause();

// Slow down operations
await page.setDefaultTimeout(5000);
await page.setDefaultNavigationTimeout(10000);

// Debug selectors
const element = page.locator('.my-element');
console.log(await element.count());
console.log(await element.isVisible());

// Take screenshot on failure
test.afterEach(async ({ page }, testInfo) => {
  if (testInfo.status !== testInfo.expectedStatus) {
    await page.screenshot({
      path: `failure-${testInfo.title}.png`,
      fullPage: true
    });
  }
});

Tracing & Logging

Using Playwright tracing and logging features

Playwright
// Start tracing
await context.tracing.start({ screenshots: true, snapshots: true });

// Your test code here
await page.goto('https://example.com');
await page.click('.button');

// Stop tracing and save
await context.tracing.stop({ path: 'trace.zip' });

// View trace
// npx playwright show-trace trace.zip

// Enable debug logging
process.env.DEBUG = 'pw:api';
// or
const browser = await chromium.launch({ logger: {
  isEnabled: (name, severity) => true,
  log: (name, severity, message, args) => console.log(`${name} ${message}`)
}});

Playwright - Interactive Developer Reference

Hover over code blocks to copy or run in live playground