Playwright’s Playbook: Conquering ShadowDOM Elements with Ease

Rajat
helpshift-engineering
7 min readJun 20, 2023

In the ever-evolving world of web development, ensuring that your website or application works seamlessly across different browsers and platforms is crucial. In this fast-paced digital landscape, ShadowDOM has emerged as a powerful tool for encapsulating and isolating components, providing developers with enhanced control over their web applications.

However, when it comes to automating interactions within the ShadowDOM, it can often be a daunting task. So let’s explore the significance of ShadowDOM, understand its unique challenges, and dive deep into the capabilities of Playwright that make automating ShadowDOM a breeze.

What is a Shadow DOM?

Before we delve into the automation aspect, let’s grasp some fundamentals. Shadow DOM is one of the implementations of the OOPS principle of Encapsulation in an HTML document or DOM. It is a web standard that allows encapsulation of HTML, CSS, and JavaScript code within a specific element on a webpage, creating an isolated and scoped subtree of the DOM.

In traditional web development, CSS styles and JavaScript code can easily affect and modify elements throughout the entire document, leading to potential conflicts and unintended consequences. Shadow DOM addresses this issue by providing a way to create a boundary around a specific element and its descendants, isolating them from the rest of the document.

By utilizing Shadow DOM, web developers can create reusable components that encapsulate their own HTML structure, CSS styles, and JavaScript behavior, without worrying about conflicting with or being affected by other parts of the webpage.

But, How does ShadowDOM impact Automation Testing?

While ShadowDOM brings many benefits to web development, it presents unique challenges when it comes to automation. Traditional automation frameworks often struggle to interact with elements residing within ShadowDOM boundaries. Locating, inspecting, and manipulating these encapsulated elements requires a different approach.

Here are a few key points to consider while interacting with and validating the contents of shadow DOM elements:

1. Element Identification: Shadow DOM encapsulates its elements, making them hidden from the main DOM tree. Automation frameworks need to have specific methods or techniques to locate and interact with shadow DOM elements. This may involve using specialized selectors or functions that can traverse the shadow DOM boundary.

2. Accessing Shadow DOM: Automation tools may provide specific APIs or methods to access the shadow DOM content. For example, Playwright offers the `shadowRoot()` method, which allows you to obtain the root element of the shadow DOM subtree. Once you have access to the shadow root, you can interact with its elements using regular DOM manipulation methods.

3. Handling Encapsulation: Shadow DOM’s encapsulation ensures that styles and behavior within a shadow DOM subtree do not affect or get affected by external styles or scripts. When automating tests, it’s important to consider the encapsulation boundaries and ensure that interactions with shadow DOM elements are performed within their intended context.

4. Validation and Assertions: Verification and assertion of shadow DOM elements may require specific techniques. For example, you might need to validate the contents of shadow DOM elements by accessing their properties or attributes through specific methods provided by the automation framework.

In short, automation testing with Shadow DOM requires understanding the unique characteristics of shadow DOM elements and utilizing the features and APIs provided by automation frameworks to interact with and validate them accurately.

Now, how do we solve this?

Enter Playwright, the versatile automation library, which empowers testers to effortlessly navigate and manipulate the ShadowDOM with ease. Playwright is able to access elements in the open shadow DOM. Playwright’s css and text locators pierce shadow DOM by default, which mean, you do not need explicit JS code to access the shadow DOM, which is in the case of Selenium. One thing to note here is that Xpaths do not pierce shadow DOM.

Another important thing to remember is that both Playwright and Selenium cannot access the elements inside the closed shadow DOM.

Let’s delve deeper into the common scenarios which deal with interacting with the elements inside a ShadowDOM.
We’ll be using SelectorsHub Practice page as the AUT since it has all of the complex scenarios we are looking for.

Scenario 1 : Element inside an open Shadow Root

This is a very common scenario where the element is directly under a ShadowDOM on a page. Let’s consider the input box with the label UserName and placeholder text enter name on the SelectorsHub practise page, as shown in the image below.

Page — DOM → ShadowDOM → elements

As we know Playwright css engine pierces the shadowDOM by default, so to input value to the placeholder:

  • We will write css selector of the div tag for where the parent shadow root of the input tag starts (shown in the image above), which is: #userName.
  • The css selector of the parent shadow root will be followed by css selector of its child input field, which is: #kils.

So the resulting code to enter text to the input field would be:

After running the code, we see that the code runs successfully and the element receives the text input.

Scenario 2: Element inside multiple open Shadow Roots (Nested Shadow Roots)

We can also encounter case where there are nested shadow roots — which means, one shadow root is inside of another shadow root. In that case too, Playwright can easily pierce the inner shadow DOM and get to the elements.

Let’s consider the input box with the label UserName and placeholder text Enter pizza name on the SelectorsHub practise page, as shown in the image below.

Page — DOM → ShadowDOM → ShadowDOM → elements

As we know Playwright css engine easily pierce through the shadowDOM, we’ll follow the same approach as above:

  • We will write css selector of the div tag for where the parent shadow root of the input tag starts (shown in the image above), which is: #userName.
  • It will be followed by css selector of the child input field which is inside another shadow root, which is: #pizza.

So the resulting code to enter text to the input field would be:

We see that the code runs like a charm and the element receives the text input.

Scenario 3: Element inside an iFrame inside an open Shadow Root

While working with the enterprise products, we encounter many complex scenarios where many automation frameworks fail to work.

Another such scenario is where the element is inside an iframe, which is further embedded inside an open shadow root. Let’s consider the input box with the label Snacks and placeholder text Do you love tea on the SelectorsHub practise page for shadowDOM in iFrames, as shown in the image below.

Page — DOM → iFrame → ShadowDOM → elements

How to handle this scenario, Let’s find out!!

If we try to access elements inside an iframe → inside a shadow root, just like we did in the previous scenario, the code will throw an error. By default, Playwright css engine will pierce the shadow root DOM but will not search elements inside iframe or closed root.

To get the element inside the iframe:

  • We will first have to go to the iframe and then search element inside the iframe. So, we’ll use the framelocator method to get to the iframe with id pact.
  • Then using the css selector of the parent shadowRoot (#snacktime ), traverse to its child input field (#tea) and then fill it with required text – and voila, the code works !!

The resulting code would be:

Scenario 4: Element inside a closed Shadow Root

Until now, we have covered the scenarios where Playwright can directly or indirectly pierce the shadow root, since it is an open state shadow DOM.

Now, if the element is inside a closed shadow DOM, playwright css engine will not be able to search it. Let’s consider the input box with the label Password and placeholder text enter passwordon the SelectorsHub practise page, as shown in the image below.

Page — DOM → ShadowDOM (closed) → element

Following the approach as in Scenario-1, the resulting code would be:

Since Playwright engine cannot access the element, page.locator methods are of no use here. The required element would not be found and the code will throw an error.

Hence, we cannot automate scenarios related to closed shadow root using Playwright.

Conclusion

As web development continues to evolve, the importance of robust and efficient web automation becomes increasingly apparent. Now that we have covered the complex scenarios w.r.t Shadow DOM and their handling using Playwright, I hope you’re feeling empowered and ready to tackle more such complexities in automation.

By leveraging Playwright’s rich features and capabilities, developers and QA engineers can confidently tackle the challenges posed by modern web applications.

So, go ahead, embrace the power of Playwright, and automate the unautomatable!

--

--