Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Shadow DOM serialisation support #1165

Merged
merged 107 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
9231933
use declarative dom for serializing
samarsault Dec 6, 2022
f995642
Remove getInnerHTML polyfill
samarsault Dec 6, 2022
c432e1c
:memo: update documentation for testing cli packages
itsjwala Dec 7, 2022
3ba8de2
:bug: return document instead of fragment
itsjwala Dec 8, 2022
2e1a07c
:bug: missed let : (
itsjwala Dec 8, 2022
8fd98aa
firefox use default html without declarative
samarsault Dec 13, 2022
ed92d42
add basic tests
samarsault Dec 13, 2022
bbd3644
Serialized element tests
samarsault Dec 21, 2022
13d1b67
rename clone node file name
itsjwala Dec 19, 2022
779172b
mark dom elements in shadow dom, next steps - serialize them
itsjwala Dec 20, 2022
6d33e92
serialize inputs, cssom, video, canvas, frames
itsjwala Dec 22, 2022
3bfebf4
add comments
itsjwala Dec 22, 2022
ee4f143
add warning log for video serialization
itsjwala Dec 22, 2022
d08a988
remove line and add comment
itsjwala Dec 26, 2022
ebe9271
add extra comments
itsjwala Dec 26, 2022
5629413
added declarative shadow dom polyfill for non chromium infra browsers
itsjwala Jan 3, 2023
6e26316
serialize frame test
samarsault Jan 3, 2023
a878a4f
serialize cssom inside shadow
samarsault Jan 3, 2023
f24abfe
shadowDom global in other tests
samarsault Jan 3, 2023
ae3f89d
update id
itsjwala Jan 6, 2023
70f0f5c
karma separate shadow dom config
samarsault Jan 3, 2023
86aea78
Use shadow mode in karma
samarsault Jan 3, 2023
db609d9
refactor dom test to platform
samarsault Jan 9, 2023
a46eaa6
serialize cssom createElement fix
samarsault Jan 9, 2023
7747eda
domTransformation shadow dom unsupported
samarsault Jan 9, 2023
ebbab8b
frames tests add polyfill
samarsault Jan 9, 2023
422de93
withExample: Remove test-shadow for plain to avoid flakes
samarsault Jan 9, 2023
1e88af8
fix frame test side effect in input
samarsault Jan 9, 2023
48c10a5
refactor helper with options
samarsault Jan 9, 2023
7a55414
firefox tests limit platforms
samarsault Jan 9, 2023
49bf6cc
revert test script changes
samarsault Jan 9, 2023
44ae9a5
add tests for inject polyfill
itsjwala Jan 10, 2023
a0d6fbc
:bookmark: v1.19.0-alpha.0
itsjwala Jan 10, 2023
b80a73a
:memo: update readme for dom package
itsjwala Jan 11, 2023
77a1526
use declarative dom for serializing
samarsault Dec 6, 2022
fa4fe40
Remove getInnerHTML polyfill
samarsault Dec 6, 2022
a52b319
:bug: return document instead of fragment
itsjwala Dec 8, 2022
93ff77c
:bug: missed let : (
itsjwala Dec 8, 2022
1812f70
firefox use default html without declarative
samarsault Dec 13, 2022
340cff1
add basic tests
samarsault Dec 13, 2022
6c1fb96
Serialized element tests
samarsault Dec 21, 2022
0c6112b
rename clone node file name
itsjwala Dec 19, 2022
5055721
mark dom elements in shadow dom, next steps - serialize them
itsjwala Dec 20, 2022
5f258d4
serialize inputs, cssom, video, canvas, frames
itsjwala Dec 22, 2022
fdaddd2
add comments
itsjwala Dec 22, 2022
11d2317
add warning log for video serialization
itsjwala Dec 22, 2022
4e485ad
remove line and add comment
itsjwala Dec 26, 2022
e2e17bd
add extra comments
itsjwala Dec 26, 2022
0ee30f0
serialize frame test
samarsault Jan 3, 2023
59b4650
serialize cssom inside shadow
samarsault Jan 3, 2023
875624c
shadowDom global in other tests
samarsault Jan 3, 2023
e2daf4d
karma separate shadow dom config
samarsault Jan 3, 2023
caae096
Use shadow mode in karma
samarsault Jan 3, 2023
cef1c42
added declarative shadow dom polyfill for non chromium infra browsers
itsjwala Jan 3, 2023
cfcd554
refactor dom test to platform
samarsault Jan 9, 2023
9550ae5
domTransformation shadow dom unsupported
samarsault Jan 9, 2023
87a4c38
frames tests add polyfill
samarsault Jan 9, 2023
3d61bf0
withExample: Remove test-shadow for plain to avoid flakes
samarsault Jan 9, 2023
25c2807
fix frame test side effect in input
samarsault Jan 9, 2023
e6bfde8
refactor helper with options
samarsault Jan 9, 2023
9e7439d
firefox tests limit platforms
samarsault Jan 9, 2023
e03c3c6
revert test script changes
samarsault Jan 9, 2023
95eb3e4
frame test more specific
samarsault Jan 10, 2023
3d7fd53
many nested many flat shadow dom
samarsault Jan 10, 2023
902eb43
failing domTransformation for shadow
samarsault Jan 11, 2023
e5d43d0
adoptedStylesheet test
samarsault Jan 11, 2023
c39e29d
fix frames test
samarsault Jan 11, 2023
3e8b734
:bug: return if style id is not found
itsjwala Jan 12, 2023
9893fcc
:bookmark: v1.19.1-alpha.0
itsjwala Jan 12, 2023
f847f49
disableShadowDom option
samarsault Jan 13, 2023
3cf174d
allow disableShadowDom in storybook + cil-snapshot
samarsault Jan 16, 2023
af5714c
disable shadow dom snake case
samarsault Jan 16, 2023
f09e529
cloneNode pass ctx
samarsault Jan 16, 2023
afbfcf5
Add comment
itsjwala Jan 17, 2023
3f6d41f
adoptedStylesheet serialize dom
samarsault Jan 17, 2023
b520ee2
Add comment
itsjwala Jan 17, 2023
560c589
run polyfill as first thing
itsjwala Jan 25, 2023
f56ee1a
custom element test case
samarsault Feb 5, 2023
6969f04
frame in head
samarsault Feb 5, 2023
bc1e812
disable shadow dom naming
samarsault Feb 5, 2023
9d44bf4
use getTestBrowser
samarsault Feb 5, 2023
0f4166d
increase nesting levels
samarsault Feb 5, 2023
b1af229
remove comment
itsjwala Feb 6, 2023
285ebc4
rename argument
itsjwala Feb 6, 2023
cf04c20
inject polyfill only when not disabled
itsjwala Feb 6, 2023
096f764
fix linter
itsjwala Feb 6, 2023
2732297
fix polyfill
itsjwala Feb 6, 2023
ea63218
lint fix
samarsault Feb 6, 2023
6c51b42
Merge branch 'shadow-dom' of github.com:percy/cli into shadow-dom
itsjwala Feb 6, 2023
8bd2e73
refactor
itsjwala Feb 6, 2023
71e6b39
fix disableShadowDOM option
itsjwala Feb 7, 2023
9f3baa7
update readme
itsjwala Feb 7, 2023
ced8778
fix core test
itsjwala Feb 7, 2023
4d23277
serialize adopted styles as link
samarsault Feb 8, 2023
68eac6d
Merge remote-tracking branch 'origin/shadow-dom' into shadow-dom
samarsault Feb 8, 2023
d4ff7c7
text resource as base64
samarsault Feb 8, 2023
ff1bdff
use dataj-percy-serialized
samarsault Feb 9, 2023
36a13bf
fix tests
samarsault Feb 9, 2023
d9bf828
:bookmark: v1.19.2-alpha.0
samarsault Feb 9, 2023
4ae92f0
lerna update
samarsault Feb 10, 2023
f407380
refactor recursive serialize
samarsault Feb 14, 2023
4038cdf
invalid marking test
samarsault Feb 14, 2023
71f7eb5
adoptedStylesheet document test
samarsault Feb 14, 2023
0aa9765
fiix custom element test
samarsault Feb 14, 2023
5762162
fix recursive serialization of special elements
samarsault Feb 14, 2023
2e92ad4
refactor serialize dom
samarsault Feb 14, 2023
803e7d3
increase test coverage
itsjwala Feb 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions packages/dom/src/prepare-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ export function markElement(domElement, disableShadowDOM) {

// add special marker for shadow host
if (!disableShadowDOM && domElement.shadowRoot) {
if (!domElement.getAttribute('data-percy-shadow-host')) {
domElement.setAttribute('data-percy-shadow-host', '');
}
domElement.setAttribute('data-percy-shadow-host', '');

if (!domElement.getAttribute('data-percy-element-id')) {
domElement.setAttribute('data-percy-element-id', uid());
Expand Down
14 changes: 0 additions & 14 deletions packages/dom/src/serialize-canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,6 @@ export function serializeCanvas({ dom, clone, resources }) {
}
cloneEl.remove();
}

// find canvas inside shadow host and recursively serialize them.
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) {
let percyElementId = shadowHost.getAttribute('data-percy-element-id');
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`);

if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) {
serializeCanvas({
dom: shadowHost.shadowRoot,
clone: cloneShadowHost.shadowRoot,
resources
});
}
}
}

export default serializeCanvas;
26 changes: 4 additions & 22 deletions packages/dom/src/serialize-cssom.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function styleSheetsMatch(sheetA, sheetB) {
}

// Outputs in-memory CSSOM into their respective DOM nodes.
export function serializeCSSOM({ dom, clone, warnings, resources }, adoptedStylesMap = null) {
export function serializeCSSOM({ dom, clone, warnings, resources, cache }) {
for (let styleSheet of dom.styleSheets) {
if (isCSSOM(styleSheet)) {
let styleId = styleSheet.ownerNode.getAttribute('data-percy-element-id');
Expand All @@ -45,22 +45,18 @@ export function serializeCSSOM({ dom, clone, warnings, resources }, adoptedStyle

// clone stylesheets in shadowRoot
// https://github.com/WICG/construct-stylesheets/issues/93
if (!adoptedStylesMap) {
adoptedStylesMap = new Map();
}

for (let sheet of dom.adoptedStyleSheets) {
const styleLink = document.createElement('link');
styleLink.setAttribute('rel', 'stylesheet');

if (!adoptedStylesMap.has(sheet)) {
if (!cache.has(sheet)) {
const styles = Array.from(sheet.cssRules)
.map(cssRule => cssRule.cssText).join('\n');
let resource = resourceFromText(uid(), 'text/css', styles);
resources.add(resource);
adoptedStylesMap.set(sheet, resource.url);
cache.set(sheet, resource.url);
}
styleLink.setAttribute('data-percy-serialized-attribute-href', adoptedStylesMap.get(sheet));
styleLink.setAttribute('data-percy-serialized-attribute-href', cache.get(sheet));

if (clone.constructor.name === 'HTMLDocument') {
// handle document and iframe
Expand All @@ -69,20 +65,6 @@ export function serializeCSSOM({ dom, clone, warnings, resources }, adoptedStyle
clone.prepend(styleLink);
}
}

// find stylesheets inside shadow host and recursively serialize them.
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) {
let percyElementId = shadowHost.getAttribute('data-percy-element-id');
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`);

if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) {
serializeCSSOM({
dom: shadowHost.shadowRoot,
clone: cloneShadowHost.shadowRoot,
resources
}, adoptedStylesMap);
}
}
}

export default serializeCSSOM;
31 changes: 25 additions & 6 deletions packages/dom/src/serialize-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ function serializeHTML(ctx) {
return doctype(ctx.dom) + html;
}

function serializeElements(ctx) {
serializeInputs(ctx);
serializeFrames(ctx);
serializeVideos(ctx);

if (!ctx.enableJavaScript) {
serializeCSSOM(ctx);
serializeCanvas(ctx);
}
}

// Serializes a document and returns the resulting DOM string.
export function serializeDOM(options) {
let {
Expand All @@ -46,20 +57,28 @@ export function serializeDOM(options) {
let ctx = {
resources: new Set(),
warnings: new Set(),
cache: new Map(),
enableJavaScript,
disableShadowDOM
};

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

serializeInputs(ctx);
serializeFrames(ctx);
serializeVideos(ctx);
serializeElements(ctx);

if (!enableJavaScript) {
serializeCSSOM(ctx);
serializeCanvas(ctx);
for (const shadowHost of ctx.dom.querySelectorAll('[data-percy-shadow-host]')) {
samarsault marked this conversation as resolved.
Show resolved Hide resolved
let percyElementId = shadowHost.getAttribute('data-percy-element-id');
let cloneShadowHost = ctx.clone.querySelector(`[data-percy-element-id="${percyElementId}"]`);
if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) {
serializeElements({
...ctx,
dom: shadowHost.shadowRoot,
clone: cloneShadowHost.shadowRoot
});
} else {
ctx.warnings.add('element with data-percy-shadow-host does not have shadowRoot');
}
}

if (domTransformation) {
Expand Down
16 changes: 0 additions & 16 deletions packages/dom/src/serialize-frames.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,6 @@ export function serializeFrames({ dom, clone, warnings, resources, enableJavaScr
cloneEl.remove();
}
}

// find iframes inside shadow host and recursively serialize them.
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) {
let percyElementId = shadowHost.getAttribute('data-percy-element-id');
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`);

if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) {
serializeFrames({
dom: shadowHost.shadowRoot,
clone: cloneShadowHost.shadowRoot,
warnings,
resources,
enableJavaScript
});
}
}
}

export default serializeFrames;
15 changes: 1 addition & 14 deletions packages/dom/src/serialize-inputs.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Translates JavaScript properties of inputs into DOM attributes.
export function serializeInputElements({ dom, clone }) {
export function serializeInputElements({ dom, clone, warnings }) {
for (let elem of dom.querySelectorAll('input, textarea, select')) {
let inputId = elem.getAttribute('data-percy-element-id');
let cloneEl = clone.querySelector(`[data-percy-element-id="${inputId}"]`);
Expand Down Expand Up @@ -28,19 +28,6 @@ export function serializeInputElements({ dom, clone }) {
cloneEl.setAttribute('value', elem.value);
}
}

// find inputs inside shadow host and recursively serialize them.
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) {
let percyElementId = shadowHost.getAttribute('data-percy-element-id');
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`);

if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) {
serializeInputElements({
dom: shadowHost.shadowRoot,
clone: cloneShadowHost.shadowRoot
});
}
}
}

export default serializeInputElements;
15 changes: 0 additions & 15 deletions packages/dom/src/serialize-video.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,6 @@ export function serializeVideos({ dom, clone, resources, warnings }) {
// use a data attribute to avoid making a real request
cloneEl.setAttribute('data-percy-serialized-attribute-poster', resource.url);
}

// find video inside shadow host and recursively serialize them.
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) {
let percyElementId = shadowHost.getAttribute('data-percy-element-id');
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`);

if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) {
serializeVideos({
dom: shadowHost.shadowRoot,
clone: cloneShadowHost.shadowRoot,
resources,
warnings
});
}
}
}

export default serializeVideos;