Automation made easy for Web Components #shadow-roots

Automate Shadow DOM with WebDriver & Playwright

Locate elements in Shadow DOM of Web Components directly through CSS query engine.

This document shows how to use the simpler CSS/xPaths that calls through document.querySelector to locate elements within #shadow-root of your Web Components or Salesforce LWC Applications. This solution can be extended to LitElements, Lighting Fast Templates etc.

The wish is to locate your #shadow-root elements directly through CSS query engine (whic you cannot do it with current WebDriver implementation) e.g,

https://medium.com/media/688072c871ac827da34895057bf6731f/href

🔎 If you’re building your app with the Web Components or Salesforce’s LWC, and if you try to use document.querySelector (in the console), it will not find anything in the document though you see the element in the Browser DOM. The reason is that the elements of Web Component are not in the Main DOM but rather in the Shadow DOM.

“The Shadow DOM shield becomes the pain for developers in writing integration/component/E2E automated tests for Web Components.”

⚠️ THE PROBLEM

Shadow DOM prevents your components from easily being e2e tested because normal Selenium commands fail, due to the element actually not being in the main document. Rather, they are encapsulated under Shadow DOM.

Selenium uses querySelector to find an element; Shadow DOMs prevent this.

The selector engines like css/xpath do not work on the shadow DOM by default.

Example

Let’s take a look at chrome://download page. It implements the Shadow DOM. As you see, the #searchInput is a scoped element under #shadow-root (open), and so the document.querySelector command fails to locate the #searchInput element,

The below query fails to return the element because #searchInput is encapsulated under Shadow Dom,

https://medium.com/media/1ff87622bc29dfc8144da9648c48c0bb/href

and as a result the below Selenium WebDriver Command will also fail to find an element ❎

https://medium.com/media/af4785ce5cb48633e734444fbcfac807/href

So what is needed is a very complex nested CSS [not recommended]

https://medium.com/media/96b5abde6d915960e9f8180b727f50f6/href

🤔 now imagine, you add one more element in the nested route. Then, you are unknowingly breaking the automation tests. You will need to track and update all the existing nested CSS — which is a pain!!

Can I get the support from WebDriver?

Yes. Codeceptjs-BDD Framework provides out-of-the-box support to locate Shadow DOM elements at ease. Though, there is an existing feature request to have the support in W3C/Webdriver, but thru Codeceptjs-BDD Framework, you can locate elements like, document.query,

I.click('.any-shadow-elements-in-dom'); // no dom hierarchy

[..] most end-to-end testing frameworks rely on [..] calls to querySelector through CSS/xPaths. Elements in Shadow DOM are selectable by neither. But, we have a Solution at framework level.

🚀 THE SOLUTION

The solution is Codeceptjs-BDD Webdriver implementations 🎉 🎉 🎉, which provides automatic support for the Shadow DOM , and Playwright already has in-built support.

Let’s talk about the real scenarios built with framework CodeceptJS!

salesforce/codeceptjs-bdd

Example: As you see in line #6 in below gif, the CSS is pretty simplified in test.

✅ As you see in a below example, you would just define a very simple CSS #searchInput . The Playwright driver will find an element(s) for you. No need to mention about any of the hierachy of #shadow-roots!

🙌 No Nested/Complex CSS required!

https://medium.com/media/3f3eeeb821abf23a84d6614f87725159/href

Simply inspect the element in DOM, and grab the unique attribute. It is as simple as that with Playwright because Playwright does rest of the plumbing work for us.

❣️ WebDriver Exclusive Support for Shadow Dom 

salesforce/codeceptjs-bdd

✅ The Framework Documentations: https://gkushang.github.io/

Demo Time

Let’s take a look some real examples with scenarios

The examples in this doc are built with Codeceptjs-BDD framework with Playwright!

A Complete Example Test

As you see in above example, the #searchInput is a scoped element (#shadow-root) but it does not require you to have nested CSS of #shadowRootsto locate the element but it still finds an element!

Salesforce’s LWC Page Object, the Another Example

The Salesforce Lighting Web Components (LWC) is another great example of Shadow DOM elements. LWC Recipes is build with LWC. Below is the Page Object on how to query Shadow DOM elements with simple CSS.

A complete E2E automation Example of Salesforce’s Lighting Web Components Application is available here:

salesforce/codeceptjs-bdd

🎉 The Codeceptjs-BDD makes it easy to Automate Web Components in any of the below mentioned automation test layers:

  • Component Tests
  • Integration Tests
  • Functional Tests
  • E2E Tests

⭐️ Don’t forget to checkout more docs on Codeceptjs-BDD framework WebSite and the CodeceptJS library for great additional features🌈!

Thanks for reading, I hope you discovered something new and useful. Stay curious, and happy coding!


Automation made easy for Web Components #shadow-roots was originally published in Salesforce Engineering on Medium, where people are continuing the conversation by highlighting and responding to this story.

Published
Categorized as Technology