SoftwareTestPilot
Advanced-DOMadvanced 16 min

Shadow DOM Elements — Practice in Playwright, Selenium & Cypress

Shadow DOM automation practice for Playwright and Selenium — pierce open shadow roots, locate web components, and assert against encapsulated UI.

Live element

Locators cheat-sheet

data-testidRoleAccessible labelWhat it is
shadow-hostgenericShadow host elementCustom element <pilot-toggle> with an OPEN shadow root.
shadow-btnbuttonToggle shadow stateLives inside the open shadow root. Use shadow-piercing selectors.
shadow-statestatusShadow toggle stateText node inside the shadow root that flips between ON / OFF.

Reference solutions

import { test, expect } from '@playwright/test';

test('toggles state inside the open shadow root', async ({ page }) => {
  await page.goto('/practice/shadow-dom');

  // Playwright auto-pierces OPEN shadow roots — locators "just work".
  const widget = page.frameLocator('iframe[title="Shadow DOM live widget"]');

  // Use getByTestId; no shadow-specific syntax needed.
  await expect(widget.getByTestId('shadow-state')).toHaveText('OFF');
  await widget.getByTestId('shadow-btn').click();
  await expect(widget.getByTestId('shadow-state')).toHaveText('ON');

  // Equivalent CSS shadow-piercing if you ever need explicit form:
  // page.locator('pilot-toggle >> [data-testid="shadow-btn"]')
});
Try it in the Practice Hub Open learning module