Puppetry
3.2.2
3.2.2
  • Welcome Puppetry
  • Getting Started
  • Project
  • Suite
  • Group
  • Target
    • Simple Target
    • iFrame Target
    • ShadowDOM Target
    • Chained Target
    • Shared Target
  • Test Case
  • Test Step / Action
    • Page Commands
    • Page Assertions
    • Target Commands
    • Target Assertions
  • Managing Records
  • Snippets
  • Running tests
    • Interactive Mode
    • Troubleshooting
  • Test Report
  • Export
    • Exporting as Jest Project (CI-friendly)
    • Exporting as Test Specification
  • Settings
  • Template Expressions
  • Testing Techniques
    • Testing Dynamic Content
    • Exhaustive Testing
    • Performance Testing
    • Visual Regression Testing
    • Testing Shadow DOM
    • Testing Google Analytics tracking code
    • Testing Chrome Extensions
    • Testing REST API
    • Mocking HTTP/S Requests
    • Testing Transactional Emails
      • Example with Restmail.net
      • Example with Mailinator
      • Example with IMAP bridge
      • Example with Google API
    • Testing Forms with Captcha
  • Version Control
  • Tips and Tricks
    • Embrace the Power of CSS
  • Command API
  • Test Application
Powered by GitBook
On this page

Was this helpful?

  1. Testing Techniques

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

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.

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

<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:

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:

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

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):

Then we create a target for the hosted element

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.

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

PreviousVisual Regression TestingNextTesting Google Analytics tracking code

Last updated 5 years ago

Was this helpful?

Defining shadow root target
Defining hosted element target
Chained target
Addressing a chained target