All challenges · Foundations
Challenge 3 of 29 · Beginner-friendly · Foundations
Count Multiple Elements: Reuse One Locator
Repeat an action a set number of times with one locator you keep in a variable. The hidden check counts what your actions produced.
Skills you will practise
- reusing a locator
- repeated actions
- role-based locators
The concept
Playwright locators are descriptions, not snapshots. When you write const tagInput = page.getByRole('textbox', { name: 'Tag' }), nothing is looked up yet. Each time you act on tagInput, Playwright finds the element fresh. That makes it safe to store a locator in a variable and use it again and again, even if the page re-renders between clicks.
This matters when a task says “do this three times” or when you need to check how many items exist. Reusing one well-named locator keeps the test readable and means there is only one place to fix if the UI changes.
To check how many things are on the page, use expect(locator).toHaveCount(n). It retries until the count matches, which avoids reading a number before the page has finished updating.
The fragile version
for (let i = 0; i < 3; i++) {
await page.locator('#app > div:nth-child(4) > button').click();
}
const n = await page.locator('li').count();
expect(n).toBe(3);Why it breaks: The selector is tied to DOM position, and count() reads the number once with no retry, so it can run before the last item appears and fail intermittently.
A robust Playwright version
const tagInput = page.getByRole('textbox', { name: 'Tag' });
for (const tag of ['smoke', 'checkout', 'mobile']) {
await tagInput.fill(tag);
await tagInput.press('Tab');
}
await expect(page.getByRole('listitem')).toHaveCount(3);One readable locator, reused for every action in the loop. The web-first toHaveCount assertion waits until the list reaches the expected size.
This is a general example on a made-up page, not the challenge’s reference solution.
Common mistakes
- Using
forEachwith async callbacks, which does not wait for each click. - Asserting with
count()plustoBe, which does not retry. - Counting too broadly, for example every
lion the page including the navigation menu.
FAQ
Can I store a Playwright locator in a variable?
Yes. Locators are lazy and re-resolve on every action, so they are safe to reuse.
What is the difference between count() and toHaveCount()?
count() returns the number right now. toHaveCount() is an assertion that keeps retrying until it matches or times out.
Why does my loop not wait between clicks?
Array.forEach ignores returned Promises. Use a for or for...of loop with await.
Try it
Practise this in Challenge 3. You write the code in the browser editor with no setup. It runs in a fresh Chromium, a hidden validator checks what actually happened, and you get pass or fail, the logs and a video of the run. Challenges 1 to 10 are open without an account; create a free one any time to keep your progress. The reference solution and the hidden validator are shown only after you pass. We never publish solutions here.