All challenges · Core Interactions

Challenge 15 of 29 · Building fluency · Core Interactions

Filter Table Rows

Narrow a locator to one table row by its text, then act on a control inside that row. The hidden check confirms you picked the right one.

Skills you will practise

  • filter()
  • tables
  • scoped locators

The concept

Tables are full of repeated controls. Every row has an “Edit” button, so getByRole('button', { name: 'Edit' }) matches dozens. The fix is to narrow the search: first find the row you care about, then the control inside it.

locator.filter() keeps only matches that satisfy a condition. filter({ hasText: 'Ada Lovelace' }) keeps rows containing that text; filter({ has: page.getByRole('cell', { name: 'Overdue' }) }) keeps rows containing a matching element. Then you chain a locator onto the result to act inside that row only.

This is called scoping, and it is one of the most useful habits in Playwright: describe where something is in human terms, not by its index.

The fragile version

Fragile
await page.locator('table tr:nth-child(3) td:nth-child(5) button').click();

Why it breaks: Sort the table, add a row, or insert a column and this clicks the wrong person's button, without failing.

A robust Playwright version

Robust
const row = page.getByRole('row').filter({ hasText: 'Ada Lovelace' });
await row.getByRole('button', { name: 'Edit' }).click();
await expect(page.getByRole('dialog', { name: /edit ada lovelace/i })).toBeVisible();

It finds the row by its content and the button by its role, so reordering does not matter.

This is a general example on a made-up page, not the challenge’s reference solution.

Common mistakes

  • Filtering by text that appears in more than one row (for example a first name only).
  • Using nth() on rows after sorting or paging.
  • Filtering the cell instead of the row, then failing to find the button.

FAQ

What does filter() do in Playwright?

It narrows a locator to elements that contain given text (hasText) or a matching child (has).

What is the difference between filter hasText and getByText?

filter({ hasText }) keeps containers that include the text; getByText finds the element holding the text.

Can I filter out rows?

Yes, with hasNotText or hasNot.

Try it

Practise this in Challenge 15. 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. Create a free account to open the practice page and its hints. The reference solution and the hidden validator are shown only after you pass. We never publish solutions here.

Practise this challenge free