Shadow DOM
AdvancedA component with an open shadow root and one with a closed shadow root.
Practice area
Open shadow root
Closed shadow root
Tasks to automate
- Type into the input inside the open shadow root and click its button; assert the message.
- Find the same input with a normal document-level CSS selector and see why it fails.
- Look at the closed shadow root and explain why it cannot be reached from a test. Find the host element and assert that it exists.
Model solutions
Try the tasks first. These show one good way, not the only way.
Selenium (Java)
WebElement host = driver.findElement(By.id("pg-shadow-host"));
SearchContext shadow = host.getShadowRoot(); // Selenium 4
shadow.findElement(By.cssSelector("#shadow-input")).sendKeys("hello");
shadow.findElement(By.cssSelector("#shadow-btn")).click();
String msg = shadow.findElement(By.cssSelector("#shadow-msg")).getText();
// XPath does not work inside a shadow root; use CSS.
Playwright (TypeScript)
// Playwright's CSS and role locators pierce open shadow roots automatically
await page.locator('#shadow-input').fill('hello');
await page.locator('#shadow-btn').click();
await expect(page.locator('#shadow-msg')).toContainText('hello');
Element IDs on this page are stable and will not change. Nothing you do here is sent to a server.
