Skip to content

Commit

Permalink
disableShadowDom option
Browse files Browse the repository at this point in the history
  • Loading branch information
samarsault committed Jan 13, 2023
1 parent 1a95e82 commit 437300d
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 11 deletions.
12 changes: 6 additions & 6 deletions packages/dom/src/clone-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import markElement from './prepare-dom';

// returns document fragment
const deepClone = host => {
const deepClone = (host, disableShadowDom = false) => {
// clones shadow DOM and light DOM for a given node
let cloneNode = (node, parent) => {
let walkTree = (nextn, nextp) => {
Expand All @@ -17,14 +17,14 @@ const deepClone = host => {
};

// mark the node before cloning
markElement(node);
markElement(node, disableShadowDom);

let clone = node.cloneNode();

parent.appendChild(clone);

// clone shadow DOM
if (node.shadowRoot) {
if (node.shadowRoot && !disableShadowDom) {
// create shadowRoot
if (clone.shadowRoot) {
// it may be set up in a custom element's constructor
Expand Down Expand Up @@ -59,8 +59,8 @@ const deepClone = host => {
/**
* Deep clone a document while also preserving shadow roots and converting adoptedStylesheets to <style> tags.
*/
const cloneNodeAndShadow = doc => {
let mockDocumentFragment = deepClone(doc.documentElement);
const cloneNodeAndShadow = (doc, disableShadowDom = false) => {
let mockDocumentFragment = deepClone(doc.documentElement, disableShadowDom);
// convert document fragment to document object
let cloneDocument = doc.cloneNode();
// dissolve document fragment in clone document
Expand All @@ -71,7 +71,7 @@ const cloneNodeAndShadow = doc => {
/**
* Use `getInnerHTML()` to serialize shadow dom as <template> tags. `innerHTML` and `outerHTML` don't do this. Buzzword: "declarative shadow dom"
*/
const getOuterHTML = docElement => {
const getOuterHTML = (docElement) => {
// firefox doesn't serialize shadow DOM, we're awaiting API's by firefox to become ready and are not polyfilling it.
if (!docElement.getInnerHTML) { return docElement.outerHTML; }
// chromium gives us declarative shadow DOM serialization API
Expand Down
4 changes: 2 additions & 2 deletions packages/dom/src/prepare-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ function uid() {
return `_${Math.random().toString(36).substr(2, 9)}`;
}

export function markElement(domElement) {
export function markElement(domElement, disableShadowDom = false) {
// Mark elements that are to be serialized later with a data attribute.
if (['input', 'textarea', 'select', 'iframe', 'canvas', 'video', 'style'].includes(domElement.tagName?.toLowerCase())) {
if (!domElement.getAttribute('data-percy-element-id')) {
Expand All @@ -12,7 +12,7 @@ export function markElement(domElement) {
}

// add special marker for shadow host
if (domElement.shadowRoot) {
if (!disableShadowDom && domElement.shadowRoot) {
if (!domElement.getAttribute('data-percy-shadow-host')) {
domElement.setAttribute('data-percy-shadow-host', '');
}
Expand Down
5 changes: 3 additions & 2 deletions packages/dom/src/serialize-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export function serializeDOM(options) {
// allow snake_case or camelCase
enableJavaScript = options?.enable_javascript,
domTransformation = options?.dom_transformation,
stringifyResponse = options?.stringify_response
stringifyResponse = options?.stringify_response,
disableShadowDom = options?.disableShadowDom
} = options || {};

// keep certain records throughout serialization
Expand All @@ -49,7 +50,7 @@ export function serializeDOM(options) {
};

ctx.dom = dom;
ctx.clone = cloneNodeAndShadow(ctx.dom);
ctx.clone = cloneNodeAndShadow(ctx.dom, disableShadowDom);

serializeInputs(ctx);
serializeFrames(ctx);
Expand Down
16 changes: 15 additions & 1 deletion packages/dom/test/serialize-dom.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,25 @@ describe('serializeDOM', () => {
const html = serializeDOM().html;
expect(html).toMatch(new RegExp(matchRegex));
});

it('respects disableShadowDom', () => {
if (!navigator.userAgent.toLowerCase().includes('chrome')) {
return;
}
withExample('<div id="content"></div>', { withShadow: false });
const baseContent = document.querySelector('#content');
const el = createShadowEl(8);
baseContent.appendChild(el);

const html = serializeDOM({ disableShadowDom: true }).html;
expect(html).not.toMatch('<p>Percy-8</p>');
expect(html).not.toMatch('data-percy-shadow-host=');
});
});

describe('with `domTransformation`', () => {
beforeEach(() => {
withExample('<span class="delete-me">Delete me</span>', { withShadow: true });
withExample('<span class="delete-me">Delete me</span>', { withShadow: false });
spyOn(console, 'error');
});

Expand Down

0 comments on commit 437300d

Please sign in to comment.