← Back to Playwright Mastery
Intermediate16 min read

Assertions & Validation

Use web-first expect assertions with auto-retry and custom matchers.

Web-First expect

Playwright expect polls until condition met or timeout—unlike Jest expect which checks once. toBeVisible, toHaveText, toHaveValue, toBeChecked, toHaveURL, toHaveTitle common matchers.

Configure timeout per assertion: expect(locator).toHaveText("Done", { timeout: 10000 }).

await expect(page.getByRole("alert")).toHaveText("Saved successfully");
await expect(page).toHaveURL(/\/success/);
await expect(page.getByTestId("count")).toHaveText("3");

Soft Assertions

expect.soft continues test after failure, reporting all soft failures at end—useful for visual checklist pages. Hard assertions stop immediately.

Do not overuse soft—critical path assertions should fail fast.

await expect.soft(page.getByText("Header")).toBeVisible();
await expect.soft(page.getByText("Footer")).toBeVisible();

Negation and Count

not matcher inverts: toBeHidden, not.toHaveText. toHaveCount asserts list length. toContainText partial match.

Polling works for negation too—wait until element hidden after delete animation.

await expect(page.getByText("Loading")).toBeHidden();
await expect(page.getByRole("listitem")).toHaveCount(5);

API Response Assertions

Use APIRequestContext or waitForResponse during UI action to assert HTTP status and JSON body.

page.waitForResponse predicate filters URL and status before await click triggering request.

const responsePromise = page.waitForResponse(
  (r) => r.url().includes("/api/order") && r.status() === 201
);
await page.getByRole("button", { name: "Place order" }).click();
const response = await responsePromise;
const body = await response.json();
expect(body.id).toBeTruthy();

Custom Expect Messages

Pass message as second argument or use expect.configure for global soft/hard defaults.

Combine with test.step for readable report steps grouping actions and assertions.

await test.step("Verify checkout summary", async () => {
  await expect(page.getByTestId("total")).toHaveText("$99.00");
});

Get In Touch


Ready to discuss your next project? Drop me a message.