# Testing Shadow DOM

> Shadow DOM is a new DOM feature that helps you build components. You can think of shadow DOM as a scoped subtree inside your element.\
> [polymer-project.org](https://polymer-library.polymer-project.org/2.0/docs/devguide/shadow-dom)

Shadow DOM is a technology that unlocks such features as isolated DOM and scoped CSS. It's usually used with custom elements to isolate their DOM from the global one. Puppetry targets are relative to a DOM scope (global or local). In order to query elements inside custom elements we have go with chained targets. So we are to create a target for the host element (the custom element root) and targets for the hosted sub-elements that point to the host target.&#x20;

It's much easier to explain with an example. Imagine we have a custom element foo-component, built out of a template:

```markup
<foo-component id="fooShadowRoot"></foo-component>
<template id="fooTemplate">
  <div id="shadowLocalTarget">
    Local Target in Shadow DOM
  </div>  
</template>
```

We can register the component with following code:

```javascript
document.addEventListener( "DOMContentLoaded", () => {

    function registerCustomElement( elName, templateId ) {
      globalThis.customElements.define( elName, class extends HTMLElement {
      constructor() {
          super();
          this.attachShadow({ mode: "open" });
          this.shadowRoot.appendChild( document.getElementById( templateId ).content );
        }
      });
    }

    registerCustomElement( "foo-component", "fooTemplate" );
});
```

Now if we inspect the page DOM with DevTools we can find the following sub-tree:

![](/files/-LtysXayBOAcNZK1HSNU)

Let's say our goal is to access a local target (#shadowLocalTarget), hosted by foo-component element (fooShadowRoot).&#x20;

> With DevTools you can inspect the target element and get with Copy/JS Path code like the that:\
> document.querySelector("#fooShadowRoot").shadowRoot.querySelector("#shadowLocalTarget")\
> If we translate it to Puppetry it actually gives us two targets:\
> \- shadow root:  #fooShadowRoot \
> \- hosted element: #shadowLocalTarget, with the first target for the parent

What we have to do first is to create in Puppetry a target for foo-component (shadow root):

![Defining shadow root target](/files/-Ltyu6zV9plxkktlJqvU)

Then  we create a target for the hosted element

![Defining hosted element target](/files/-LtyuBDltkgSOvUR6SEb)

The first one is a simple target like we are used to have in Puppetry, but the second is chained one. While building it we expand Options, set **Parent target** to `SHADOW_FOO` and **Parent type** to `shadow host`.

![Chained target](/files/-Ltyuth3vvu4X9qKb4xh)

As soon as the hosted element target defined (`SHADOWDOM_FOO_LOCAL`) we can address it as any simple target:

![Addressing a chained target](/files/-LtyuylKl8VVEZqJ2aEF)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.puppetry.app/testing-techniques/testing-shadow-dom.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
