DEV Community

Cover image for Playwright E2E Tests: Actions, Assertions, Hooks
Pratham Rathod
Pratham Rathod

Posted on

Playwright E2E Tests: Actions, Assertions, Hooks

Playwright E2E Tests: Actions, Assertions, Hooks

Learn Playwright E2E testing. Write first test, actions, async assertions, test isolation, leverage hooks for reliable web automation!

This guide provides a practical overview of writing tests with Playwright, focusing on core concepts, actions, assertions, and test organization.

Introduction

Playwright tests are designed for simplicity and reliability. They perform actions on web pages and assert expected states. Playwright automatically handles waiting for elements to become actionable and for assertions to eventually pass, eliminating the need for manual waits and reducing test flakiness.

Getting Started: Your First Test

Playwright tests are typically written in TypeScript or JavaScript. A basic test involves navigating to a URL and performing assertions.

// tests/example.spec.ts
import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  // Expect a title "to contain" a substring.
  await expect(page).toHaveTitle(/Playwright/);
});

test('get started link', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  // Click the "Get started" link using its role and name.
  await page.getByRole('link', { name: 'Get started' }).click();

  // Expects the page to have a heading with the name "Installation".
  await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
Enter fullscreen mode Exit fullscreen mode

Note: When using JavaScript in VS Code, add // @ts-check at the start of each test file to enable automatic type checking.

Performing Actions

Most tests begin with navigation and then interact with page elements.

Navigation

Use page.goto() to navigate to a URL. Playwright waits for the page to reach the load state before proceeding.

await page.goto('https://playwright.dev/');
Enter fullscreen mode Exit fullscreen mode

Interactions

Interacting with elements starts by locating them using Playwright's Locators API. Locators provide a robust way to find elements on the page. Playwright automatically waits for elements to become actionable (e.g., visible, enabled) before performing an action, so you don't need to add explicit waits.

// Create a locator for the "Get started" link.
const getStartedLink = page.getByRole('link', { name: 'Get started' });

// Click the located element.
await getStartedLink.click();
Enter fullscreen mode Exit fullscreen mode

Often, this can be condensed into a single line:

await page.getByRole('link', { name: 'Get started' }).click();
Enter fullscreen mode Exit fullscreen mode

Basic Actions

Here are some common Playwright actions:

Action Description
locator.check() Check a checkbox
locator.click() Click an element
locator.uncheck() Uncheck a checkbox
locator.hover() Hover mouse over an element
locator.fill() Fill a form field with text
locator.focus() Focus an element
locator.press() Press a single key
locator.setInputFiles() Pick files for upload
locator.selectOption() Select an option in a dropdown

Using Assertions

Playwright includes test assertions via the expect function. Call expect(value) and use a matcher to define your expectation.

Playwright offers async matchers that wait for a condition to be met, making tests non-flaky.

// This assertion waits until the page title contains "Playwright".
await expect(page).toHaveTitle(/Playwright/);
Enter fullscreen mode Exit fullscreen mode

Popular Async Assertions

Assertion Description
expect(locator).toBeChecked() Checkbox is checked
expect(locator).toBeEnabled() Control is enabled
expect(locator).toBeVisible() Element is visible
expect(locator).toContainText() Element contains specific text
expect(locator).toHaveAttribute() Element has a specific attribute
expect(locator).toHaveCount() List of elements has a given length
expect(locator).toHaveText() Element matches text (exact or regex)
expect(locator).toHaveValue() Input element has a specific value
expect(page).toHaveTitle() Page has a specific title (exact or regex)
expect(page).toHaveURL() Page has a specific URL (exact or regex)

Playwright also includes generic matchers like toEqual, toContain, and toBeTruthy for immediate synchronous checks. These do not require await.

// Synchronous assertion.
expect(success).toBeTruthy();
Enter fullscreen mode Exit fullscreen mode

Test Isolation

Playwright Test ensures strong isolation between tests. Each test receives a fresh environment, thanks to the page fixture which belongs to an isolated BrowserContext. A BrowserContext is equivalent to a brand new browser profile, preventing test interference.

// tests/example.spec.ts
import { test } from '@playwright/test';

test('example test', async ({ page }) => {
  // "page" here is isolated for this specific test.
});

test('another test', async ({ page }) => {
  // "page" in this second test is completely isolated from the first test.
});
Enter fullscreen mode Exit fullscreen mode

Using Test Hooks

Playwright provides various test hooks to organize and manage test execution.

  • test.describe(name, callback): Groups related tests.
  • test.beforeEach(callback): Runs before each test in the current describe block.
  • test.afterEach(callback): Runs after each test in the current describe block.
  • test.beforeAll(callback): Runs once before all tests in the current describe block.
  • test.afterAll(callback): Runs once after all tests in the current describe block.
// tests/example.spec.ts
import { test, expect } from '@playwright/test';

test.describe('navigation', () => {
  // Navigate to the starting URL before each test in this group.
  test.beforeEach(async ({ page }) => {
    await page.goto('https://playwright.dev/');
  });

  test('main navigation', async ({ page }) => {
    // This test starts at 'https://playwright.dev/' due to beforeEach.
    await expect(page).toHaveURL('https://playwright.dev/');
  });

  test('navigate to docs', async ({ page }) => {
    // This test also starts at 'https://playwright.dev/'.
    await page.getByRole('link', { name: 'Docs' }).click();
    await expect(page).toHaveURL(/.*docs/);
  });
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)