App & Browser Testing Made Easy

Give your users a seamless experience by testing on 3000+ real devices and browsers. Don't compromise with emulators and simulators

Get Started free
Home Guide Demystifying Playwright Selectors: A Step-by-Step Guide

Demystifying Playwright Selectors: A Step-by-Step Guide

By Hamid Akhtar, Community Contributor -

Playwright Selectors act as a GPS for web automation and testing, providing developers with precise coordinates to find and interact with specific elements in a webpage’s complex structure. Let’s say you’re an architect working on a large building (the webpage). Each component – windows, doors, or pillars – signifies different web elements like text boxes, buttons, or images. 

Playwright Selectors serve as your blueprint, helping you locate and manipulate these components to ensure the building stands strong and functions well. For instance, in testing an e-learning portal, Playwright Selectors would help you locate the login fields, input credentials, and click the ‘login’ button, simulating a real user experience. 

What are Playwright Selectors

Playwright Selectors, represented as strings, serve as a guidebook to create Locators, which describe how to find specific elements on a webpage. They encompass an array of techniques, such as Text Selectors, CSS Selectors, XPath Selectors, React Selectors, and more.

To provide a simpler analogy, imagine you’re playing a game of “I Spy” on a complex, detailed picture – the webpage. The Playwright Selectors are like your clues to find specific items – or in this case, web elements like text boxes, buttons, or images. By using these “clues”, developers can perform tasks or tests on those elements, ensuring the webpage works as expected.

Different Types of Playwright Selectors

Here are some examples that help illustrate these different selector techniques:

  • Basic text selectors: This allows you to select an element via its text content.
const submitButton = await page.locator('text="Submit"');
  • Basic CSS selectors: These are used to select elements based on their CSS properties.
const passwordField = await page.locator('input[type=password]');
  • Selecting visible elements: This is useful for selecting elements that are visible on the page.
const visibleDivs = await page.locator('div:visible');
  • Selecting elements that contain other elements: Playwright enables selection of parent elements based on child elements.
const parentDiv = await page.locator('div >> "child text"');
  • Selecting elements in Shadow DOM: Shadow DOM elements can also be selected using Playwright.
const shadowElement = await page.locator('css=div#shadow-root >> css=span');
  • Chained selectors: These are used when one selector needs to run relative to the previous one.
const chainedElement = await page.locator('div.parent >> css=span.child');

Additionally, Playwright supports custom selector engines. This means you can define your own way of querying elements, for instance, based on a tag name.

Playwright-specific selectors, including text selectors and chained selectors, fill in the gaps where CSS and XPath selectors might fall short. They provide an even more powerful way to accurately locate and interact with elements on a webpage.

CSS Selectors in Playwright

With Playwright, developers can leverage CSS selectors to locate and interact with web elements:

  • Element Selector: Selects elements based on the tag name. Example, the below command selects all paragraph elements.
await page.locator('p'); 
  • Class Selector: Selects elements based on the class name. Example, the below command selects all elements with the class myClass.
await page.locator('.myClass');
  • ID Selector: Selects an element based on its ID. Example, select the element with the ID myID using the command
 await page.locator('#myID'); 
  • Attribute Selector: Selects elements based on an attribute and its value. Example, the below command selects all text input elements.
await page.locator('input[type="text"]');
  • Combining Selectors: Combines different selectors for precision. Example, the below command selects a button with class myClass and text “Submit“.
await page.locator('button.myClass:has-text("Submit")');
  • Visible Pseudo-class: Selects elements that are visible on the page. Example, the below command selects all visible div elements.
await page.locator('div:visible');
  • Has Pseudo-class: Selects elements that contain specific other elements. Example, the below command  selects div elements containing elements with class childClass.
await page.locator('div:has(.childClass)'); 
  • Not Pseudo-class: Selects elements that do not match a condition. Example, the below command selects div elements that do not have class excludeClass.
await page.locator('div:not(.excludeClass)'); 
  • FirstChild Pseudo-class: Selects the first child element. Example, the below command selects the first child div element.
await page.locator('div:first-child');
  • LastChild Pseudo-class: Selects the last child element. Example, the below command selects the last child div element.
await page.locator('div:last-child'); 
  • Shadow DOM Selector: Selects elements in the Shadow DOM. Example, the below command selects span elements inside a div with ID shadow-root.
await page.locator('div#shadow-root >> css=span'); 
  • Chained Selectors: Chains selectors for relative search. Example, the below command selects span with class child inside a div with class parent.
await page.locator('div.parent >> css=span.child');
  • CSS Equals: Specifies a CSS selector. Example, the below command selects div elements with class myClass.
await page.locator('css=div.myClass');
  • Visible Pseudo-class with Text: Selects visible elements with specific text. Example, the below command selects visible paragraph elements with the text “Hello“.
await page.locator('p:visible:has-text("Hello")');
  • Nth-match Pseudo-class: Selects the nth matching element. Example, the below command selects the second div with class myClass.
await page.locator('div:nth-match(2, .myClass)');
  • Playwright-specific selector: Playwright selectors provide additional functionality. Example, the below command selects a React component named MyComponent.
await page.locator('_react=MyComponent');
  • Has-text Pseudo-class: Selects elements containing specific text. Example the beloc command, selects paragraph elements containing the text “Hello“.
await page.locator('p:has-text("Hello")');
  • Is Pseudo-class: Matches an element if it matches any of the selectors. Example, the below command, selects paragraph elements that have either class1 or class2.
await page.locator('p:is(.class1, .class2)');
  • XPath Selector: Used to select elements using XPath expressions. Example the below command selects div elements with class myClass.
await page.locator('//div[@class="myClass"]'); 
  • Custom Selector Engine: Allows you to define your own selector engine. Example: Define a custom selector to select elements based on a specific data attribute:
// Define your custom selector engine
playwright.selectors.register('data-testid', {
create(root, target) {
return root.querySelector(`[data-testid="${target}"]`);
},
});
// Use your custom selector
await page.locator('data-testid=myTestId');

This example creates a custom selector engine to select elements based on a data-testid attribute and uses it to select an element with data-testid=”myTestId”.

Xpath Selectors in Playwright

In Playwright, XPath selectors offer a flexible way to pinpoint elements on a webpage, beyond just their tag, class, or ID. They allow developers to navigate through the webpage structure and select elements based on a range of conditions.

  • Tag Selector: You can select all elements of a particular type. For example, you can select all paragraph elements using
//p
  • Attribute Selector: XPath selectors can find elements with a specific attribute. For example, you can find all div elements with the class myClass.
//div[@class="myClass"]
  • Text Content Selector: XPath can select elements based on their inner text. So, You can find paragraph elements that contain exactly the text Hello using
//p[text()="Hello"]
  • Substring Selector: XPath’s contains() function can select elements whose text includes a certain substring. For example, you can find paragraph elements that contain “Hello” anywhere in their text using
 //p[contains(text(), "Hello")]
  • Sibling Selector: Using XPath, you can find elements in relation to others. For instance, you can  select all div elements that directly follow another div using 
//div/following-sibling::div
  • Position Selector: XPath allows selecting elements based on their order in the webpage. For instance, you can select the first div element on the page using
//div[1]

In short, XPath selectors provide a versatile toolkit to navigate and select elements on a webpage when using Playwright, often proving handy when CSS selectors might not be enough.

How to create Locators in Playwright

In Playwright, locators are like labels we put on web page elements to interact with them. Imagine if you could put a sticker on a button on a webpage, and then tell Playwright, “Click on the button with this sticker.” That’s what a locator does, but with code instead of stickers.

You create a locator using the page.locator() function. You pass a selector into this function, which can be a description based on the element’s tag, class, or other attributes. Here’s an example:

const button = page.locator('button.myButton');

In this example, we’re telling Playwright to find a button with the class myButton and label it as button.

Once you have a locator, you can ask the Playwright to perform actions with it. For example, you can tell Playwright to click the button like this:

await button.click();

This is like saying, “Playwright, click on the element I labeled as ‘button’.”

If you want to know how many elements match the locator, you can ask Playwright to count them:

const numberOfButtons = await button.count();

This is like saying, “Playwright, how many ‘button’ labels did you find?”

You can even create new locators based on existing ones. This is like adding another sticker to the ones already there:

const smallButton = button.locator('.small');

This is like saying, “Playwright, among the elements labeled button, find those with the class small and label them smallButton.”

In short, locators are a simple and powerful way to interact with web page elements in Playwright.

Know more about Playwright Capabilities

Best Practices for using Playwright Selectors 

When using playwright selectors best practices, it’s kind of like you’re setting up directions for Playwright to find its way around a webpage. So, here are a few tips to keep in mind:

  1. Avoid overly specific selectors: Imagine you’re guiding a friend to your house, but you give super specific instructions like, “Take a left turn where that red 1995 Honda Civic is parked.” That car might not be there tomorrow, right? Similarly, avoid using selectors that rely too heavily on a specific structure or attribute values that may change.
  2. Be mindful of dynamic content: If parts of the page change often, like ads or timestamps, make sure not to tie your selectors to those. It would be like telling your friend to turn at the McDonald’s that’s no longer there!
  3. Prioritize user-visible attributes: It’s much easier to find a house if you know it’s the blue one with the big oak tree out front, right? Similarly, it’s easier to maintain tests if your selectors are based on text or other attributes that you can see when you look at the page, rather than hidden attributes.
  4. Use selector chaining: This is like saying, “Go to the house at the end of the street, then the third room on the left.” In Playwright, you can start with a broad locator and then chain more specific ones onto it. This makes your code easier to read and your selectors more robust.
  5. Use waitForSelector cautiously: When navigating, it’s good to wait for a landmark to show up before proceeding. But in Playwright, be cautious about using waitForSelector for every single action – it might slow your tests down a lot. Instead, use waitForLoadState after actions that cause navigation.
  6. Avoid using indexes: If you tell your friend to “take a right at the third traffic light,” what happens if a new light gets added? In Playwright, avoid using indexes in selectors because the order of elements can change.

And remember, just like with directions, it’s all about making things easy to understand and follow, both for Playwright and for anyone else reading your code! 

Closing Notes

Navigating through a website with Playwright selectors is akin to exploring a city with a map crafted by expert cartographers like Google Maps. Every street, every landmark, every turn holds importance for reaching your destination smoothly. Similarly, each Playwright selector helps to efficiently find, interact, and test web elements. Imagine, without a well-defined map, even Google Maps could find itself in uncharted territories. 

Likewise, without well-designed selectors, your automation scripts could hit unexpected roadblocks. So, use these practices, ensure your automation journey is as smooth as a well-planned road trip. Remember, the better the map (selectors), the more enjoyable and productive the journey (coding).

BrowserStack provides a comprehensive suite of testing tools including BrowserStack Automate, Live, App Live, and Percy, all seamlessly integrated with Playwright. These platforms empower you to perform real-time interactive testing, automated browser tests, visual testing and more, ensuring top-notch quality for your applications. 

Try BrowserStack for Free

Tags
Automation Testing Mobile Testing

Featured Articles

Page Object Model with Playwright: Tutorial

Playwright Automation Framework: Tutorial

App & Browser Testing Made Easy

Seamlessly test across 20,000+ real devices with BrowserStack