Shadow DOM
Shadow DOM is a web standard that developers use to encapsulate their html code and style components so that no other style components can override their code. It is a critically important piece of the web components story as it ensures that a component will work in any environment even if other CSS or JavaScript is at play on the page.
Custom HTML Tags
Custom elements provide a way for authors to build their own fully-featured DOM elements and these custom HTML tags can’t be directly identified with selenium tools.
Problem Statement
- You have already developed your web-based automation framework in java selenium. Your frontend application uses Polymer that uses shadow DOM. Selenium doesn’t provide any way to deal with shadow-dom elements.
- Your application page contains custom HTML tags that can’t be identified directly using selenium.
In this article, we will try to solve multi-level Shadow DOM automation problem using an open source GitHub project that will let you test multi-level shadow DOM elements in your java selenium project. We will use Chrome as the main browser for testing this feature as Chrome version 53 or later fully supports shadow DOM.
In one of our projects, a workflow automation tool Frevvo, developers started using the Google Polymer framework that creates Shadow DOM elements. As our automation framework was developed using java selenium, we were stuck as selenium was not able to find any elements under the Shadow DOM.
After some research, we found that the Selenium Javascript executor can help, but the code to achieve this functionality can get complex very quickly, affecting maintainability in the long run.
Finally, we stumbled upon a working solution that can be directly integrated with selenium code and is very easy to use.
This project works by injecting javascript code that interacts with the Shadow DOM and returns us selenium objects that can directly be used in tests.
The Solution
You can use this plugin by adding the jar file or by including a dependency in your java selenium project.
Add the following dependencyMaven
<dependency>
<groupId>io.github.sukgu</groupId>
<artifactId>automation</artifactId>
<version>0.0.1</version>
<dependency>
Gradle
implementation 'io.github.sukgu:automation:0.0.1'
You can also download the jar file from the Maven Central repository and include it in your project
Selectors
For the html tag <paper-tab title=”Settings”> You can use this code in your framework to grab the paper-tab element Object.
import io.github.sukgu.*;
Shadow shadow = new Shadow(driver);
WebElement element = shadow.findElement("paper-tab[title='Settings']");
List<WebElement> element = shadow.findElements("paper-tab[title='Settings']");
String text = element.getText();
for an html tag that resides under a shadow-root dom element <input title=”The name of the employee”> You can use this code in your framework to grab the paper-tab element Object.
import io.github.sukgu.*;
Shadow shadow = new Shadow(driver);
WebElement element = shadow.findElement("input[title='The name of the employee']");
String text = element.getText();
for html tag that resides under a Shadow-root DOM element
<properties-page id="settingsPage">
<textarea id="textarea">
</properties-page>
You can use this code in your framework to grab the textarea element Object.
import io.github.sukgu.*;
Shadow shadow = new Shadow(driver);
WebElement element = shadow.findElement("properties-page#settingsPage>textarea#textarea");
String text = element.getText();
This plugin supports upto 3 levels of shadow-dom elements. The plugin is available as an open source project on GitHub, you can fork and make changes as per your requirements.
References
GitHub: //github.com/sukgu/shadow-automation-selenium
Shadow DOM: //www.w3.org/TR/shadow-dom/
Selenium: //www.seleniumhq.org/