playwright: [Question] Is the locator.count() function supposed to wait for elements matching that locator before returning the count value?

Hi,

I’ve been trying to use the locator.count function in my typescript Playwright test and I’ve been fumbling around trying to figure out why I was getting a 0 value returned from the count function. As I was debugging, I searched with the exact locator that my test was using on the chromium dev tools and it was finding 5 elements.

The original code I was using was:

const numberOfDresses: number = await this.page.locator(DressesPage.dressesPrices).count();

which was returning 0.

And I had to change it to this in order for it to work:

await this.page.locator(DressesPage.dressesPrices).nth(1).waitFor();
const numberOfDresses: number = await this.page.locator(DressesPage.dressesPrices).count();

So it got me wondering… Is the locator.count() function supposed to wait for elements matching that locator before returning the count value? Or have I stumbled across a bug?

Thanks, Mathew

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 8
  • Comments: 15 (7 by maintainers)

Commits related to this issue

Most upvoted comments

Are you interested in toBeGreaterCount? Like if you don’t know what to wait for, then either toBeGreaterCount could be a valid feature request or you use your approach with just waitFor which waits for at least one element.

In the end, I just used what I was using:

await this.page.locator(DressesPage.dressesPrices).nth(1).waitFor();
const numberOfDresses: number = await this.page.locator(DressesPage.dressesPrices).count();

This question was really raised because I didn’t understand how .count() works and I thought I might’ve encountered a bug in the function. For anyone who might find this from a Google search, just know that the .count() function will get a count without waiting for any elements that match your provided locator, so you have to wait first.

No, I actually want to get the count of how many elements appear on the screen which match a given locator, without any prior knowledge of how many might appear. In my exact situation, x number of dresses will be displayed for sale on a webpage. At any given point, the merchant could add or remove dresses, and my goal is to get a count of all dresses displayed on the webpage and loop through them to find and select the most expensive one, then add it to the cart. For this scenario, a toHaveCount(x) or hypothetically a toBeGreaterCount(x) function would not be suitable.

Essentially, I think it might be useful to have a count() function which waits for the elements to be displayed first, e.g. waitThenCount()

locator.count() is not wait, it does the amount of elements which are found of the time you issue the command.

To wait for elements, you should use the web-first assertions: await expect(page.locator('.fooobar').toHaveCount(42) which waits automatically until the condition is met: https://playwright.dev/docs/test-assertions#locator-assertions-to-have-count

Alternatively do it like you did by using waitFor, but we don’t recommend it, since web-first assertions make it more readable.

    await expect.poll(async () => page.locator('div').count()).toBeGreaterThan(5);

or

await expect(page.locator('.fooobar').toHaveCount(42)

I stumbled upon this aswell today but I don’t think that these should be the way forward and I cant explain why I get different results in this example:

const itemsList: number = await page.locator('[data-testid="education.navigation.item"]').count();
await expect(page.locator('[data-testid="education.navigation.item"]')).toHaveCount(4) // success
console.log(itemsList); // returns 0

Feel free to file a feature request for it!

Same here, I think there are many valid uses cases for this. I would name it toHaveCountGreaterThan() (and corresponding toHaveCountLessThan)