Table of contents
When testing your front end, selecting elements efficiently and reliably is crucial for writing robust tests. Playwright, a modern framework for browser automation, introduces two primary methods for element selection: element handles and page locators. While both serve the purpose of interacting with the DOM, page locators offer distinct advantages that make them the superior choice for most testing scenarios. This post explains why page locators are the correct way to select elements with Playwright, drawing insights from practical examples.
Understanding Element Handles and Page Locators
Element handles (page.$
and page.$$
) allow you to directly access DOM elements. For instance, you might use an element handle to click a button or fetch a collection of images. Initially, this approach seems straightforward and effective. However, element handles have a significant limitation: they capture a snapshot of the DOM at a specific moment. If the DOM changes after you've obtained an element handle (e.g., after clicking a button that dynamically adds content), the handle won't reflect these updates. This behavior can lead to flaky tests that fail when elements are dynamically added or removed from the page.
Page locators, on the other hand, are designed to be "lazy." They don't immediately query the DOM when defined. Instead, Playwright evaluates them only at the moment of use, ensuring they always reference the current state of the DOM. This lazy evaluation makes page locators inherently more flexible and reliable for dynamic content.
The Case for Page Locators
Let's consider a practical example to illustrate the benefits of page locators over element handles. Imagine a test scenario where you need to click a button on a webpage, which then dynamically adds images to the DOM. With element handles, if you try to assert the number of images before and after clicking the button, you might encounter failures because the handles won't automatically update to reflect the new DOM state.
Page locators solve this problem elegantly. Since they evaluate the DOM lazily, they always operate on the most current representation of the page. This means you can perform actions or assertions with confidence, knowing that you're interacting with the latest elements. Moreover, page locators integrate seamlessly with Playwright's expect
API, offering convenient methods like toHaveCount
, toBeHidden
, and toHaveClass
, which further simplifies writing assertions.
What is ElementHandle in Playwright?
ElementHandle represents a reference to an in-page DOM element within a Playwright script. These handles are created using the page.$()
method and provide a direct link to a specific element on the page. Unlike Locators, which are abstract descriptions of how to find elements, ElementHandles point to an actual element in the DOM at the time of their creation.
Key Features and Methods of ElementHandle
- Preventing Garbage Collection: ElementHandles prevent their corresponding DOM element from being garbage-collected by the browser, ensuring the element remains accessible as long as the handle exists. They are automatically disposed of when their originating frame navigates away or when explicitly disposed of using
jsHandle.dispose()
. - Interaction and Evaluation: ElementHandles can be used to perform actions on elements (e.g., clicking with
hrefElement.click()
) and as arguments inpage.$eval()
andpage.evaluate()
methods, allowing for direct manipulation and evaluation of elements. - Bounding Box Calculation: The
boundingBox
method returns the visible bounding box of the element, useful for interactions requiring precise positioning, such as mouse clicks. - Content Frame Access: For elements referencing iframe nodes,
contentFrame
returns the content frame, enabling interaction within iframes. - Owner Frame Identification:
ownerFrame
returns the frame containing the element, useful in multi-frame scenarios to understand element context. - State Waiting:
waitForElementState
allows scripts to wait for elements to reach a certain state (e.g., visible, stable, enabled) before proceeding, enhancing reliability in dynamic content scenarios.
Why Use ElementHandle?
Despite the general recommendation towards using Locators, there are scenarios where ElementHandles might be preferred or necessary:
- Direct Element Reference: When you need a stable reference to a specific element that won't change, ElementHandles provide a direct link to that element, unaffected by subsequent DOM changes.
- Precise Interaction: For tasks requiring exact positioning, such as clicking at a specific point within an element, the bounding box information from an ElementHandle is invaluable.
- Complex Evaluations and Actions: In cases where complex, element-specific JavaScript evaluations or actions are required, an ElementHandle can be directly manipulated within
page.evaluate()
or used withpage.$eval()
for more intricate operations. - Iframe Interactions: When interacting with content within iframes, using
contentFrame
from an ElementHandle can simplify the process of accessing and interacting with elements inside the iframe.
The advantage and the disadvantage of ElementHandle is that it’s more brittle: if we want to make absolutely positively sure that the same element is loading in the same state as when we wrote the test, ElementHandle is the right technique. Again that’s also the disadvantage, as brittle-ness is a primary complaint by users trying to maintain frontend and end-to-end tests.
Advantages of Page Locators
- Dynamic Content Handling: Page locators are inherently suited for modern web applications where content is frequently added or removed. They ensure your tests remain stable and reliable even as the DOM changes.
- Simplified Assertions: The integration with Playwright's
expect
API allows for more readable and concise assertions. This not only makes your tests easier to understand but also reduces the amount of boilerplate code. - Improved Test Stability: By always referencing the current state of the DOM, page locators reduce the likelihood of flaky tests. This stability is crucial for continuous integration environments and automated testing pipelines.
- Efficiency: Since page locators are evaluated only when used, they can lead to more efficient tests. There's no need to re-query the DOM or manage element handles manually, which can save time and resources, especially in complex test suites.
If you love your users, stick with Page Locators in Playwright
While element handles may still have their place in certain scenarios, page locators represent a more advanced and reliable method for element selection in Playwright tests. Their lazy evaluation model, seamless integration with assertion methods, and superior handling of dynamic content make them the correct choice for most testing needs. By adopting page locators, developers and testers can write more stable, efficient, and readable tests, ensuring their web applications function correctly across all scenarios.
To see page locators in action, check out Stefan’s video on the same topic from our Checkly YouTube channel:
Join the Checkly Community
If you have your own experience using different standards for finding page elements, we’d love to hear from you. Join the Checkly community Slack, follow us on X, or connect on LinkedIn.