Playwright: Filter Visible Elements With locator.filter({ visible: true })
This highlights Playwright's new locator.filter({ visible: true }) feature, which simplifies testing by focusing on visible elements, improving accuracy and test clarity.
Join the DZone community and get the full member experience.
Join For FreeThis blog covers how the new filter visible element option helps in writing more precise, user-focused tests with ease with the option locator.filter({ visible: true })
.
Playwright has quickly become a go-to tool for end-to-end testing, thanks to its robust API, cross-browser support, and easy handling of modern web applications. One of its standout features is the locator API, which allows testers to precisely target elements on a page. With recent updates, Playwright has added even more power to this API, including a new visible option for the locator.filter() method
.
This feature simplifies the process of working with only visible elements, making your tests cleaner, more reliable, and easier to maintain. In this blog, we’ll dive into what this new option does, why it matters, and how to use it effectively with a practical example.
Why Visibility Matters in Testing
In web testing, visibility is a critical factor. Elements on a page might exist in the DOM (Document Object Model) but not be visible to users due to CSS properties like display: none
, visibility: hidden
, or even positioning that pushes them off-screen. When writing automated tests, you often want to interact only with elements that a real user can see and interact with. Ignoring hidden elements ensures your tests reflect the actual user experience, avoiding false positives or unexpected failures.
Before the visible option was added to locator.filter()
, Playwright developers had to rely on workarounds like chaining additional selectors, using isVisible() checks
, or filtering locators manually. Let’s explore how it works and why it’s a game-changer.
Introducing the Visible Option in locator.filter()
The locator.filter()
method in Playwright allows you to refine a set of matched elements based on specific conditions. The addition of the visible option, set to true, now lets you filter a locator to include only elements that are visible on the page.
This small but mighty addition eliminates the need for extra checks and keeps your test logic concise. To see it in action, let’s walk through a practical example inspired by a common testing scenario: working with a to-do list.
Old Approach Example
Let's take the example below, where two elements are hidden:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To-Do List</title>
</head>
<body>
<h1>My To-Do List</h1>
<ul>
<li data-testid="todo-item">Buy groceries</li>
<li data-testid="todo-item">Complete project</li>
<li data-testid="todo-item">Java</li>
<li data-testid="todo-item" style="display: none;">Hidden task</li> <!-- Hidden item -->
<li data-testid="todo-item">Read a book</li>
<li data-testid="todo-item" style="visibility: hidden;">Another hidden task</li> <!-- Hidden item -->
</ul>
</body>
</html>
Without the visible option, you’d need a more complex solution, like looping through elements and checking their visibility individually — something like below.
const allItems = await page.getByTestId('todo-item').all();
const visibleItems = [];
for (const item of allItems) {
if (await item.isVisible()) {
visibleItems.push(item);
}
}
expect(visibleItems.length).toBe(3);
With Filtering Visible Option Example
Imagine you’re testing a to-do list application. The app displays a list of tasks, some of which are marked as “complete” and hidden from view (e.g., with display: none), while others remain visible. Your goal is to verify that exactly three to-do items are visible to the user.
Here’s how you can achieve this with the new visible option in Playwright for the below HTML:
// example.spec.ts
import { test, expect } from '@playwright/test';
test('some test', async ({ page }) => {
// Navigate to the to-do list page
await page.goto('http://example.com/todo');
// Get all to-do items and filter for visible ones
const todoItems = page.getByTestId('todo-item').filter({ visible: true });
// Assert that there are exactly 3 visible to-do items
await expect(todoItems).toHaveCount(3);
});
Let’s break this down:
- Setup: The test navigates to a hypothetical to-do list page.
- Locator:
page.getByTestId(‘todo-item’)
selects all elements with thedata-testid=”todo-item”
attribute. This might match five elements in the DOM, for example, including both visible and hidden ones. - Filtering:
.filter({ visible: true })
narrows the selection to only those elements that are visible on the page. - Assertion:
expect(todoItems).toHaveCount(3)
checks that exactly three to-do items are visible, ensuring the test aligns with the user’s perspective.
Why This Matters for Testers
The addition of visible to locator.filter()
improves readability, and makes tests more intuitive. For teams managing large test suites, this can save time and reduce maintenance overhead. Plus, it aligns with Playwright’s goal of providing tools that feel natural for testing modern, dynamic web apps.
Conclusion
Filtering visible elements with locator.filter({ visible: true })
is a simple yet transformative addition to Playwright. It empowers testers to write more precise, user-focused tests without jumping through hoops. The to-do list example we explored demonstrates its clarity and efficiency, but the possibilities extend far beyond that. Next time you’re testing a web app, give it a try — your test suite will thank you!
Opinions expressed by DZone contributors are their own.
Comments