Playwright Assertions with TypeScript – Complete Guide with Examples

Assertions are one of the most important concepts in Playwright test automation. They verify whether the application behaves as expected after performing an action. Without assertions, your automation script simply performs actions without validating the results.

Playwright provides a powerful assertion library built on top of expect(), which automatically waits for conditions to become true before failing the test. This feature makes Playwright tests much more reliable compared to traditional automation frameworks.

In this article, you’ll learn everything about Playwright assertions, including different assertion types, best practices, and practical examples using TypeScript.


What are Assertions?

Assertions verify the expected state of your application.

For example, after clicking the Login button, you may want to verify:

  • User is redirected to Dashboard
  • Welcome message is displayed
  • Logout button is visible
  • Shopping cart contains 3 products

If the expected condition is not met, the test fails.

Example:

expect(await page.title()).toBe("Dashboard");

Why Playwright Assertions are Powerful

Unlike traditional assertions, Playwright assertions:

  • Auto-wait until the condition becomes true
  • Retry assertions automatically
  • Produce detailed error messages
  • Capture screenshots on failures
  • Generate trace files
  • Work with UI elements directly

Traditional Selenium example:

Thread.sleep(5000);
Assert.assertEquals(driver.getTitle(), "Dashboard");

Playwright:

await expect(page).toHaveTitle("Dashboard");

No manual waits required.


Importing Assertions

Playwright Test automatically provides expect.

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

Assertion Categories

Playwright provides several assertion types.

  • Value Assertions
  • Locator Assertions
  • Page Assertions
  • API Assertions
  • Screenshot Assertions
  • Soft Assertions
  • Polling Assertions
  • Custom Assertions

Let’s explore each one.


1. Value Assertions

Used for JavaScript values.

Example:

test('Number Assertion', async () => {

    const count = 10;

    expect(count).toBe(10);

});

toBe()

Checks exact equality.

expect(5).toBe(5);

Example

const user = "Deepesh";

expect(user).toBe("Deepesh");

not.toBe()

expect(5).not.toBe(10);

toEqual()

Used for arrays and objects.

const user = {
    name: "John",
    age: 30
};

expect(user).toEqual({
    name: "John",
    age: 30
});

toContain()

expect(["Apple","Orange"]).toContain("Apple");

String example

expect("Playwright Automation").toContain("Automation");

toHaveLength()

expect([1,2,3]).toHaveLength(3);

String

expect("Playwright").toHaveLength(10);

toBeTruthy()

expect(true).toBeTruthy();

Example

const isLoggedIn = true;

expect(isLoggedIn).toBeTruthy();

toBeFalsy()

expect(false).toBeFalsy();

toBeNull()

expect(null).toBeNull();

toBeDefined()

const username = "Admin";

expect(username).toBeDefined();

toBeUndefined()

let city;

expect(city).toBeUndefined();

toBeGreaterThan()

expect(20).toBeGreaterThan(10);

toBeLessThan()

expect(5).toBeLessThan(10);

toBeCloseTo()

Useful for decimal values.

expect(0.1 + 0.2).toBeCloseTo(0.3);

2. Locator Assertions

Locator assertions are the most commonly used assertions in Playwright.

Example locator

const loginButton = page.locator("#login");

toBeVisible()

Checks whether an element is visible.

await expect(loginButton).toBeVisible();

toBeHidden()

await expect(page.locator(".loader")).toBeHidden();

toBeEnabled()

await expect(loginButton).toBeEnabled();

toBeDisabled()

await expect(page.locator("#submit")).toBeDisabled();

toBeChecked()

Checkbox example

await page.locator("#remember").check();

await expect(page.locator("#remember")).toBeChecked();

toHaveText()

await expect(page.locator("h1"))
.toHaveText("Dashboard");

toContainText()

await expect(page.locator(".message"))
.toContainText("Success");

toHaveValue()

Textbox example

await page.fill("#username","Admin");

await expect(page.locator("#username"))
.toHaveValue("Admin");

toHaveAttribute()

await expect(page.locator("#email"))
.toHaveAttribute("type","email");

toHaveClass()

await expect(page.locator(".active"))
.toHaveClass("active");

Multiple classes

await expect(page.locator(".btn"))
.toHaveClass(/btn primary/);

toHaveCount()

Useful for lists.

await expect(page.locator(".product"))
.toHaveCount(8);

toBeEditable()

await expect(page.locator("#username"))
.toBeEditable();

toHaveCSS()

await expect(page.locator("#title"))
.toHaveCSS("color","rgb(255, 0, 0)");

toHaveJSProperty()

await expect(page.locator("#checkbox"))
.toHaveJSProperty("checked", true);

toHaveId()

await expect(page.locator("#login"))
.toHaveId("login");

3. Page Assertions


toHaveTitle()

await expect(page)
.toHaveTitle("Dashboard");

toHaveURL()

await expect(page)
.toHaveURL("https://example.com/dashboard");

Using Regex

await expect(page)
.toHaveURL(/dashboard/);

4. Screenshot Assertions

Playwright can compare screenshots automatically.

await expect(page)
.toHaveScreenshot();

Specific filename

await expect(page)
.toHaveScreenshot("homepage.png");

Element screenshot

await expect(page.locator(".logo"))
.toHaveScreenshot();

This is useful for visual regression testing.


5. API Assertions

Example

const response = await page.request.get(
    "https://reqres.in/api/users/2"
);

expect(response.status()).toBe(200);
expect(response.ok()).toBeTruthy();

Verify JSON

const body = await response.json();

expect(body.data.first_name)
.toBe("Janet");

6. Soft Assertions

Normally,

expect(value).toBe(expected);

stops execution when it fails.

Soft assertions allow the test to continue.

expect.soft(title).toBe("Dashboard");

expect.soft(username).toBe("Admin");

Example

test('Soft Assertions', async ({ page }) => {

    await page.goto("https://example.com");

    await expect.soft(page).toHaveTitle("Home");

    await expect.soft(page.locator("h1"))
    .toContainText("Example");

    await expect.soft(page.locator("#login"))
    .toBeVisible();

});

7. Polling Assertions

Sometimes values are updated after several seconds.

Playwright provides polling.

await expect.poll(async () => {

    return await page.locator(".counter").textContent();

}).toBe("10");

Playwright retries until timeout.


8. Custom Message

Provide a helpful failure message.

expect(
    totalPrice,
    "Total price should be greater than zero"
).toBeGreaterThan(0);

9. Array Assertions

const fruits = [
    "Apple",
    "Orange",
    "Mango"
];

expect(fruits).toContain("Orange");
expect(fruits).toHaveLength(3);

10. Object Assertions

const employee = {

    id:1,
    name:"John"

};

expect(employee).toEqual({

    id:1,
    name:"John"

});

Real Login Example

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

test('Verify Login', async ({ page }) => {

    await page.goto("https://example.com");

    await page.fill("#username","Admin");

    await page.fill("#password","admin123");

    await page.click("#login");

    await expect(page)
        .toHaveURL(/dashboard/);

    await expect(page.locator("h1"))
        .toContainText("Dashboard");

    await expect(page.locator("#logout"))
        .toBeVisible();

});

Assertion Timeouts

By default, Playwright retries assertions until the configured timeout.

Example:

await expect(locator).toBeVisible({
    timeout: 10000
});

This waits up to 10 seconds before failing.


Combining Assertions

await expect(page).toHaveTitle("Dashboard");

await expect(page).toHaveURL(/dashboard/);

await expect(page.locator("#welcome"))
    .toContainText("Welcome");

await expect(page.locator("#logout"))
    .toBeVisible();

await expect(page.locator(".product"))
    .toHaveCount(6);

Best Practices

  • Prefer Playwright locator assertions (toBeVisible, toHaveText, etc.) over manual value checks because they automatically wait for the expected condition.
  • Avoid using waitForTimeout() before assertions. Let Playwright’s built-in retry mechanism handle synchronization.
  • Use descriptive locators (getByRole, getByLabel, getByTestId) instead of fragile CSS or XPath selectors whenever possible.
  • Use expect.soft() when you want to collect multiple verification failures in a single test execution.
  • Keep assertions focused on one expected behavior to make failures easier to understand.
  • Add meaningful custom messages for business-critical validations.
  • Use regular expressions with toHaveURL() and toHaveText() when parts of the value are dynamic.
  • For visual testing, use screenshot assertions only for stable UI components to reduce flaky results.
  • Set assertion-specific timeouts only when an element legitimately requires more time to appear.

Common Mistakes

Using Manual Waits

await page.waitForTimeout(5000);

expect(await page.title()).toBe("Dashboard");

await expect(page).toHaveTitle("Dashboard");

Using textContent() Instead of Locator Assertions

const text = await page.locator("h1").textContent();

expect(text).toBe("Dashboard");

await expect(page.locator("h1"))
    .toHaveText("Dashboard");

Hard-Coding Dynamic URLs

await expect(page).toHaveURL(
    "https://example.com/dashboard?id=123"
);

await expect(page).toHaveURL(/dashboard/);

Summary

Playwright assertions are a core part of building stable and maintainable automated tests. Their automatic waiting, intelligent retries, and rich set of locator-specific assertions eliminate much of the flakiness found in traditional UI automation frameworks.

By mastering value assertions, locator assertions, page assertions, API assertions, soft assertions, polling, and visual assertions, you can create robust end-to-end tests that are easier to read, debug, and maintain. Adopting Playwright’s built-in assertion methods instead of manual waits or custom validation logic will result in faster, more reliable, and more professional automation suites.

Leave a Comment