In this post, we’ll demystify these tricky elements, explain how to work with them in Selenium (Java), and walk through real-world examples that every automation engineer should know.
π§© What Are SVG and Shadow DOM?
Term
Definition
SVG (Scalable Vector Graphics)
XML-based markup for drawing graphics like charts, graphs, and icons — rendered in the DOM as svg, path, circle, etc.
Shadow DOM
A browser feature that encapsulates a portion of the DOM, making it hidden from standard document traversal and locators. Common in web components (e.g., date pickers, Material UI).
π― Real-World Use Cases
Scenario | Type | Example |
---|---|---|
Line charts on dashboards | SVG | D3.js-based financial graph |
Play/Pause video controls | Shadow DOM | HTML5 video elements |
Date pickers | Shadow DOM | <input type="date"> in Chrome |
App icons or animated loading indicators | SVG | <svg><path>...</path></svg> |
πΌ️ Working with SVG in Selenium
✅ Why It’s Tricky:
SVG elements belong to a different namespace, so normal XPath and CSS selectors might not behave as expected.
π§ͺ Example: Clicking an SVG Icon
<svg><path fill="#000000" d="M10 20L30 40"></path></svg>WebElement svgIcon = driver.findElement(By.xpath("//*[local-name()='svg']//*[local-name()='path' and @fill='#000000']"));svgIcon.click();
✔️ Use local-name() in XPath to bypass the namespace issue.
π§ͺ Example: Extracting Text from an SVG Chart
List<WebElement> labels = driver.findElements(
By.xpath("//*[local-name()='svg']//*[local-name()='text']")
);
for (WebElement label : labels) {
System.out.println(label.getText());
}
✔️ Handy when validating chart labels or axis values.
π Working with Shadow DOM in Selenium
⚠️ Why It’s Tricky:
Shadow DOM creates an encapsulated DOM that’s invisible to Selenium’s normal locator strategies. You need JavaScript to access it.
π§ͺ Example: Clicking a Button Inside Shadow DOM
<custom-element>#shadow-root<button id="shadowBtn">Click Me</button></custom-element>WebElement shadowHost = driver.findElement(By.cssSelector("custom-element"));JavascriptExecutor js = (JavascriptExecutor) driver;WebElement shadowRoot = (WebElement) js.executeScript("return arguments[0].shadowRoot", shadowHost);WebElement shadowBtn = shadowRoot.findElement(By.cssSelector("#shadowBtn"));shadowBtn.click();
✔️ No XPath. Only JavaScript + CSS selectors work reliably here.
π¨π¬ Advanced: Nested Shadow DOMs
Some web components go deeper, with shadow roots inside other shadow roots. In that case, you’ll need recursive traversal via JavaScript.
WebElement deepElement = (WebElement) js.executeScript(
"return document.querySelector('outer-element')" +
".shadowRoot.querySelector('inner-element')" +
".shadowRoot.querySelector('#targetBtn')"
);
deepElement.click();
⚔️ SVG vs Shadow DOM: What’s the Difference?
Feature | SVG Elements | Shadow DOM Elements |
---|---|---|
Part of DOM? | ✅ Yes | π« Hidden from regular DOM |
XPath Support? | ✅ With local-name() | ❌ Not supported |
JS Required? | ❌ Optional | ✅ Mandatory |
Use Case | Graphs, icons, data visuals | Web components, inputs, Material UI, videos |
Locator Strategy | XPath w/ local-name(), JS optional | JSExecutor + CSS only |
public WebElement getShadowElement(WebDriver driver, WebElement host, String selector) {JavascriptExecutor js = (JavascriptExecutor) driver;WebElement shadowRoot = (WebElement) js.executeScript("return arguments[0].shadowRoot", host);return shadowRoot.findElement(By.cssSelector(selector));}
π Final Thoughts
Most flaky tests involving dashboards, charts, or modern web apps are caused by SVG or Shadow DOM interactions. Understanding their quirks helps you:
Avoid wasted hours debugging failed locators
Write stable, future-proof UI automation
Handle real-world UIs powered by modern frameworks (e.g., React, Angular, D3.js, Material UI)
π Pro tip: Always inspect deeply — if elements look untraceable, you’re probably dealing with Shadow DOM or SVG.
No comments:
Post a Comment