mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
481 lines
16 KiB
HTML
481 lines
16 KiB
HTML
<!doctype html>
|
|
<!--
|
|
@license
|
|
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
|
|
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
Code distributed by Google as part of the polymer project is also
|
|
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
-->
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js" register="true" shadydom="true"></script>
|
|
<script src="wct-browser-config.js"></script>
|
|
<script src="../../node_modules/wct-browser-legacy/browser.js"></script>
|
|
<script type="module" src="../../polymer-legacy.js"></script>
|
|
</head>
|
|
<body>
|
|
<template></template>
|
|
<script type="module">
|
|
import { Polymer } from '../../polymer-legacy.js';
|
|
var template = document.querySelector('template');
|
|
Polymer({
|
|
is: 'x-content-test',
|
|
_template: template
|
|
});
|
|
|
|
/*
|
|
* Test the `<slot>` element distribution algorithm by verifying the
|
|
* resulting composed tree structure.
|
|
*/
|
|
function testRender(descr, hostInnerHtml, shadowRootHtml, expectedHtml) {
|
|
test(descr, function() {
|
|
// Create an instance of the test element.
|
|
var host = document.createElement('x-content-test');
|
|
// Populate the initial pool of light DOM children.
|
|
host.innerHTML = hostInnerHtml;
|
|
document.body.appendChild(host);
|
|
// Pretend we're stamping the template contents.
|
|
if (shadowRootHtml) {
|
|
host.shadowRoot.innerHTML = shadowRootHtml;
|
|
}
|
|
// Invoke distribution and verify the resulting tree.
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), expectedHtml);
|
|
document.body.removeChild(host);
|
|
});
|
|
test(descr + ' fragment', function() {
|
|
// Create an instance of the test element.
|
|
var host = document.createElement('x-content-test');
|
|
// Populate the initial pool of light DOM children.
|
|
host.innerHTML = hostInnerHtml;
|
|
document.body.appendChild(host);
|
|
// Pretend we're stamping the template contents.
|
|
var div = document.createElement('div');
|
|
div.innerHTML = shadowRootHtml;
|
|
var frag = document.createDocumentFragment();
|
|
while (div.firstChild) {
|
|
frag.appendChild(div.firstChild);
|
|
}
|
|
host.shadowRoot.appendChild(frag);
|
|
// Invoke distribution and verify the resulting tree.
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), expectedHtml);
|
|
document.body.removeChild(host);
|
|
});
|
|
}
|
|
|
|
testRender('Empty shadow', 'abc', '', '');
|
|
testRender('Simple shadow', 'abc', 'def', 'def');
|
|
testRender('Fallback shadow', 'abc',
|
|
'<slot name="xxx">fallback</name>', 'fallback');
|
|
testRender('Fallback shadow, empty host', '',
|
|
'<slot name="xxx">fallback</name>', 'fallback');
|
|
testRender('Content', 'abc',
|
|
'<slot>fallback</slot>', 'abc');
|
|
testRender('Content before', 'abc',
|
|
'before<slot>fallback</slot>', 'beforeabc');
|
|
testRender('Content after', 'abc',
|
|
'<slot>fallback</slot>after', 'abcafter');
|
|
|
|
suite('render content', function() {
|
|
testRender('no select', '<a href="">Link</a> <b>bold</b>',
|
|
'<slot></slot>',
|
|
'<a href="">Link</a> <b>bold</b>');
|
|
testRender('select ""', '<a href="">Link</a> <b>bold</b>',
|
|
'<slot></slot>',
|
|
'<a href="">Link</a> <b>bold</b>');
|
|
|
|
testRender('slot a',
|
|
'<a slot="a">a</a> <a slot="b">b</a>',
|
|
'<slot name="a"></slot>',
|
|
'<a slot="a">a</a>');
|
|
|
|
testRender('slot b a',
|
|
'<a slot="a">a</a> <a slot="b">b</a>',
|
|
'<slot name="b"></slot><slot name="a"></slot>',
|
|
'<a slot="b">b</a><a slot="a">a</a>');
|
|
|
|
testRender('slot b a 2',
|
|
'<a slot="a">a</a> <a slot="b">b</a> <a slot="b">c</a>',
|
|
'<slot name="b"></slot><slot name="a"></slot>',
|
|
'<a slot="b">b</a><a slot="b">c</a><a slot="a">a</a>');
|
|
|
|
testRender('slot c catchall',
|
|
'<span>a</span><span>b</span><span slot="c">c</span><span>d</span>',
|
|
'<slot name="c"></slot><slot></slot>',
|
|
'<span slot="c">c</span><span>a</span><span>b</span><span>d</span>');
|
|
});
|
|
|
|
|
|
test('Reproject', function() {
|
|
var host = document.createElement('x-content-test');
|
|
document.body.appendChild(host);
|
|
host.innerHTML = '<a></a>';
|
|
// pre-distirbution grab first composed node.
|
|
var a = getComposedChildAtIndex(host, 0);
|
|
|
|
host.shadowRoot.innerHTML = '<x-content-test id="p"></x-content-test>';
|
|
// force upgrade on polyfilled browsers
|
|
var p = host.shadowRoot.firstChild;
|
|
p.innerHTML = '<b slot="b"></b><slot slot="a"></slot>';
|
|
var b = p.firstChild;
|
|
var content = p.lastChild;
|
|
|
|
p.shadowRoot.innerHTML =
|
|
'a: <slot name="a"></slot>b: <slot name="b"></slot>';
|
|
var textNodeA = p.shadowRoot.firstChild;
|
|
var contentA = p.shadowRoot.childNodes[1];
|
|
var textNodeB = p.shadowRoot.childNodes[2];
|
|
var contentB = p.shadowRoot.childNodes[3];
|
|
|
|
function testRender() {
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host),
|
|
'<x-content-test id="p">a: <a></a>b: <b slot="b"></b></x-content-test>');
|
|
|
|
assertArrayEqual(host.childNodes, [a]);
|
|
assert.strictEqual(a.parentNode, host);
|
|
assertArrayEqual(host.shadowRoot.childNodes, [p]);
|
|
assert.strictEqual(p.parentNode, host.shadowRoot);
|
|
assertArrayEqual(p.childNodes, [b, content]);
|
|
assert.strictEqual(b.parentNode, p);
|
|
assert.strictEqual(content.parentNode, p);
|
|
assertArrayEqual(p.shadowRoot.childNodes,
|
|
[textNodeA, contentA, textNodeB, contentB]);
|
|
}
|
|
|
|
testRender();
|
|
testRender();
|
|
document.body.removeChild(host);
|
|
});
|
|
|
|
|
|
suite('Mutate light DOM', function() {
|
|
var host;
|
|
|
|
setup(function() {
|
|
host = document.createElement('x-content-test');
|
|
document.body.appendChild(host);
|
|
});
|
|
|
|
teardown(function() {
|
|
document.body.removeChild(host);
|
|
});
|
|
|
|
test('removeAllChildNodes - mutate host', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
|
|
host.shadowRoot.innerHTML = '<slot>fallback</slot>';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
host.firstChild.textContent = '';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a></a>');
|
|
|
|
host.innerHTML = '';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), 'fallback');
|
|
});
|
|
|
|
|
|
test('removeAllChildNodes - mutate shadow', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
|
|
host.shadowRoot.innerHTML = '<slot></slot><b>after</b>';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b>after</b>');
|
|
|
|
host.shadowRoot.childNodes[1].textContent = '';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b></b>');
|
|
|
|
host.shadowRoot.innerHTML = '';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '');
|
|
});
|
|
|
|
test('removeAllChildNodes - mutate shadow fallback', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
|
|
host.shadowRoot.innerHTML = '<slot name="xxx"><b>fallback</b></slot>';
|
|
var b = host.shadowRoot.firstChild.firstChild;
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b>fallback</b>');
|
|
|
|
b.textContent = '';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b></b>');
|
|
|
|
host.shadowRoot.firstChild.innerHTML = '';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '');
|
|
|
|
host.shadowRoot.innerHTML = '';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '');
|
|
});
|
|
|
|
test('removeChild - mutate host', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
|
|
host.shadowRoot.innerHTML = '<slot>fallback</slot>';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
host.firstChild.removeChild(host.firstChild.firstChild);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a></a>');
|
|
|
|
host.innerHTML = '';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), 'fallback');
|
|
});
|
|
|
|
test('removeChild - mutate host 2', function() {
|
|
host.innerHTML = '<a></a><b></b>';
|
|
var a = getComposedChildAtIndex(host, 0);
|
|
var b = getComposedChildAtIndex(host, 1);
|
|
|
|
host.shadowRoot.innerHTML = '<slot>fallback</slot>';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a></a><b></b>');
|
|
|
|
host.removeChild(b);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a></a>');
|
|
|
|
host.removeChild(a);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), 'fallback');
|
|
});
|
|
|
|
test('removeChild - mutate shadow', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
|
|
host.shadowRoot.innerHTML = '<slot></slot><b>after</b>';
|
|
var b = host.shadowRoot.lastChild;
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b>after</b>');
|
|
|
|
b.removeChild(b.firstChild);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b></b>');
|
|
|
|
host.shadowRoot.removeChild(b);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
host.shadowRoot.removeChild(host.shadowRoot.firstChild);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '');
|
|
});
|
|
|
|
test('setAttribute slot', function() {
|
|
host.innerHTML = '<a slot="a">Hello</a><b slot="b">World</b>';
|
|
|
|
|
|
host.shadowRoot.innerHTML = '<slot name="b">fallback b</slot>' +
|
|
'<slot name="a">fallback a</slot>';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b slot="b">World</b><a slot="a">Hello</a>');
|
|
|
|
host.shadowRoot.firstChild.setAttribute('name', 'xxx');
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), 'fallback b<a slot="a">Hello</a>');
|
|
|
|
host.shadowRoot.firstChild.setAttribute('name', '');
|
|
host.shadowRoot.lastChild.setAttribute('name', '');
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), 'fallback bfallback a');
|
|
});
|
|
|
|
test('appendChild - mutate host', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
host.shadowRoot.innerHTML = '<slot></slot>';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
host.appendChild(b);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b></b>');
|
|
});
|
|
|
|
test('appendChild - mutate shadow', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
host.shadowRoot.innerHTML = '<slot></slot>';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
host.shadowRoot.appendChild(b);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b></b>');
|
|
});
|
|
|
|
test('insertBefore - mutate host', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
var a = getComposedChildAtIndex(host, 0);
|
|
host.shadowRoot.innerHTML = '<slot></slot>';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
host.insertBefore(b, a);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b></b><a>Hello</a>');
|
|
});
|
|
|
|
test('insertBefore - mutate shadow', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
|
|
|
|
host.shadowRoot.innerHTML = '<slot></slot>';
|
|
var content = host.shadowRoot.firstChild;
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
host.shadowRoot.insertBefore(b, content);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b></b><a>Hello</a>');
|
|
});
|
|
|
|
test('replaceChild - mutate host', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
host.shadowRoot.innerHTML = '<slot></slot>';
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
var b = document.createElement('b');
|
|
host.replaceChild(b, host.firstChild);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b></b>');
|
|
});
|
|
|
|
test('replaceChild - mutate shadow', function() {
|
|
host.innerHTML = '<a>Hello</a>';
|
|
host.shadowRoot.innerHTML = '<slot></slot>';
|
|
var content = host.shadowRoot.firstChild;
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
var b = document.createElement('b');
|
|
host.shadowRoot.replaceChild(b, content);
|
|
ShadyDOM.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b></b>');
|
|
});
|
|
|
|
test('querySelectorAll (shadowRoot)', function() {
|
|
host.innerHTML = '<div id="main"></div>';
|
|
host.shadowRoot.innerHTML = '<slot></slot><span id="main"></span>' +
|
|
'<x-content-test></x-content-test>';
|
|
// force upgrade on polyfilled browsers
|
|
ShadyDOM.flush();
|
|
var hostLocalMain = getComposedChildAtIndex(host.shadowRoot, 1);
|
|
var child = getComposedChildAtIndex(host.shadowRoot, 100);
|
|
child.innerHTML = '<div id="sub"></div>';
|
|
var childLightSub = getComposedChildAtIndex(child, 0);
|
|
child.shadowRoot.innerHTML = '<slot></slot><span id="sub"></span>';
|
|
var childLocalSub = child.shadowRoot.lastChild;
|
|
ShadyDOM.flush();
|
|
assert.deepEqual(host.root.querySelectorAll('span#main'), [hostLocalMain]);
|
|
assert.deepEqual(host.root.querySelectorAll('div#sub'), [childLightSub]);
|
|
assert.deepEqual(child.root.querySelectorAll('span#sub'), [childLocalSub]);
|
|
});
|
|
|
|
test('querySelectorAll (light dom)', function() {
|
|
host.innerHTML = '<div id="main"></div>';
|
|
var hostLightMain = getComposedChildAtIndex(host, 0);
|
|
host.shadowRoot.innerHTML = '<slot></slot><span id="main"></span>' +
|
|
'<x-content-test></x-content-test>';
|
|
var child = getComposedChildAtIndex(host.shadowRoot, 100);
|
|
child.innerHTML = '<div id="sub"></div>';
|
|
var childLightSub = getComposedChildAtIndex(child, 100) ;
|
|
child.shadowRoot.innerHTML = '<slot></slot><span id="sub"></span>';
|
|
ShadyDOM.flush();
|
|
assert.deepEqual(host.querySelectorAll('div#main'), [hostLightMain]);
|
|
assert.deepEqual(host.querySelectorAll('#sub'), []);
|
|
assert.deepEqual(child.querySelectorAll('div#sub'), [childLightSub]);
|
|
});
|
|
|
|
});
|
|
|
|
suite('Add shadowRoot to element with childNodes', function() {
|
|
|
|
var el;
|
|
|
|
setup(function() {
|
|
el = document.createElement('div');
|
|
el.testHTML = '<div slot="a">hi</div>';
|
|
el.innerHTML = el.testHTML;
|
|
el.attachShadow({mode: 'open'});
|
|
});
|
|
|
|
test('empty root', function() {
|
|
ShadyDOM.flush();
|
|
assert.equal(getComposedHTML(el), '');
|
|
});
|
|
|
|
test('simple root', function() {
|
|
var shadow = '<div>shadow</div>';
|
|
el.shadowRoot.innerHTML = shadow;
|
|
ShadyDOM.flush();
|
|
assert.equal(getComposedHTML(el), shadow);
|
|
});
|
|
|
|
test('slot matching', function() {
|
|
var shadow = '<div><slot name="a"></slot></div>';
|
|
el.shadowRoot.innerHTML = shadow;
|
|
ShadyDOM.flush();
|
|
assert.equal(getComposedHTML(el), '<div>' + el.testHTML + '</div>');
|
|
});
|
|
|
|
test('slot not matching', function() {
|
|
var shadow = '<div><slot name="b"></slot></div>';
|
|
el.shadowRoot.innerHTML = shadow;
|
|
ShadyDOM.flush();
|
|
assert.equal(getComposedHTML(el), '<div></div>');
|
|
});
|
|
|
|
});
|
|
|
|
function getEffectiveChildNodes(node) {
|
|
var list = [];
|
|
var c$ = node.childNodes;
|
|
for (var i=0, l=c$.length, c; (i<l) && (c=c$[i]); i++) {
|
|
if (c.localName && (c.localName === 'content' || c.localName === 'slot')) {
|
|
list = list.concat(c.assignedNodes({flatten: true}));
|
|
} else {
|
|
list.push(c);
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
function getComposedHTML(node) {
|
|
// Ignore shady CSS scoping
|
|
return ShadyDOM.nativeTree.innerHTML(node).replace(/ class="[^"]*"/g, '');
|
|
}
|
|
|
|
function getComposedChildAtIndex(node, index) {
|
|
var c$ = getEffectiveChildNodes(node);
|
|
if (c$) {
|
|
index = index || 0;
|
|
index = Math.max(0, Math.min(index, c$.length-1));
|
|
return c$[index];
|
|
}
|
|
}
|
|
|
|
function assertArrayEqual(a, b, msg) {
|
|
assert.equal(a.length, b.length, msg);
|
|
for (var i = 0; i < a.length; i++) {
|
|
assert.equal(a[i], b[i], msg);
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|