Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Query Languages That Can Handle ShadowDOM

DZone 's Guide to

Query Languages That Can Handle ShadowDOM

XDomPath, an open source tool for querying ShadowDOM.

· Web Dev Zone ·
Free Resource

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:

ShadowDOM example
ShadowDOM example


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:

Finding a span inside of ShadowDOM
Finding 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.

XDomPath Language

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).

XDomPath for DOM with ShadowDOM
XDomPath for DOM with ShadowDOM


So algorithm of mapping DOM to XML looks like this:

  1. ShadowRoot node is always the first child of its host.
  2. ShadowRoot’s host is its direct parent.
  3. Slotted elements are direct children of the host (not slot child elements).
  4. All other nodes relationships are not impacted.

Let’s Try a Few Queries

Example 1. Simple deep searching XDomPath query “.//div”

Deep searching XDOMPath query
Deep searching XDomPath query


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()”

Searching for shadow roots
Searching for shadow roots


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’]”

Searching for text nodes
Searching for text nodes


Example 4.
Slotted elements querying.XDomPath query “.//div/text()”

Slotted elements querying
Slotted elements querying


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”

Ensuring an element is under the shadow root
Ensuring an element is under the shadow root


Example 6.
Finding containers that have a shadow root. XDomPath query “.//div[./shadow()]”

Searching for a shadow root
Searching for a shadow root


Programming API

XDomPath is a Javascript library that is available as an npm dependency. Below is an example of including XDomPath into a code-base.

  1. Basic XDomPath usage:
Including XDomPath into a code-base
Including XDomPath into a codebase


2. Using new features:

Using new features
Using new features


3. Planned feature of defining manual functions:

Planned feature of manual functions
Planned feature of 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:

XDomPath in Java code-base
XDomPath in Java codebase

Conclusion

I hope that my solution will help you with testing/developing your web applications. Thanks for reading!

Topics:
automation testing ,web developement ,xpath in selenium webdriver ,shadow dom ,tutorial ,xdompath

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}