Filtering Locators by Text Content in Playwright with TypeScript
How I used Playwright's locator filtering to extract data
Introduction
Automating web testing often involves interacting with elements that lack unique identifiers like IDs or classes. In such cases, Playwright's powerful locator filtering capabilities can save the day. In this post, we'll explore how to filter locators by text content in TypeScript, using a real-world example from the American Freight Refrigerators & Freezers page.
Our goal is to capture the number of items displayed on the page, where the text (e.g., "Showing 24 results") is not tied to a unique ID. We'll use Playwright's text-based filtering and parse the result to extract the number.
The Challenge
On the American Freight page, the text indicating the number of results is displayed dynamically, something like:
Showing 24 results
The element containing this text doesn't have a unique ID or class, making it tricky to locate directly. A naive approach might grab multiple elements with similar text, leading to incorrect results. Playwright's locator filtering allows us to narrow down the search by combining text matching with additional conditions.
Screenshot of the page that I am testing.
Solution: Playwright Locator Filtering
Playwright provides the getByText
method to locate elements by their text content. We can further refine this using the filter
method to ensure we target the exact element. Here's how it works:
- Use
page.getByText('Showing', { exact: false })
to find elements containing the word "Showing". - Apply
filter({ hasText: 'results' })
to narrow down to elements that also contain "results". - Extract the text content and parse it to get the number using a regular expression.
Below is the complete TypeScript code for the test:
import { test, expect } from '@playwright/test';
test('American Freight Refrigerator Numbers', async ({ page }) => {
await page.goto('https://www.americanfreight.com/plp/appliances/refrigerators-freezers/695');
// Locate element with text starting with "Showing" and containing "results"
const locator = page.getByText('Showing', { exact: false });
const element = locator.filter({ hasText: 'results' });
const text = await element.innerText();
const match = text.match(/Showing (d+) results/);
const resultsNumber = match ? match[1] : null;
console.log(`Number of results: ${resultsNumber}`);
expect(resultsNumber).not.toBeNull();
});
Code Breakdown
Let's dissect the key parts of the code:
- Navigating to the Page:
await page.goto(...)
loads the American Freight page. - Locating by Text:
page.getByText('Showing', { exact: false })
finds all elements containing "Showing". Theexact: false
option allows partial matches. - Filtering:
locator.filter({ hasText: 'results' })
refines the locator to only include elements that also contain "results". - Extracting Text:
await element.innerText()
retrieves the full text content (e.g., "Showing 24 results"). - Parsing the Number: The regex
/Showing (d+) results/
captures the number between "Showing" and "results". The result is stored inresultsNumber
.
Why Use Locator Filtering?
Locator filtering is a game-changer for several reasons:
- Precision: It allows you to target elements based on multiple conditions, reducing false positives.
- Flexibility: You can combine text, attributes, or even child elements in the filter.
- Robustness: It handles dynamic content where IDs or classes may change.
In our example, filtering ensured we got the exact element with "Showing" and "results", avoiding other elements with similar text.
Tips for Success
- Inspect the Page: Use browser DevTools to confirm the text content and structure before writing your locator.
- Test Your Locator: Use Playwright's
locator.count()
orlocator.all()
to verify how many elements match your criteria. - Handle Edge Cases: Add checks for
null
or unexpected text formats, as we did with the regex match. - Debugging: Log the
innerText
or use Playwright's tracing to inspect the locator's behavior.
Conclusion
Playwright's locator filtering by text content is a powerful tool for tackling elements without unique identifiers. By combining getByText
and filter
, we successfully extracted the number of refrigerators from the American Freight page. This approach is versatile and can be adapted to many scenarios in web automation.
Try it out in your next Playwright project, and explore other filtering options like has
or hasNotText
to handle even more complex cases!