Query Languages That Can Handle ShadowDOM
Query Languages That Can Handle ShadowDOM
XDomPath, an open source tool for querying ShadowDOM.
Join the DZone community and get the full member experience.Join For Free
XPath is a query language that is widely used by developers and QA automation engineers. Very often, XPath becomes the main engine for querying DOM nodes inside Selenium projects. Its ability to walk up or down to apply different filters and functions makes it a solid choice.
What Has Changed?
UIs are becoming increasingly more complicated. This can make for a real headache for developers who have to design their applications to be easily supportable and scalable.
Web components technologyis pretty new, but it already has made noise in industry. It gives developers the ability to create native, reusable HTML elements that can be plugged in declaratively. One of the most important technology of web components is ShadowDOM.
ShadowDOM is a new feature of DOM API that provides the ability to encapsulate your DOM subtree. As result, you can design your new, reusable HTML elements that can have their own isolated DOM with isolated styles.
DOM With ShadowDOM
Let’s take a look at the simple example with ShadowDOM:
Hmm, doesn't it look a bit different from the clear XML? A shadow root is like a new root of another DOM subtree? In this case, we see that the DOM tree is not a clear XML anymore.
XPath and ShadowDOM
ShadowDOM breaks the XML structure of a DOM. How do you access scoped Shadow tree nodes via XPath? What if I want to just find some input element with some particular class without sticking to the shadow subtree deepness?
Let’s try if we can find a span inside of ShadowDOM:
Ouch! It seems like XPath cannot search deeply through the ShadowDOM. Is it suitable for the same tasks as before? If we need to work with our DOM as one global document of elements without caring about ShadowDOM deepness, we need an ability to query as before.
You can ask — is it safe? ShadowDOM was created for security reasons, and we are going to reduce its encapsulation and use it as before. For automation purposes it is fine, since the main goal is to find element (not to modify or remove). It can also suit developers' needs, but only in some specific cases; it shouldn’t be the main pattern of querying nodes in runtime code, but the idea should be the same — use it only to find elements.
What query languages do we have for a DOM tree? Specific only for DOM tree. Not sure if we can name something more than just CSS. Is CSS bad? No, but Xpath is much more powerful, and it will be very useful if we can continue to use these features in the future.
This was my main purpose for creating a new DOM query Xpath-based language — XDomPath.
You can read more technical details about setup and installation on my GitHub.
XDomPath XML Model
XDomPath tries to treat DOM with ShadowDOM as simple XML (screenshot below).
So algorithm of mapping DOM to XML looks like this:
- ShadowRoot node is always the first child of its host.
- ShadowRoot’s host is its direct parent.
- Slotted elements are direct children of the host (not slot child elements).
- All other nodes relationships are not impacted.
Let’s Try a Few Queries
Example 1. Simple deep searching XDomPath query “.//div”
We see that XDomPath doesn’t require us to move deeply inside of a particular ShadowDOM scope manually. With the following algorithm above we will process the shadow root element as children of the div (first and second) container.
Example 2. Searching for shadow roots. XDomPath query “.//shadow()”
Same as the text() function, we can use new shadow() function, which returns a shadowRoot NodeList.
Example 3. Searching for text nodes. XDomPath query “.//text()[.=’some-text’]”
Example 4. Slotted elements querying.XDomPath query “.//div/text()”
Since slotted elements are treated as direct children of the host element, this query will return a single text node.
Example 5. Ensuring that the element is located under the shadow root. XDomPath query “.//shadow()/p”
Example 6. Finding containers that have a shadow root. XDomPath query “.//div[./shadow()]”
- Basic XDomPath usage:
2. Using new features:
3. Planned feature of defining manual functions:
Selenium WebDriver Java Annotation Support
To add support of XDomPath for Selenium automation Java projects, I’ve created a new annotation FindByQuery which extends regular FindBy with new query option — XDomPath.
You can find it here.
Here is how it can be used inside of Java code-base:
I hope that my solution will help you with testing/developing your web applications. Thanks for reading!
Opinions expressed by DZone contributors are their own.