Bird
Raised Fist0
Selenium Javatesting~15 mins

Shadow DOM element access in Selenium Java - Build an Automation Script

Choose your learning style10 modes available
Access and verify text inside a Shadow DOM element
Preconditions (3)
Step 1: Locate the Shadow DOM host element by id 'shadow-host'
Step 2: Access the Shadow Root of the host element
Step 3: Find the span element with class 'shadow-text' inside the Shadow Root
Step 4: Verify that the text of the span element is exactly 'Hello Shadow DOM'
✅ Expected Result: The span element inside the Shadow DOM contains the text 'Hello Shadow DOM'
Automation Requirements - Selenium WebDriver with Java
Assertions Needed:
Assert that the text inside the Shadow DOM span element equals 'Hello Shadow DOM'
Best Practices:
Use explicit waits to ensure elements are present before accessing
Use JavaScriptExecutor to access Shadow DOM elements since Selenium does not support Shadow DOM natively
Use clear and maintainable locators (id for host, class for inner element)
Handle exceptions gracefully if elements are not found
Automated Solution
Selenium Java
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.Duration;

public class ShadowDomTest {
    private WebDriver driver;
    private WebDriverWait wait;

    @BeforeEach
    public void setUp() {
        driver = new ChromeDriver();
        wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        driver.get("https://example.com/shadowdompage"); // Replace with actual URL
    }

    @Test
    public void testShadowDomText() {
        // Wait for shadow host element to be present
        WebElement shadowHost = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("shadow-host")));

        // Use JavaScriptExecutor to get shadow root
        JavascriptExecutor js = (JavascriptExecutor) driver;
        WebElement shadowRoot = (WebElement) js.executeScript("return arguments[0].shadowRoot", shadowHost);

        // Find the span inside shadow root
        WebElement shadowText = shadowRoot.findElement(By.cssSelector("span.shadow-text"));

        // Assert the text content
        String actualText = shadowText.getText();
        assertEquals("Hello Shadow DOM", actualText, "Shadow DOM text should match expected value");
    }

    @AfterEach
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

The test starts by opening the browser and navigating to the page with the Shadow DOM.

We wait explicitly for the shadow host element with id 'shadow-host' to be present to avoid timing issues.

Since Selenium does not support Shadow DOM directly, we use JavascriptExecutor to get the shadow root of the host element.

Inside the shadow root, we locate the span element with class 'shadow-text' using a CSS selector.

We then get the text of this span and assert it equals the expected string 'Hello Shadow DOM'.

Finally, the browser is closed in the tearDown method to clean up.

Common Mistakes - 3 Pitfalls
Trying to locate Shadow DOM elements directly with Selenium locators without using JavaScriptExecutor
Not using explicit waits before accessing elements
Using brittle or overly complex XPath locators inside Shadow DOM
Bonus Challenge

Now add data-driven testing to verify shadow DOM text for 3 different shadow hosts with ids 'shadow-host1', 'shadow-host2', 'shadow-host3' and their expected texts.

Show Hint

Practice

(1/5)
1. What is the main reason we need special methods to access elements inside a Shadow DOM in Selenium Java?
easy
A. Because Shadow DOM elements are hidden inside a separate DOM tree and not directly accessible.
B. Because Shadow DOM elements use a different programming language.
C. Because Shadow DOM elements are only visible on mobile browsers.
D. Because Shadow DOM elements are deprecated and not supported.

Solution

  1. Step 1: Understand Shadow DOM structure

    Shadow DOM creates a separate DOM tree inside a host element, hiding its internals from the main DOM.
  2. Step 2: Recognize access limitation

    Normal Selenium methods cannot directly access elements inside this hidden tree, so special methods are needed.
  3. Final Answer:

    Because Shadow DOM elements are hidden inside a separate DOM tree and not directly accessible. -> Option A
  4. Quick Check:

    Shadow DOM hides elements = Need special access [OK]
Hint: Shadow DOM hides elements inside separate tree [OK]
Common Mistakes:
  • Thinking Shadow DOM uses a different language
  • Assuming Shadow DOM elements are deprecated
  • Believing Shadow DOM is only for mobile
2. Which Selenium Java code snippet correctly accesses a button inside a Shadow DOM hosted by an element with id 'shadowHost'?
easy
A. WebElement button = driver.findElement(By.id("shadowHost")).findElement(By.tagName("button"));
B. WebElement host = driver.findElement(By.id("shadowHost")); WebElement shadowRoot = host.getShadowRoot(); WebElement button = shadowRoot.findElement(By.cssSelector("button"));
C. WebElement button = driver.findElement(By.cssSelector("#shadowHost button"));
D. WebElement button = driver.getShadowRoot().findElement(By.cssSelector("button"));

Solution

  1. Step 1: Find the shadow host element

    Use driver.findElement(By.id("shadowHost")) to get the host element.
  2. Step 2: Access the shadow root and find the button

    Call getShadowRoot() on the host, then find the button inside the shadow root.
  3. Final Answer:

    Use getShadowRoot() on host, then findElement inside shadow root. -> Option B
  4. Quick Check:

    Shadow root access = getShadowRoot() then findElement [OK]
Hint: Use getShadowRoot() on host before findElement inside [OK]
Common Mistakes:
  • Trying to find shadow elements directly from driver
  • Calling getShadowRoot() on driver instead of host
  • Using nested findElement without shadow root
3. Given the code below, what will be the output if the button inside the Shadow DOM has text 'Click Me'?
WebElement host = driver.findElement(By.id("shadowHost"));
WebElement shadowRoot = host.getShadowRoot();
WebElement button = shadowRoot.findElement(By.cssSelector("button"));
System.out.println(button.getText());
medium
A. Click Me
B. NoSuchElementException
C. null
D. shadowHost

Solution

  1. Step 1: Access shadow host and shadow root

    The code correctly finds the shadow host and calls getShadowRoot() to access the Shadow DOM.
  2. Step 2: Find button and get its text

    The button inside the Shadow DOM is found by CSS selector and getText() returns its visible text 'Click Me'.
  3. Final Answer:

    Click Me -> Option A
  4. Quick Check:

    Correct shadow DOM access = button text output [OK]
Hint: getShadowRoot() then findElement returns correct element [OK]
Common Mistakes:
  • Expecting NoSuchElementException without shadow root access
  • Assuming getText() returns null
  • Confusing shadow host text with shadow element text
4. What is wrong with the following Selenium Java code trying to click a button inside Shadow DOM?
WebElement button = driver.findElement(By.cssSelector("#shadowHost button"));
button.click();
medium
A. driver.findElement cannot find elements by CSS selector.
B. The CSS selector is invalid syntax.
C. The button element cannot be clicked inside Shadow DOM.
D. It tries to find the button directly without accessing the shadow root first.

Solution

  1. Step 1: Analyze element access method

    The code tries to find the button inside Shadow DOM directly from driver using a combined CSS selector.
  2. Step 2: Identify Shadow DOM access requirement

    Shadow DOM elements require accessing the shadow root via getShadowRoot() on the host element before finding inner elements.
  3. Final Answer:

    It tries to find the button directly without accessing the shadow root first. -> Option D
  4. Quick Check:

    Shadow DOM needs getShadowRoot() before findElement [OK]
Hint: Always getShadowRoot() before accessing shadow elements [OK]
Common Mistakes:
  • Using combined CSS selector ignoring shadow root
  • Thinking CSS selector alone works inside Shadow DOM
  • Assuming button cannot be clicked inside Shadow DOM
5. You need to click a nested button inside two levels of Shadow DOM. The outer shadow host has id 'outerHost', and inside it, the inner shadow host has id 'innerHost'. Which code correctly clicks the button inside the inner Shadow DOM?
hard
A. WebElement innerHost = driver.findElement(By.id("innerHost")); WebElement button = innerHost.getShadowRoot().findElement(By.cssSelector("button")); button.click();
B. WebElement button = driver.findElement(By.cssSelector("#outerHost #innerHost button")); button.click();
C. WebElement outerHost = driver.findElement(By.id("outerHost")); WebElement outerShadow = outerHost.getShadowRoot(); WebElement innerHost = outerShadow.findElement(By.id("innerHost")); WebElement innerShadow = innerHost.getShadowRoot(); WebElement button = innerShadow.findElement(By.cssSelector("button")); button.click();
D. WebElement outerHost = driver.findElement(By.id("outerHost")); WebElement button = outerHost.getShadowRoot().findElement(By.cssSelector("#innerHost button")); button.click();

Solution

  1. Step 1: Access outer shadow root

    Find the outer host by id and call getShadowRoot() to access its Shadow DOM.
  2. Step 2: Access inner shadow root

    Inside the outer shadow root, find the inner host element, then call getShadowRoot() again to access the inner Shadow DOM.
  3. Step 3: Find and click the button

    Inside the inner shadow root, find the button and call click() on it.
  4. Final Answer:

    Access each shadow root step-by-step before finding nested elements. -> Option C
  5. Quick Check:

    Nested Shadow DOM requires chained getShadowRoot() calls [OK]
Hint: Chain getShadowRoot() calls for nested Shadow DOM [OK]
Common Mistakes:
  • Trying to find nested shadow elements directly from driver
  • Skipping inner shadow root access
  • Using combined CSS selectors ignoring Shadow DOM
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard