Shadow DOM allows developers to encapsulate their HTML, CSS, and JavaScript, creating reusable web components with isolated DOM trees. Shadow root elements serve as entry points to this encapsulated content.
Open shadow roots allow access to their internal structure via the `shadowRoot` property.
Closed shadow roots hide their structure from external access, preventing direct manipulation via JavaScript.
Nested shadow roots contain one or more layers of shadow roots, encapsulating their own elements.
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class OpenShadowRootExample {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://shariqsp.com/shadowroot.html");
// Access open shadow root
WebElement shadowHost = driver.findElement(By.id("openShadowHost"));
WebElement shadowRoot = shadowHost.shadowRoot;
// Interact with shadow elements
WebElement username = shadowRoot.findElement(By.id("openUsername"));
WebElement password = shadowRoot.findElement(By.id("openPassword"));
WebElement loginButton = shadowRoot.findElement(By.id("openLoginButton"));
username.sendKeys("user1");
password.sendKeys("password123");
loginButton.click();
}
}
Accessing closed shadow roots directly via Selenium is not possible. Below is the structure.
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.JavascriptExecutor;
public class ClosedShadowRootExample {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://shariqsp.com/shadowroot.html");
// Access closed shadow root
WebElement shadowHost = driver.findElement(By.id("closedShadowHost"));
WebElement shadowRoot = (WebElement) ((JavascriptExecutor) driver)
.executeScript("return arguments[0].shadowRoot", shadowHost);
// Interact with shadow elements if accessible
WebElement username = shadowRoot.findElement(By.cssSelector("input[placeholder='Username (Closed)']"));
WebElement password = shadowRoot.findElement(By.cssSelector("input[placeholder='Password (Closed)']"));
WebElement loginButton = shadowRoot.findElement(By.xpath("//button[text()='Login']"));
username.sendKeys("user1");
password.sendKeys("password123");
loginButton.click();
}
}
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.JavascriptExecutor;
public class NestedShadowRootExample {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "./drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://shariqsp.com/shadowroot.html");
// Access nested shadow root
WebElement shadowHost = driver.findElement(By.id("nestedShadowHost"));
WebElement firstShadowRoot = (WebElement) ((JavascriptExecutor) driver)
.executeScript("return arguments[0].shadowRoot", shadowHost);
WebElement secondShadowRoot = (WebElement) ((JavascriptExecutor) driver)
.executeScript("return arguments[0].shadowRoot", firstShadowRoot.findElement(By.className("nested-shadow")));
// Interact with nested shadow elements
WebElement username = secondShadowRoot.findElement(By.id("nestedUsername"));
WebElement password = secondShadowRoot.findElement(By.id("nestedPassword"));
WebElement loginButton = secondShadowRoot.findElement(By.id("nestedLoginButton"));
username.sendKeys("user1");
password.sendKeys("password123");
loginButton.click();
}
}