Skip to content
QA Knowledge Hub

Shadow DOM

Advanced

A component with an open shadow root and one with a closed shadow root.

Practice area

Open shadow root

Closed shadow root

Tasks to automate

  1. Type into the input inside the open shadow root and click its button; assert the message.
  2. Find the same input with a normal document-level CSS selector and see why it fails.
  3. 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.