Q10 of 42 · Playwright
How do you assert text content in Playwright?
Short answer
Short answer: Use `expect(locator).toHaveText(...)` for exact / regex match, `toContainText(...)` for substring, `toHaveValue(...)` for inputs, `toHaveTitle(...)` for the page title. All assertions auto-retry until the timeout.
Detail
Playwright's expect (from @playwright/test) has built-in matchers that auto-retry. They differ from Jest's expect — these are Locator-aware.
Common matchers:
// Exact text
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Welcome');
// Regex
await expect(page.getByTestId('total')).toHaveText(/£\d+\.\d{2}/);
// Substring
await expect(page.getByTestId('cart-banner')).toContainText('items in your cart');
// Array match (multiple elements)
await expect(page.getByRole('listitem')).toHaveText(['Apples', 'Bread', 'Cheese']);
// Input value
await expect(page.getByLabel('Email')).toHaveValue('alice@x.com');
// Page title / URL
await expect(page).toHaveTitle('qa.codes');
await expect(page).toHaveURL(/dashboard/);
The retry behaviour means you don't write waitForText boilerplate — expect(...).toHaveText(...) waits up to the test timeout for the assertion to pass.
toHaveText vs toContainText: exact-match vs substring. Exact is stricter and catches unexpected text additions; substring is forgiving and survives copy tweaks. Default to exact unless the surrounding text is genuinely unstable.
Negative assertions: await expect(locator).not.toBeVisible() etc. — same auto-retry but inverted.
Custom timeout per assertion:
await expect(locator).toHaveText('Loaded', { timeout: 10_000 });
// EXAMPLE
assertions.spec.ts
import { test, expect } from '@playwright/test';
test('cart assertions', async ({ page }) => {
await page.goto('/cart');
// Page-level
await expect(page).toHaveTitle('Your cart — qa.codes');
await expect(page).toHaveURL(/\/cart/);
// Single element
await expect(page.getByTestId('total')).toHaveText('£42.50');
await expect(page.getByRole('heading')).toContainText('cart');
// Multiple elements at once
await expect(page.getByTestId('item-name')).toHaveText([
'Apples', 'Bread', 'Cheese',
]);
// Negative
await expect(page.getByTestId('empty-state')).not.toBeVisible();
// Custom timeout for slow updates
await expect(page.getByTestId('total')).toHaveText('£0.00', { timeout: 10_000 });
});