Assertions are how your Playwright tests prove that the application behaves correctly. Unlike simple synchronous assertions, Playwrightβs expect API understands asynchronous UI changes and will wait for conditions to become true within a timeout. Using these assertions correctly helps you avoid flaky tests and makes failures more informative.
How Playwright Assertions Work
Playwright exposes an expect API that you use with locators, pages and other objects. Assertions such as toBeVisible, toHaveText and toHaveURL automatically retry until the expectation is met or the timeout expires.
// playwright-assertions-intro.spec.ts
import { test, expect } from '@playwright/test';
test('uses auto-waiting assertions', async ({ page }) => {
await page.goto('https://demo.myshop.com/dashboard');
// Waits until the heading is attached and visible.
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
// Waits until the URL matches the expected pattern.
await expect(page).toHaveURL(/.*dashboard/);
});
Understanding that assertions are asynchronous by design is crucial. They are not simple one-time checks; they are smart conditions that Playwright evaluates over time based on your configured timeouts.
Common Mistakes
Mistake 1 β Treating expect as a synchronous one-shot check
This leads to redundant waits.
β Wrong: Calling waitForTimeout before every assertion “just in case”.
β
Correct: Let expect handle waiting for most conditions automatically.
Mistake 2 β Asserting on raw values instead of locators
This can be brittle.
β Wrong: Reading text manually via innerText() and asserting with a separate library.
β
Correct: Use expect(locator).toHaveText(...) so Playwright can keep polling until the text updates.