PaleNeutron
PaleNeutron

Reputation: 3215

How can I wait until elements matching multiple selectors appear?

For example, I'm testing a search page, which will show the result numbers in .text > span:nth-child(1).

However, if not any result, it will only show text="nothing" or .text > span:nth-child(1) does not exist.

How can I wait for both conditions?

Upvotes: 10

Views: 11274

Answers (3)

Vishal Aggarwal
Vishal Aggarwal

Reputation: 4177

As per playwright docs, don't rely on pure CSS selectors .

NOTE We recommend prioritizing user-visible locators like text or accessible role instead of using CSS that is tied to the implementation and could break when the page changes.

From v1.33 you may use OR condition natively

await expect(locatorA.or(locatorB)).toBeVisible()

Simple Example:

Consider a scenario where you'd like to click on a "New email" button, but sometimes a security settings dialog shows up instead. In this case, you can wait for either a "New email" button, or a dialog and act accordingly.

const newEmail = page.getByRole('button', { name: 'New' });
const dialog = page.getByText('Confirm security settings');
await expect(newEmail.or(dialog)).toBeVisible();
if (await dialog.isVisible())
  await page.getByRole('button', { name: 'Dismiss' }).click();
await newEmail.click();

Upvotes: 6

Yevhen Laichenkov
Yevhen Laichenkov

Reputation: 8662

You need to use a comma-separated list of CSS selectors which will match all elements that can be selected by one of the selectors in that list:

//                                           ↓ comma
await page.locator('.text > span:nth-child(1), span:has-text("nothing")').innerText();

It will wait for either .text > span:nth-child(1) or span:has-text("nothing").

Upvotes: 16

Christian Baumann
Christian Baumann

Reputation: 3434

You can wait for both elements, using a try-catch, and setting a boolean variable, depending on which element is being found.

In Java you could use something like

Boolean nothingFound, resultsFound = false;

try {
    page.waitForSelector("text=\"nothing\"");
    nothingFound = true;

} catch (Exception e) {}

try {
    page.waitForSelector(".text > span:nth-child(1)");
    resultsFound = true;
} catch (Exception e) {}

I'm not a Javascript expert, but I think something like this should work:

let  nothingFound, resultsFound = false;

try {
    await page.waitForSelector('text="nothing"');
    nothingFound = true;
}
catch (e) {}

try {
    await page.waitForSelector('.text > span:nth-child(1)');
    resultsFound = true;
}
catch (e) {}

Upvotes: 2

Related Questions