148 lines
6.5 KiB
HTML
148 lines
6.5 KiB
HTML
<!DOCTYPE html>
|
|
<title>getHTML behavior</title>
|
|
<meta name="timeout" content="long">
|
|
<link rel='author' href='mailto:masonf@chromium.org'>
|
|
<link rel='help' href='https://github.com/whatwg/html/issues/8867'>
|
|
<script src='/resources/testharness.js'></script>
|
|
<script src='/resources/testharnessreport.js'></script>
|
|
<script src='../../html/resources/common.js'></script>
|
|
|
|
<body>
|
|
|
|
<script>
|
|
function testElementType(allowsShadowDom, elementType, runGetHTMLOnShadowRoot,
|
|
lightDOMContent, declarativeShadowDom, mode, delegatesFocus,
|
|
serializable, clonable, emptyShadowTree) {
|
|
const t = test(t => {
|
|
// Create and attach element
|
|
let wrapper;
|
|
if (runGetHTMLOnShadowRoot) {
|
|
// This ensures we're testing both Element.getHTML() and ShadowRoot.getHTML().
|
|
const host = document.createElement('div');
|
|
t.add_cleanup(function() { host.remove(); });
|
|
document.body.appendChild(host);
|
|
wrapper = host.attachShadow({mode: 'open'});
|
|
} else {
|
|
wrapper = document.createElement('div');
|
|
t.add_cleanup(function() { wrapper.remove(); });
|
|
document.body.appendChild(wrapper);
|
|
}
|
|
|
|
let shadowRoot;
|
|
let initDict = {mode: mode, delegatesFocus: delegatesFocus, clonable};
|
|
let expectedSerializable = null;
|
|
switch (serializable) {
|
|
case undefined: expectedSerializable = false; break;
|
|
case "true": initDict.serializable = expectedSerializable = true; break;
|
|
case "false": initDict.serializable = expectedSerializable = false; break;
|
|
default: throw new Error(`Invalid serializable ${serializable}`);
|
|
}
|
|
const delegatesAttr = delegatesFocus ? ' shadowrootdelegatesfocus=""' : '';
|
|
const serializableAttr = expectedSerializable ? ' shadowrootserializable=""' : '';
|
|
const clonableAttr = clonable ? ' shadowrootclonable=""' : '';
|
|
|
|
if (allowsShadowDom && declarativeShadowDom) {
|
|
const html = `<${elementType}>${lightDOMContent}<template ` +
|
|
`shadowrootmode=${mode}${delegatesAttr}${serializableAttr}` +
|
|
`${clonableAttr}>`;
|
|
wrapper.setHTMLUnsafe(html);
|
|
// Get hold of the declarative shadow root in a way that works when its mode is "closed"
|
|
shadowRoot = wrapper.firstElementChild.attachShadow(initDict);
|
|
} else {
|
|
// Imperative shadow dom
|
|
const element = document.createElement(elementType);
|
|
wrapper.appendChild(element);
|
|
const temp = document.createElement('div');
|
|
temp.innerHTML = lightDOMContent;
|
|
element.append(...temp.childNodes);
|
|
if (allowsShadowDom) {
|
|
shadowRoot = element.attachShadow(initDict);
|
|
}
|
|
}
|
|
assert_true(!allowsShadowDom || !!shadowRoot);
|
|
|
|
if (allowsShadowDom) {
|
|
const correctShadowHtml = `<template shadowrootmode="${mode}"` +
|
|
`${delegatesAttr}${serializableAttr}${clonableAttr}>` +
|
|
(emptyShadowTree ? `` : `<slot></slot>`) + `</template>`;
|
|
const correctHtml = `<${elementType}>${correctShadowHtml}` +
|
|
`${lightDOMContent}</${elementType}>`;
|
|
assert_equals(shadowRoot.mode,mode);
|
|
assert_equals(shadowRoot.delegatesFocus,delegatesFocus);
|
|
assert_equals(shadowRoot.serializable,expectedSerializable);
|
|
assert_equals(shadowRoot.clonable,clonable);
|
|
if (!emptyShadowTree) {
|
|
shadowRoot.appendChild(document.createElement('slot'));
|
|
}
|
|
const emptyElement = `<${elementType}>${lightDOMContent}</${elementType}>`;
|
|
if (expectedSerializable) {
|
|
assert_equals(wrapper.getHTML({serializableShadowRoots: true}),
|
|
correctHtml);
|
|
assert_equals(wrapper.firstElementChild.getHTML({
|
|
serializableShadowRoots: true}),
|
|
`${correctShadowHtml}${lightDOMContent}`);
|
|
} else {
|
|
assert_equals(wrapper.getHTML({serializableShadowRoots: true}), emptyElement);
|
|
}
|
|
// If we provide the shadow root, serialize it, regardless of serializableShadowRoots.
|
|
assert_equals(wrapper.getHTML({serializableShadowRoots: true, shadowRoots:
|
|
[shadowRoot]}),correctHtml);
|
|
assert_equals(wrapper.getHTML({serializableShadowRoots: false, shadowRoots:
|
|
[shadowRoot]}),correctHtml);
|
|
assert_equals(wrapper.getHTML({shadowRoots: [shadowRoot]}),correctHtml);
|
|
} else {
|
|
// For non-shadow hosts, getHTML() should also match .innerHTML
|
|
assert_equals(wrapper.getHTML({serializableShadowRoots: true}),wrapper.innerHTML);
|
|
}
|
|
|
|
// Either way, make sure getHTML({serializableShadowRoots: false}) matches .innerHTML
|
|
assert_equals(wrapper.getHTML({serializableShadowRoots: false}),wrapper.innerHTML,
|
|
'getHTML() with serializableShadowRoots false should return the same as .innerHTML');
|
|
// ...and that the default for serializableShadowRoots is false.
|
|
assert_equals(wrapper.getHTML(),wrapper.innerHTML,
|
|
'The default for serializableShadowRoots should be false');
|
|
|
|
}, `${runGetHTMLOnShadowRoot ? 'ShadowRoot' : 'Element'}.getHTML() on ` +
|
|
`<${elementType}>${lightDOMContent}${allowsShadowDom ?
|
|
`, with ${declarativeShadowDom ? 'declarative' : 'imperative'} shadow, ` +
|
|
`mode=${mode}, delegatesFocus=${delegatesFocus}, ` +
|
|
`serializable=${serializable}, clonable=${clonable},` : ''}` +
|
|
` with${emptyShadowTree ? `out` : ``} shadow tree contents.`);
|
|
}
|
|
|
|
function runAllTests() {
|
|
const allElements = [...HTML5_ELEMENTS, 'htmlunknown'];
|
|
const safelisted = HTML5_SHADOW_ALLOWED_ELEMENTS.filter(el => el != 'body');
|
|
for (const elementName of allElements) {
|
|
const allowsShadowDom = safelisted.includes(elementName);
|
|
for (const runGetHTMLOnShadowRoot of [false, true]) {
|
|
for (const lightDOMContent of ['','<span>light</span>']) {
|
|
if (allowsShadowDom) {
|
|
for (const declarativeShadowDom of [false, true]) {
|
|
for (const delegatesFocus of [false, true]) {
|
|
for (const clonable of [false, true]) {
|
|
for (const mode of ['open', 'closed']) {
|
|
for (const serializable of [undefined, 'false', 'true']) {
|
|
for (const emptyShadowTree of [false, true]) {
|
|
testElementType(true, elementName, runGetHTMLOnShadowRoot,
|
|
lightDOMContent, declarativeShadowDom, mode,
|
|
delegatesFocus, serializable, clonable,
|
|
emptyShadowTree);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
testElementType(false, elementName, runGetHTMLOnShadowRoot,
|
|
lightDOMContent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
runAllTests();
|
|
|
|
</script>
|