Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Microsoft Playwright Expect API

From Leeroopedia
Knowledge Sources
Domains Testing, Browser_Automation
Last Updated 2026-02-11 00:00 GMT

Overview

Concrete tool for verifying application state through auto-retrying, web-first assertions provided by the Playwright library.

Description

The expect function in Playwright Test is the assertion entry point that combines the familiar jest-expect API with Playwright-specific web-first matchers. When called with a Locator argument, it returns a proxy object that provides over 30 auto-retrying assertion methods. These methods repeatedly poll the DOM until the expected condition is met or a timeout expires.

The implementation at packages/playwright/src/matchers/expect.ts (lines 83-155) creates a Proxy around the standard expectLibrary (jest-expect) and wraps each matcher call with ExpectMetaInfo for tracking. The actual matchers are defined in packages/playwright/src/matchers/matchers.ts (lines 160-397) and use the internal pollAgainstDeadline utility to implement retry logic with a default timeout of 5000ms.

Playwright's expect supports both Locator-specific assertions (auto-retrying) and generic value assertions (non-retrying, identical to jest-expect). It also provides expect.soft() for soft assertions that do not stop test execution on failure, and expect.poll() for retrying arbitrary conditions.

Usage

Use expect after every action in a test to verify the result. Use Locator-based assertions (e.g., expect(locator).toBeVisible()) for DOM state verification, as these auto-retry. Use generic assertions (e.g., expect(value).toBe(5)) for non-DOM values. Use expect.soft() when you want to continue the test after a failure. Use expect(locator).toHaveScreenshot() for visual regression testing.

Code Reference

Source Location

  • Repository: playwright
  • File (expect entry): packages/playwright/src/matchers/expect.ts (lines 83-155)
  • File (matchers): packages/playwright/src/matchers/matchers.ts (lines 160-397)

Signature

// Core expect function
function expect(value: Locator): LocatorAssertions;
function expect(value: Page): PageAssertions;
function expect(value: APIResponse): APIResponseAssertions;
function expect<T>(value: T): JestExpect<T>;

// Soft assertions (do not stop test on failure)
expect.soft(value: Locator): LocatorAssertions;

// Polling assertions (retry arbitrary conditions)
expect.poll(callback: () => Promise<T> | T, options?: { timeout?: number; intervals?: number[] }): JestExpect<T>;

// Locator assertion methods (auto-retrying)
expect(locator).toBeVisible(options?: { visible?: boolean; timeout?: number }): Promise<void>;
expect(locator).toHaveText(expected: string | RegExp | (string | RegExp)[], options?: { useInnerText?: boolean; ignoreCase?: boolean; timeout?: number }): Promise<void>;
expect(locator).toBeAttached(options?: { attached?: boolean; timeout?: number }): Promise<void>;
expect(locator).toBeChecked(options?: { checked?: boolean; timeout?: number }): Promise<void>;
expect(locator).toBeDisabled(options?: { timeout?: number }): Promise<void>;
expect(locator).toBeEnabled(options?: { enabled?: boolean; timeout?: number }): Promise<void>;
expect(locator).toBeFocused(options?: { timeout?: number }): Promise<void>;
expect(locator).toBeHidden(options?: { timeout?: number }): Promise<void>;
expect(locator).toContainText(expected: string | RegExp | (string | RegExp)[], options?: { useInnerText?: boolean; ignoreCase?: boolean; timeout?: number }): Promise<void>;
expect(locator).toHaveAttribute(name: string, value: string | RegExp, options?: { timeout?: number }): Promise<void>;
expect(locator).toHaveCount(count: number, options?: { timeout?: number }): Promise<void>;
expect(locator).toHaveCSS(name: string, value: string | RegExp, options?: { timeout?: number }): Promise<void>;
expect(locator).toHaveValue(value: string | RegExp, options?: { timeout?: number }): Promise<void>;
expect(locator).toHaveScreenshot(name?: string, options?: ScreenshotOptions): Promise<void>;
expect(locator).toMatchAriaSnapshot(expected: string, options?: { timeout?: number }): Promise<void>;
expect(locator).toPass(options?: { timeout?: number; intervals?: number[] }): Promise<void>;

// Page assertion methods
expect(page).toHaveTitle(titleOrRegExp: string | RegExp, options?: { timeout?: number }): Promise<void>;
expect(page).toHaveURL(urlOrRegExp: string | RegExp, options?: { timeout?: number }): Promise<void>;

Import

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

I/O Contract

Inputs

Name Type Required Description
value Page | APIResponse | any Yes The subject of the assertion. When a Locator is provided, auto-retrying web-first matchers become available. When other types are provided, standard jest-expect matchers are used.
toBeVisible options.visible boolean No When false, asserts the element is NOT visible. Default: true.
toBeVisible options.timeout number No Custom timeout in milliseconds. Default: 5000ms (configurable via expect.timeout in config).
toHaveText expected RegExp | (string | RegExp)[] Yes (for toHaveText) Expected text content. When an array is provided, each element is matched against corresponding Locator matches.
toHaveText options.useInnerText boolean No Use element.innerText instead of element.textContent. Default: false.
toHaveText options.ignoreCase boolean No Perform case-insensitive comparison. Default: false.
toHaveAttribute name string Yes (for toHaveAttribute) The attribute name to check.
toHaveAttribute value RegExp Yes (for toHaveAttribute) The expected attribute value.
toHaveCount count number Yes (for toHaveCount) The expected number of matching elements.
toHaveScreenshot name string No Name for the screenshot file. Auto-generated from test title if omitted.

Outputs

Name Type Description
(resolved) Promise<void> All Locator-based assertions return a Promise that resolves when the condition is met. The Promise rejects with a descriptive error (showing expected vs. actual) if the timeout expires.
Soft assertion failure collected error When using expect.soft(), failures are collected rather than thrown. They are reported at test completion.
Poll result JestExpect<T> When using expect.poll(), the callback's return value is evaluated against the chained matcher with retry logic.

Usage Examples

Basic Example

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

test('verify page elements', async ({ page }) => {
  await page.goto('https://example.com');

  // Auto-retrying assertion: waits for element to become visible
  await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible();

  // Verify text content
  await expect(page.getByRole('main')).toHaveText(/Example Domain/);

  // Verify element count
  await expect(page.getByRole('link')).toHaveCount(1);

  // Verify page title
  await expect(page).toHaveTitle('Example Domain');

  // Verify page URL
  await expect(page).toHaveURL('https://example.com/');
});

Negated and Soft Assertions Example

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

test('negated and soft assertions', async ({ page }) => {
  await page.goto('https://example.com/form');

  // Negated assertion: verify element is NOT visible
  await expect(page.getByRole('alert')).not.toBeVisible();

  // Soft assertion: continues test even if this fails
  await expect.soft(page.getByRole('heading')).toHaveText('Form Title');

  // Verify form control state
  await expect(page.getByRole('button', { name: 'Submit' })).toBeDisabled();
  await page.getByLabel('Name').fill('John');
  await expect(page.getByRole('button', { name: 'Submit' })).toBeEnabled();
});

Polling and Screenshot Assertions Example

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

test('advanced assertions', async ({ page }) => {
  await page.goto('https://example.com/dashboard');

  // Poll a non-Locator condition with retry
  await expect.poll(async () => {
    const response = await page.request.get('/api/status');
    return response.status();
  }, { timeout: 10000 }).toBe(200);

  // Visual regression: compare screenshot
  await expect(page.getByTestId('chart')).toHaveScreenshot('chart.png');

  // Verify CSS property
  await expect(page.getByRole('alert')).toHaveCSS('background-color', 'rgb(255, 0, 0)');

  // Verify attribute
  await expect(page.getByRole('link', { name: 'Docs' })).toHaveAttribute('href', /\/docs/);

  // Accessibility: match ARIA snapshot
  await expect(page.getByRole('navigation')).toMatchAriaSnapshot(`
    - navigation:
      - link "Home"
      - link "About"
      - link "Contact"
  `);
});

Related Pages

Implements Principle

Uses Heuristic

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment