Task Progress0 of 4 Tasks
0%

Deep DOM

Elements buried in nested iframes, a frame that rewrites itself, a closed shadow root and a shadow root inside an iframe. Each task ticks itself when your script gets there.

1.Nested iframes

Three frames deepTo do
Click the button inside the innermost frame
Goal

Switch into frame-level-1, then frame-level-2, then frame-level-3, and click the button.

2.Changing iframe

Frame that rewrites itselfTo do
Goal

The frame counts down from 5, then replaces its content. Wait for liftoff and type the launch code in the answer box.

3.Closed shadow DOM

Closed shadow rootTo do
Type "shadow" into the widget and submit
Goal

Submit “shadow” through the widget. Its input and button are in a closed shadow root that selectors cannot reach.

4.Shadow DOM inside an iframe

Shadow root in a frameTo do
Click the button inside the frame
Goal

Enter the iframe, then reach into the open shadow root under #shadow-host and click its button.

5. Solutions

Try the challenges yourself first. Reference solutions are hidden until you ask for them.

About this Deep DOM page

A deep DOM is a page where iframes are nested inside iframes and shadow roots sit inside those frames, some of them closed. A closed shadow root returns null for element.shadowRoot, so page scripts cannot reach it. Automate it by switching or chaining through each frame in order, then using the driver's own shadow root access rather than JavaScript.

Screenshot of the Deep DOM practice page on QA Playground. Nested iframes, closed shadow roots and shadow DOM inside frames.
Deep DOM: Nested iframes, closed shadow roots and shadow DOM inside frames.

Frequently asked questions

How do I handle nested iframes in Selenium?

Switch one level at a time: switchTo().frame(outer), then switchTo().frame(inner). Use parentFrame() to go up one level or defaultContent() to return to the top. Switching straight to the inner frame fails because Selenium only sees children of the current context.

How do I handle nested iframes in Playwright?

Chain frameLocator calls: page.frameLocator('#outer').frameLocator('#inner').getByRole('button'). Each call narrows the context, and Playwright auto-waits at each level. You do not need to fetch frame objects or switch back afterward.

What is a closed shadow root?

A closed shadow root is created with attachShadow({ mode: 'closed' }). The host element's shadowRoot property returns null, so page JavaScript and querySelector chains cannot enter it. Open roots, with mode 'open', expose shadowRoot normally.

Can Selenium or Playwright access a closed shadow root?

Not by locating elements. Playwright's CSS and text locators pierce open shadow roots only, and Selenium's getShadowRoot() cannot open a closed one. The practical route is the keyboard: focus the element just before the host, press Tab into the closed root and type, which is what the Deep DOM page asks you to do.

How do I find a shadow DOM element inside an iframe?

Enter the frame first, then locate the shadow host and open its root. In Selenium: switchTo().frame(), findElement(host).getShadowRoot().findElement(css). In Playwright: frameLocator(...).locator('host-css inner-css'), since Playwright's CSS locators pierce open shadow roots.

Free developer tools on Randomly.online

QA Playground is part of Randomly.online. These tools help while you write and debug tests: