Soft Assertions in Playwright



Playwright Training
Playwright Training

These three assertions are among the most powerful features in Playwright Test. They help you write more reliable tests by handling retries and failures in different ways.

  1. expect.soft() (Soft Assertion)

A soft assertion records a failure but does not stop the test immediately. The test continues executing, and all soft assertion failures are reported at the end.

Normal Assertion

If this fails, the test stops immediately.

import { test, expect } from ‘@playwright/test’;

test(‘Hard Assertion’, async ({ page }) => {

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

await expect(page).toHaveTitle(‘Wrong Title’);

console.log(‘This line will NOT execute.’);

});

Output

❌ Test Failed

Execution stopped.

Soft Assertion

import { test, expect } from ‘@playwright/test’;

test(‘Soft Assertion Example’, async ({ page }) => {

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

await expect.soft(page).toHaveTitle(‘Wrong Title’);

console.log(‘This line WILL execute.’);

await expect.soft(page.locator(‘h1’)).toHaveText(‘Wrong Heading’);

console.log(‘This also executes.’);

});

Output

❌ Title mismatch

❌ Heading mismatch

Test finished.

2 soft assertion failures.

When to use

  • Validating multiple fields on a page.
  • Checking dashboard widgets.
  • Verifying reports with many values.
  • UI comparison tests where you want all failures at once.

Example:

await expect.soft(page.locator(‘#firstName’)).toHaveValue(‘John’);

await expect.soft(page.locator(‘#lastName’)).toHaveValue(‘Smith’);

await expect.soft(page.locator(‘#email’)).toHaveValue(‘john@test.com’);

await expect.soft(page.locator(‘#country’)).toHaveValue(‘India’);

Instead of stopping at the first failure, Playwright reports every mismatch.

  1. expect.poll()

expect.poll() repeatedly executes a function until the expected value is returned or the timeout expires.

Think of it as:

Check

Still not correct

Wait

Check again

Wait

Check again

Success

It is useful when the value is not automatically retried by a locator assertion, such as an API response, database state, or a computed value.

Example: Polling an API

import { test, expect } from ‘@playwright/test’;

test(‘Poll Example’, async ({ request }) => {

await expect.poll(async () => {

const response = await request.get(‘/status’);

const body = await response.json();

return body.status;

}).toBe(‘Completed’);

});

Playwright keeps calling the function until it returns “Completed” or the timeout is reached.

Example: Waiting for a Counter

await expect.poll(async () => {

return Number(await page.locator(‘#counter’).textContent());

}).toBe(10);

Suppose the counter updates like this:

1

3

5

7

10

Playwright keeps checking until it sees 10.

Custom Timeout

await expect.poll(

async () => {

return await page.locator(‘#status’).textContent();

},

{

timeout: 30000

}

).toBe(‘Completed’);

Custom Polling Intervals

await expect.poll(

async () => getStatus(),

{

intervals: [1000, 2000, 5000]

}

).toBe(‘Done’);

Playwright waits:

  • 1 second
  • 2 seconds
  • 5 seconds

between successive retries according to the configured intervals.

Best use cases

  • API status checks
  • Database validation
  • Queue processing
  • Background jobs
  • Email delivery status
  • File generation

 

  1. expect.toPass()

expect.toPass() retries an entire block of code until every assertion inside it passes or the timeout is reached.

This is different from expect.poll(), which retries only a returned value.

Example

await expect(async () => {

await expect(page.locator(‘#status’)).toHaveText(‘Completed’);

await expect(page.locator(‘#message’)).toContainText(‘Success’);

}).toPass();

If either assertion fails, the whole callback is executed again.

Real-world Example

Suppose clicking a button starts a background process.

await page.click(‘#process’);

await expect(async () => {

await expect(page.locator(‘#status’)).toHaveText(‘Completed’);

await expect(page.locator(‘#percentage’)).toHaveText(‘100%’);

await expect(page.locator(‘#result’)).toContainText(‘Success’);

}).toPass({

timeout: 30000

});

Playwright keeps rerunning the entire block until all three assertions succeed.

expect.poll() vs expect.toPass()

Feature expect.poll() expect.toPass()
Retries A function that returns a value An entire callback block
Typical use API, database, computed values Multiple assertions or actions that may eventually succeed
Returns A value to compare No value; assertions determine success
Best for Waiting for one changing value Waiting for a complete state involving several checks

Which one should you choose?

Situation Recommended
Verify several fields but continue after failures expect.soft()
Wait for an API, queue, database, or single value to reach a target expect.poll()
Wait until multiple assertions all become true together expect.toPass()

Summary

  • expect.soft(): Collects assertion failures and lets the test continue.
  • expect.poll(): Repeatedly evaluates a function until its returned value matches the expectation.
  • expect.toPass(): Repeatedly executes a block of assertions until the entire block passes.

Together, these features make Playwright tests more resilient when dealing with asynchronous operations, eventually consistent systems, and comprehensive UI validation.

Techtutotialz Training, Job support, Interview support
Techtutotialz Training, Job support, Interview support
Tags: , , , ,
Leave a comment

Your email address will not be published. Required fields are marked *

Subscribe now

Receive weekly newsletter with educational materials, new courses, most popular posts, popular books and much more!