How to Handle Shadow DOM in Cypress

Kailash Pathak

Posted On: November 30, 2023

view count261812 Views

Read time18 Min Read

The concept of componentization has revolutionized website development, completely transforming how they are built. At the heart of this revolutionary shift is the introduction of Shadow DOM, a key component in this paradigm change. With Shadow DOM’s powerful method, developers can isolate styles, scripts, and markup within specific components. This encapsulation is a barrier, effectively shielding these components from the broader scope and avoiding accidental interference. The introduction of Shadow DOM marks a significant advancement in web development practices.

Developers may design modular and isolated components using Shadow DOM, guaranteeing their independence from the global scope. In addition to improving security, this separation makes maintenance easier and enables developers to concentrate on specific components without worrying about other variables interfering with their operation.

When it comes to automating elements within the Shadow DOM, it can be quite challenging compared to elements in the regular DOM. However, Cypress provides a solution for automating elements under the Shadow DOM.

In this blog, we will explore the complication of automating Shadow DOM in Cypress, a powerful end-to-end testing framework.

What is a Document Object Model (DOM)?

The Document Object Model (DOM) is fundamentally a programming interface that web developers are given access to by browsers. It displays the document’s structure as a tree of objects, each representing a different aspect of the document, such as its components, attributes, and textual content. When it comes to web pages, developers can dynamically interact with them, altering their appearance and functionality in real-time. This is made possible by the hierarchical structure of web pages.

DOM serves as a fundamental interface for programs to dynamically manipulate the structure, style, and content of documents on the web. It empowers developers to create, read, update, and delete elements and attributes within a web page, enabling interactivity and dynamism. This dynamic capability of the DOM is crucial for crafting interactive web applications. By harnessing programming languages such as JavaScript, developers can access and modify the DOM, allowing them to build responsive and interactive web applications with unparalleled flexibility and power.

  • Document: The web page you see in your browser is a document. When a web page is loaded, the browser creates a DOM of the page.
  • Object: In the context of the DOM, an “Object” represents every element and component of a web page. These objects include paragraphs, headings, images, buttons, forms, etc. Each of these objects can be manipulated using code.
  • Model: The DOM represents the document so that programs can change its structure, style, and content while in the browser. It provides a way for programs to manipulate the structure, style, and content of web documents.

Model

In the DOM, every branch within the tree structure leads to a node, which is a fundamental unit. These nodes are pivotal elements in the DOM, encapsulating various objects and data.

Each node represents a distinct document part, such as elements, attributes, and text content. This hierarchical arrangement allows web browsers to interpret and manipulate pages, enabling dynamic content and interactive user experiences.

Let us take an example of an HTML page. In this example, the HTML document contains a head section with a title element, setting the page title to “A simple web page”. The body section contains a heading element (< h1 >) with the text “Hello LambdaTest” and a paragraph element (< p >) with the text “How are you LambdaTest”. This HTML code would display a webpage with the specified content when rendered in a web browser.

As mentioned above, a logical tree of this HTML structure would look like this.

HTML structure

What is a Shadow DOM?

Shadow DOM stands for Shadow Document Object Model. It’s a web standard that offers a scoped subtree within a document, meaning that the DOM elements inside a Shadow DOM are hidden from the main document (& vice-versa). This encapsulation helps developers create widgets (or other components) with encapsulated styles and behaviors without worrying about conflicts with the styles or scripts of the main document (or other components).

It is particularly useful in web development when developers have to create isolated components with their styles and behavior, preventing conflicts with the styles and scripts of the main document or other components on the same page.

Shadow DOM enables the creation of multiple shadow trees alongside the standard document tree, representing the DOM structure of the entire project. Each tree possesses a root node, known as the shadow root, housing its unique elements and styling. These trees are linked to specific elements within the parent document tree or other shadow trees, with these connecting nodes referred to as shadow hosts. The demarcation line separating the regular DOM and the Shadow DOM is termed the shadow boundary.

shadow boundary

Here are some of the key components of Shadow DOM:

  • Shadow Host
  • The regular DOM element to which a Shadow DOM is attached is the Shadow Host. It’s the element where the Shadow DOM is attached, effectively encapsulating the elements inside it.

  • Shadow Tree
  • Inside the Shadow DOM, there is a Shadow Tree. This tree comprises the encapsulated DOM elements and their associated styles and behavior.

  • Shadow Root
  • The shadow root is the root node of the shadow tree. It is a gateway between the Shadow DOM and the main document’s DOM.

  • Shadow Boundary
  • At this point, we transition from the Shadow DOM to the familiar territory of the regular DOM. Elements inside the Shadow DOM can’t be accessed or styled from outside the Shadow DOM unless specific mechanisms are provided.

Benefits of Shadow DOM

Shadow DOM offers several benefits in web development. Here are some key benefits:

  • Encapsulation
  • Protects DOM and styles from outside styles and scripts, preventing conflict. It also prevents styles and scripts from the outer document from leaking into the components, causing unintended styles and behavior.

  • Isolation
  • Gives styles and scripts limited scope, avoiding clashes with global styles and scripts, as globally applied CSS and JavaScript may cause name conflicts and unwanted side effects.

  • Reusability
  • Enables the creation of self-contained, reusable components that can be safely inserted into other web application components without worrying about style inconsistencies.

  • Simplified Styling
  • Makes style easier by letting you create CSS for a single component without worrying about how it will affect the rest of the document, as traditional styling might require complex selectors to avoid conflicts.

Let’s explore an example that demonstrates the process of attaching Shadow DOM to HTML and how it helps encapsulate the structure and styles of HTML.

Consider a simple example where you want to create a custom button component encapsulated within Shadow DOM:

In this example, we define a custom button component (< my-button >) that encapsulates its HTML structure and styles using Shadow DOM. The button’s appearance and behavior are isolated from the rest of the page, making it a self-contained component that can be used without interfering with the global CSS or JavaScript.

Here’s a breakdown of the code:

  1. The HTML document defines a < my-button > custom element inside the .
  2. In the < script > block, a new custom element, MyButton is created by extending the HTMLElement class. The constructor of MyButton sets up the Shadow DOM and creates a button element inside it.
  3. Inside the Shadow DOM, a button element is created and styled with a blue background, white text, padding, no border, and a pointer cursor.
  4. The custom element is defined using customElements.define (‘ my-button ‘, MyButton);, associating the custom element tag name < my-button > with the MyButton class.

Output:

The ‘Hi 👋 Click On Me’ button is inside the Shadow DOM.

 inside the Shadow

Before delving into how to handle Shadow DOM elements using Cypress, it’s crucial to understand how to access these elements. The upcoming explanation will illuminate these challenges and solutions for effective Shadow DOM element handling in Cypress.

How to Access Shadow DOM Elements?

Before discussing how we can handle Shadow DOM in Cypress, we must discuss what will happen if a user tries to access Shadow DOM elements without using the method that is provided by Cypress to handle these elements.

Let’s examine the consequences of attempting to directly access Shadow DOM in Cypress, with detailed examples below.

Use Case 1

Let’s take an example of the LambdaTest Playground, where we have to enter data in the Name and Email field.

  1. Open the site https://www.lambdatest.com/selenium-playground/shadow-dom.
  2. Enter data in the Name field.
  3. Enter data in the Email field.

Let’s inspect the fields Name and Email. The screenshot below shows the Name and Email fields inside the shadow DOM.

Name and Email



Email text field

Let’s write Cypress code to enter data in the Name and Email text field and execute the code locally.

Upon running the code, the error "Expected to find element: #input, but never found it. Queried from:" appears in the command log below. The error occurs because the fields are within Shadow DOM.

Use

Use case

Use Case 2

Let’s take another example of the LambdaTest Playground, where we enter data in Sign Up Form fields inside the shadow DOM.

  1. Open the site https://www.lambdatest.com/selenium-playground/shadow-dom.
  2. Enter data in the Username Field.
  3. Enter data in the Email Field.
  4. Enter data in the Password Field.
  5. Enter data in the Confirm Password Field.

Let’s inspect the field. In the screenshot below, you can see that the Username and other fields are inside the shadow DOM

screenshot below

Let’s write Cypress code to enter data in the Username, Email, Password, and Confirm Password text fields.

Let’s run the above code. The screenshot below shows that the error displays Timed out retrying after 4000ms: Expected to find element: [name=”username”], but never found it. The reason is that fields are inside the Shadow DOM.

Expected to find element

Before explaining how we can solve the above issue, it’s mandatory to understand the method we can use to access Shadow DOM elements.

Methods for Handling Shadow DOM

Below is the syntax to access the Shadow element. Let’s see the methods that are used in accessing the element that is inside the Shadow DOM with detail example

Syntax:

Example:

Cypress provides a way to traverse into the Shadow DOM of an element for testing purposes. To interact with elements inside the Shadow DOM in Cypress, you can use the .shadow() command.

Assuming you have an element with an ID of ‘my-element’ inside a Shadow DOM:

To traverse into the Shadow DOM and interact with the element with class content, you can use the .shadow() command in your Cypress test.

In this example, cy.get(‘my-element’).shadow() is used to traverse into the Shadow DOM of the my-element and find the element with class content inside the Shadow DOM in Cypress.

In the next section, you will see how we can handle the elements inside Shadow DOM in Cypress using the above-mentioned methods.

Handling Shadow DOM in Cypress

So far, you have seen an issue accessing the elements under the Shadow DOM. In Cypress, there are various methods to access Shadow DOM elements. The upcoming section will elaborate on these methods, providing a comprehensive understanding of how to interact with Shadow DOM elements effectively.

Below, you will see different ways to handle Shadow DOM in Cypress.

Using the .shadow() method

Let’s take the same example and use the shadow() command to enter data in the Name and Email field.

  1. Open the site https://www.lambdatest.com/selenium-playground/shadow-dom.
  2. Enter data in the Username Field.
  3. Enter data in the Email Field.
  4. Enter data in the Password Field.
  5. Enter data in the Confirm Password Field.

Code Walkthrough

Here’s what each part does:

describe(“Enter data in Fields Inside Shadow DOM Using shadow() method”, () => { … });:

This sets up a test suite with a description.

beforeEach(() => { … });:

This is a hook that runs before each test case in the suite. In this case, it visits the specified web page before executing every test.

it(“Enter data in all Fields”, () => { … });:

This is an individual test case with the description “Enter data in all Fields”. The test case is responsible for interacting with the elements inside the Shadow DOM and entering data into the specified fields.

cy.get(“shadow-signup-form”).shadow();:

This line uses the cy.get() command to locate the Shadow DOM element with the tag name “shadow-signup-form”.

.shadow().find(‘input[name=”username”]’);:

The .shadow() method is used to interact with elements inside the Shadow DOM, and find(‘input[name=”username”]’) is used to find the input field with the name “username”.

.type(“Kailash”, { force: true });:

The .type() command is then used to simulate typing “Kailash” into this input field.

Similar lines follow for other input fields like Email, Password, and Confirm Password, where data is entered using the .type() command.

To access the input box within the Shadow DOM, we have used the .shadow() method. Once inside the shadow DOM, we can interact with the input box and enter the data in the ‘Username’, ’Email’, ‘Password’, and ‘Confirm Password’ fields.

Confirm Password

Adding a Flag in Config File

The second approach handles the Shadow DOM in Cypress by adding the flag ‘includeShadowDom’ in the configuration file.

Add the flag in the ‘cypress.config.js’ file. In the config file, you can add “includeShadowDom“: true.

The includeShadowDom: true configuration option in Cypress enables interaction with elements inside Shadow DOM. When you set includeShadowDom: true in your Cypress configuration, Cypress will enable support for Shadow DOM and allow you to interact with elements inside Shadow DOM using commands like cy.get() and cy.find().

Let’s write the code. Here, we are not using the .shadow() command.

Adding Flag with Specific Command

The third approach is to handle the Shadow DOM in Cypress by adding the ‘includeShadowDom’ flag within specific commands.

In the third approach, instead of setting the ‘includeShadowDom’ flag globally, a more flexible approach is to include it within specific commands. This allows for finer control, enabling us to specify whether to include Shadow DOM per command.

Info Note
Automate Shadow DOM in Cypress on cloud. Try LambdaTest Today!

How to Automate Shadow DOM on Cloud?

Handling Shadow DOM in Cypress on the cloud is crucial for comprehensive and accurate testing of modern web applications. The increasing trend of web applications utilizing Shadow DOM for encapsulating styles and functionality necessitates robust testing mechanisms.

As cloud testing environments like LambdaTest gain prominence, it becomes imperative to validate that the infrastructure supports the intricacies of Shadow DOM testing. This ensures that applications leveraging Shadow DOM can be thoroughly tested in cloud-based environments, guaranteeing the reliability and functionality of the application in real-world scenarios.

LambdaTest is an AI-based test execution and orchestration platform that offers over 3000 real browsers and operating systems to help you automate Shadow DOM in Cypress on the cloud. You can accelerate your Cypress testing with Java and reduce test execution time by multiple folds by running parallel tests on Cypress Cloud across multiple browsers and OS configurations.

Subscribe to the LambdaTest YouTube Channel and stay updated with the latest tutorials around automated testing, Cypress E2E testing, and more.

As we will execute the test cases on the LambdaTest platform, we must configure our tests for the LambdaTest cloud grid.

Prerequisite:

Configuring Cypress test on LambdaTest

Step 1: Install the CLI

The command-line interface of LambdaTest enables us to execute your Cypress tests on LambdaTest. Use the Cypress CLI command via npm as shown below

Step 2: Generate lambdatest-config.json

Under the root folder, configure the browsers we want to run the tests. Use the init command to generate a sample lambdatest-config.json file or create one from scratch. Use the below command

In the generated lambdatest-config.json file, pass the information below. Fill in the required values in the section lambdatest_auth, browsers, and run_settings to run your tests.

In the file below, we pass three browsers (Chrome, Firefox, and Electron) and run the test case in two browsers simultaneously.

Github

Run the below command to execute the test case on the LambdaTest.

As we run the above command, test execution starts, and test cases are run in parallel on the LambdaTest platform.

Test case execution

As we execute the test cases in the screenshot below, both test cases start executing in browsers (Chrome, Firefox) parallelly, and we can see the detailed report in the LambdaTest dashboard.

LambdaTest Dashboard offers users a convenient and intuitive interface to oversee test results, review test outcomes, and utilize various platform features. It enables live interactive testing, offering users a real-time view of the website or web application they are testing on a specific browser and operating system.

The screenshot below shows the test case starts executing in browsers (Chrome, Firefox).

starts executing

The screenshot below shows that test cases are passed in the browser (Chrome, Firefox).

cases in the Chrome browser

Here is the console log of executed test cases in the Chrome browser. You can see that three of the test cases are passing in LambdaTest Grid.

Firefox browser

Here is the console log of executed test cases in the Firefox browser. You can see that three test cases passed on the LambdaTest Grid.

LambdaTest Grid

Conclusion

In this Cypress tutorial on handling Shadow DOM in Cypress, we’ve delved into the challenges of handling elements inside Shadow DOM, shedding light on the complexities of interacting with encapsulated components. We’ve explored various approaches and techniques to handle elements within the Shadow DOM effectively using Cypress.

Furthermore, we’ve discussed the integration of LambdaTest, an AI-powered test orchestration and execution platform, and how it enhances the capabilities of Cypress automation. By seamlessly running our Cypress tests across different browser versions and platforms, we ensure our applications’ compatibility and reliability in diverse environments. This integration empowers us to deliver high-quality web experiences to users across the digital landscape.

Frequently Asked Questions (FAQs)

What is shadow DOM used for?

The Shadow DOM (Document Object Model) is a web standard that encapsulates styles, markup, and behavior within a scoped and isolated DOM subtree. It is primarily used to solve issues related to styling and the potential clash of CSS styles and JavaScript code in large and complex web applications. Here are some key purposes and use cases for the Shadow DOM

What is this shadowRoot?

In the context of the Shadow DOM (Document Object Model), shadowRoot is a property of an element that provides access to its own encapsulated subtree. The shadowRoot property refers to the root of the Shadow DOM subtree associated with a specific element.

Author Profile Author Profile Author Profile

Author’s Profile

Kailash Pathak

Currently working as Sr. Quality Lead Manager in a US-based MNC company. Where I am responsible for setting up the overall QA Automation strategy and ensuring that we deliver a high-quality product to our end users. Apart from my role, I have involved myself in educating the community about Software Testing and Test Automation. I am a Blogger and YOUTUBER. I have written a couple of blogs which can find out on my site https://qaautomationlabs.com/

Blogs: 9



linkedintwitter

Test Your Web Or Mobile Apps On 3000+ Browsers

Signup for free