Selenium WebDriver
Shadow DOM Handling in Selenium
Master the techniques for handling Shadow DOM elements in modern web applications using Selenium WebDriver.
Understanding Shadow DOM
What is Shadow DOM?
Shadow DOM is a web standard that allows developers to create encapsulated DOM trees that are attached to elements but kept separate from the main document DOM. This provides style and markup encapsulation.
Key Characteristics
- • Encapsulated DOM structure
- • Style isolation from main document
- • Hidden from regular DOM queries
- • Used in modern web components
- • Provides better modularity
Common Use Cases
- • Custom web components
- • Browser native elements (video, audio)
- • Third-party widgets
- • Modern JavaScript frameworks
- • Polymer-based applications
Shadow DOM Testing Challenges
❌ What Doesn't Work
- • Inspector Window: Cannot locate shadow elements directly
- • Regular Locators: Standard findElement() fails
- • XPath: Cannot traverse into shadow DOM
- • Standard CSS: Regular CSS selectors don't work
✅ What Works
- • Browser Console: JavaScript functions work
- • getShadowRoot(): Selenium 4+ method
- • CSS Selector: With shadowRoot navigation
- • SearchContext: Interface for shadow DOM
Locating Shadow Elements in Console
Console Method
Before automating shadow DOM elements, you can locate them in the browser console using JavaScript functions to understand the shadow DOM structure.
Basic Shadow DOM Console Syntax
// Basic shadow DOM navigation
document.querySelector('#shadow-host').shadowRoot.querySelector('button')
// Nested shadow DOM navigation
document.querySelector('ntp-app')
.shadowRoot.querySelector('cr-searchbox')
.shadowRoot.querySelector('#input')
// Complex shadow DOM structure
document.querySelector('shop-app')
.shadowRoot.querySelector('shop-home')
.shadowRoot.querySelector('a[aria-label=\"Men\\'s Outerwear Shop Now\"]')
document.querySelector('#shadow-host').shadowRoot.querySelector('button')
// Nested shadow DOM navigation
document.querySelector('ntp-app')
.shadowRoot.querySelector('cr-searchbox')
.shadowRoot.querySelector('#input')
// Complex shadow DOM structure
document.querySelector('shop-app')
.shadowRoot.querySelector('shop-home')
.shadowRoot.querySelector('a[aria-label=\"Men\\'s Outerwear Shop Now\"]')
💡 Console Testing Tips
- • Use browser DevTools Console tab
- • Test shadow DOM navigation before automation
- • Verify element accessibility and attributes
- • Understand the shadow DOM hierarchy
Selenium Shadow DOM Automation
7-Step Shadow DOM Automation Process
Follow this systematic approach to interact with shadow DOM elements using Selenium WebDriver.
Step 1: Open Browser
ChromeDriver driver = new ChromeDriver();
Step 2: Navigate to URL
driver.get("https://practice.expandtesting.com/shadowdom");
Step 3: Locate Shadow Host
WebElement shadowHost = driver.findElement(
By.cssSelector("#shadow-host"));
By.cssSelector("#shadow-host"));
Step 4: Get Shadow Root
SearchContext shadowRoot =
shadowHost.getShadowRoot();
shadowHost.getShadowRoot();
Step 5: Locate Shadow Element
WebElement shadowElement =
shadowRoot.findElement(By.cssSelector("button"));
shadowRoot.findElement(By.cssSelector("button"));
Step 6: Perform Operations
String text = shadowElement.getText();
shadowElement.click();
shadowElement.click();
Step 7: Cleanup
driver.quit();
Practical Shadow DOM Examples
Example 1: Simple Shadow DOM Interaction
URL: https://practice.expandtesting.com/shadowdom
Task: Locate and interact with button inside shadow DOM
package Tutorial19;
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
ChromeDriver driver = new ChromeDriver();
driver.get("https://practice.expandtesting.com/shadowdom");
Thread.sleep(4000);
// Find the shadow root parent tag
WebElement parentShadow = driver.findElement(By.cssSelector("#shadow-host"));
// Get shadow root to locate internal elements
SearchContext shadowRoot = parentShadow.getShadowRoot();
// Locate internal shadow element
WebElement button = shadowRoot.findElement(By.cssSelector("button"));
// Get button text and perform operations
String buttonText = button.getText();
System.out.println(buttonText);
button.click();
driver.quit();
}
}
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
ChromeDriver driver = new ChromeDriver();
driver.get("https://practice.expandtesting.com/shadowdom");
Thread.sleep(4000);
// Find the shadow root parent tag
WebElement parentShadow = driver.findElement(By.cssSelector("#shadow-host"));
// Get shadow root to locate internal elements
SearchContext shadowRoot = parentShadow.getShadowRoot();
// Locate internal shadow element
WebElement button = shadowRoot.findElement(By.cssSelector("button"));
// Get button text and perform operations
String buttonText = button.getText();
System.out.println(buttonText);
button.click();
driver.quit();
}
}
Example 2: Nested Shadow DOM Navigation
URL: chrome://newtab
Task: Enter text in Chrome's new tab search box (nested shadow DOM)
package Tutorial19;
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class Demo2 {
public static void main(String[] args) throws InterruptedException {
ChromeDriver driver = new ChromeDriver();
driver.get("chrome://newtab");
Thread.sleep(4000);
// Step 1: Locate first shadow root parent
WebElement parentShadowRoot = driver.findElement(By.cssSelector("ntp-app"));
// Step 2: Get first shadow root
SearchContext shadowRoot1 = parentShadowRoot.getShadowRoot();
// Step 3: Locate nested shadow root parent
WebElement childShadowRoot = shadowRoot1.findElement(By.cssSelector("cr-searchbox"));
// Step 4: Get nested shadow root
SearchContext shadowRoot2 = childShadowRoot.getShadowRoot();
// Step 5: Locate and interact with final element
shadowRoot2.findElement(By.cssSelector("input")).sendKeys("Selenium WebDriver");
driver.quit();
}
}
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class Demo2 {
public static void main(String[] args) throws InterruptedException {
ChromeDriver driver = new ChromeDriver();
driver.get("chrome://newtab");
Thread.sleep(4000);
// Step 1: Locate first shadow root parent
WebElement parentShadowRoot = driver.findElement(By.cssSelector("ntp-app"));
// Step 2: Get first shadow root
SearchContext shadowRoot1 = parentShadowRoot.getShadowRoot();
// Step 3: Locate nested shadow root parent
WebElement childShadowRoot = shadowRoot1.findElement(By.cssSelector("cr-searchbox"));
// Step 4: Get nested shadow root
SearchContext shadowRoot2 = childShadowRoot.getShadowRoot();
// Step 5: Locate and interact with final element
shadowRoot2.findElement(By.cssSelector("input")).sendKeys("Selenium WebDriver");
driver.quit();
}
}
Shadow DOM Best Practices
✅ Best Practices
- • Always use CSS Selector for shadow DOM
- • Test shadow DOM structure in console first
- • Use SearchContext interface properly
- • Handle nested shadow DOM systematically
- • Add appropriate waits for shadow elements
- • Verify element accessibility before interaction
🔧 Technical Tips
- • Selenium 4+ required for getShadowRoot()
- • Only CSS Selector works with shadow DOM
- • SearchContext provides findElement() method
- • Chain shadow root navigation for nested DOM
❌ Common Mistakes
- • Using XPath for shadow DOM elements
- • Trying to inspect shadow elements directly
- • Not using getShadowRoot() method
- • Mixing regular and shadow DOM locators
- • Forgetting to handle nested shadow roots
- • Not testing in console before automation
⚠️ Limitations
- • XPath cannot traverse shadow DOM
- • Regular DOM methods don't work
- • Browser inspector has limited support
- • Requires modern browser versions
Knowledge Check
Knowledge Check
Question 1 of 5
What is Shadow DOM in web development?
Shadow DOM Key Points
🎯 Shadow DOM Essentials
- • Shadow DOM provides encapsulation
- • Use getShadowRoot() method in Selenium 4+
- • Only CSS Selector works with shadow DOM
- • SearchContext interface for shadow elements
⚡ Implementation Strategy
- • Test in console before automation
- • Navigate shadow DOM systematically
- • Handle nested shadow roots properly
- • Use appropriate wait strategies
🔧 Technical Requirements
- • Selenium WebDriver 4.0 or higher
- • Modern browser versions
- • CSS Selector expertise
- • JavaScript console knowledge
🚨 Remember
- • XPath doesn't work with shadow DOM
- • Regular DOM methods fail
- • Inspector has limited shadow DOM support
- • Always chain shadow root navigation