Sometimes when writing test automation scripts you come across cases where, after performing an action like clicking on a button, then two different scenarios may occur: for example Page A may load or Page B but you don’t know which. How do you check if the browser has landed on page A or page B?
With Selenium you’d need to write a complicated loop that repeatedly checks for either Page A or Page B being visible, but fortunately with Playwright the “or” operator handles this situation much more cleanly.
Let’s look at how the Playwright “or” operator works.
First let’s pick a specific scenario: after a user logs into your e-commerce website they should arrive at the “Your Account” page where they can see their settings, previous orders etc. However sometimes your website will pop up a promotional offer to upgrade to a higher tier of membership – not always, just sometimes. So your test script needs to check if the popup appears and then click on the “No Thanks” button to continue.
Using the Playwright “or” operator allows you to wait until either of the elements is visible, and in this case we’ll check if the “Your Account” heading is visible in the Account page or if the “No Thanks” button in visible in the Upgrade popup page.
test('Using the Playwright or operator', async ({ page }) => {
// log in
await page.goto('https://www.yourwebsite.com/login');
await page.locator('input#username').fill('alex.smith@test.com');
await page.locator('input#password').fill('password123');
await page.locator('button#login').click();
// close popup if it is displayed
await expect(page.locator('h1#yourAccount').or(page.locator('button#noThanks'))).toBeVisible();
if (await page.locator('button#noThanks').isVisible()) {
await page.locator('button#noThanks').click();
}
// carry on with test....
});
Here you can see the test script waiting for either the Your Account page to be visible or the No Thanks button on the upgrade popup to be visible, then if the No Thanks button is visible it will click on it to close it.
Here’s the same code using Page Object Model:
test('Using the Playwright or operator with POM', async ({ page }) => {
// log in
await page.goto('https://www.yourwebsite.com/login');
const loginPage = new LoginPage(page);
await loginPage.login('alex.smith@test.com', 'password123');
// close popup if it is displayed
const accountPage = new AccountPage(page);
const upgradePopup = new UpgradePopup(page);
await expect(accountPage.heading.or(upgradePopup.noThanksButton)).toBeVisible();
if (await upgradePopup.noThanksButton.isVisible()) {
await upgradePopup.noThanksButton.click();
}
// carry on with test....
});
More than two
Gotchas
In the above scenario we will never have the situation where both the “Your Account” heading and “No Thanks” button will be visible at the same time, but there may be different scenarios where this is a possibility.
If this happens then you will get a “strict mode violation” error – see the help below:

To fix this you need to add a nth(0) to the statement:
await expect(accountPage.heading.or(upgradePopup.noThanksButton).nth(0)).toBeVisible();
This will always return just 1 locator, and will still work if it returns one in any case.