Playwright Locator Filtering
A teacher calling out "the student in the blue shirt" among thirty children wearing similar uniforms needs a better description to find the right one. Filtering gives Playwright that better description when a page shows many nearly identical elements.
The Problem Filtering Solves
A product listing page might repeat the same "Add to Cart" button ten times, once per product. A plain locator searching for that button text alone would match all ten, leaving Playwright unsure which one to click.
Many Similar Elements
Product List |-- Item: "Running Shoes" [Add to Cart] |-- Item: "Leather Wallet" [Add to Cart] |-- Item: "Sports Watch" [Add to Cart]
Filtering narrows the search down to only the button sitting next to "Sports Watch," ignoring the other two identical buttons.
Filtering by Visible Text
const item = page.locator('.product-card').filter({ hasText: 'Sports Watch' });
await item.getByRole('button', { name: 'Add to Cart' }).click();This code first narrows the search to the one product card containing "Sports Watch," then clicks the button only within that specific card.
Filtering by a Child Element
const inStockItems = page.locator('.product-card').filter({
has: page.locator('.in-stock-badge'),
});This filters product cards down to only those containing an "in stock" badge, skipping cards showing an "out of stock" label entirely.
Selecting by Position
await page.locator('.product-card').first().click();
await page.locator('.product-card').last().click();
await page.locator('.product-card').nth(2).click();These methods pick items by their position in the list. Counting starts at zero, so nth(2) actually selects the third item on the page.
A Real-World Example: A Restaurant Menu
A food delivery website lists many dishes, each with its own "Add" button. A test needs to add exactly one dish named "Paneer Butter Masala" to the cart. Filtering by that exact dish name guarantees the correct button gets clicked, regardless of how many other dishes sit on the same page.
await page.locator('.menu-item').filter({ hasText: 'Paneer Butter Masala' })
.getByRole('button', { name: 'Add' }).click();Combining Multiple Filters
const result = page.locator('.product-card')
.filter({ hasText: 'Shoes' })
.filter({ has: page.locator('.in-stock-badge') });Chaining two filters narrows results even further, matching only shoe products that also show as currently in stock.
Quick Practice Task
Visit a shopping or news website with a repeated list layout, such as articles or products. Write a locator that filters that list down to one item using its visible text.
Key Takeaways
- Filtering narrows a group of matching elements to one exact target.
- Text-based filtering stays readable and resistant to layout changes.
- Position-based selection works best only when order never changes.
- Multiple filters can chain together for very specific matches.
