mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
506 lines
17 KiB
HTML
506 lines
17 KiB
HTML
<!doctype html>
|
|
<!--
|
|
@license
|
|
Copyright (c) 2014 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="../../../webcomponentsjs/webcomponents-lite.js"></script>
|
|
<script src="../../../web-component-tester/browser.js"></script>
|
|
<link rel="import" href="../../polymer.html">
|
|
</head>
|
|
<body>
|
|
<template></template>
|
|
<script>
|
|
|
|
// TODO(sorvell): cannot register element in main document under polyfill.
|
|
var registered = false;
|
|
function registerTestElement() {
|
|
if (registered) return;
|
|
var template = document.querySelector('template');
|
|
Polymer({
|
|
is: 'x-content-test',
|
|
_useContent: true,
|
|
_template: template,
|
|
_encapsulateStyle: false
|
|
});
|
|
registered = true;
|
|
}
|
|
|
|
/**
|
|
* Test the `<content>` element distribution algorithm by verifying the
|
|
* resulting composed tree structure.
|
|
*/
|
|
function testRender(descr, hostInnerHtml, shadowRootHtml, expectedHtml) {
|
|
test(descr, function() {
|
|
registerTestElement();
|
|
// 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;
|
|
setInnerHTML(host, hostInnerHtml);
|
|
syncLightDOM(host);
|
|
// Pretend we're stamping the template contents.
|
|
setRootInnerHTML(host.shadyRoot, shadowRootHtml);
|
|
// Invoke distribution and verify the resulting tree.
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), expectedHtml);
|
|
});
|
|
}
|
|
|
|
testRender('Empty shadow', 'abc', '', '');
|
|
testRender('Simple shadow', 'abc', 'def', 'def');
|
|
testRender('Fallback shadow', 'abc',
|
|
'<content select="xxx">fallback</content>', 'fallback');
|
|
testRender('Content', 'abc',
|
|
'<content>fallback</content>', 'abc');
|
|
testRender('Content before', 'abc',
|
|
'before<content>fallback</content>', 'beforeabc');
|
|
testRender('Content after', 'abc',
|
|
'<content>fallback</content>after', 'abcafter');
|
|
|
|
suite('render content', function() {
|
|
testRender('no select', '<a href="">Link</a> <b>bold</b>',
|
|
'<content></content>',
|
|
'<a href="">Link</a> <b>bold</b>');
|
|
testRender('select ""', '<a href="">Link</a> <b>bold</b>',
|
|
'<content select=""></content>',
|
|
'<a href="">Link</a> <b>bold</b>');
|
|
testRender('select *', '<a href="">Link</a> <b>bold</b>',
|
|
'<content select="*"></content>',
|
|
'<a href="">Link</a><b>bold</b>');
|
|
|
|
testRender('select .a',
|
|
'<a class="a">a</a> <a class="b">b</a>',
|
|
'<content select=".a"></content>',
|
|
'<a class="a">a</a>');
|
|
|
|
testRender('select .b .a',
|
|
'<a class="a">a</a> <a class="b">b</a>',
|
|
'<content select=".b"></content><content select=".a"></content>',
|
|
'<a class="b">b</a><a class="a">a</a>');
|
|
|
|
testRender('select .b .a 2',
|
|
'<a class="a">a</a> <a class="b">b</a> <a class="b">c</a>',
|
|
'<content select=".b"></content><content select=".a"></content>',
|
|
'<a class="b">b</a><a class="b">c</a><a class="a">a</a>');
|
|
|
|
testRender('select [c] *',
|
|
'<span>a</span><span>b</span><span c>c</span><span>d</span>',
|
|
'<content select="[c]"></content><content></content>',
|
|
'<span c="">c</span><span>a</span><span>b</span><span>d</span>');
|
|
});
|
|
|
|
|
|
test('Reproject', function() {
|
|
registerTestElement();
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a></a>');
|
|
// pre-distirbution grab first composed node.
|
|
var a = getComposedChildAtIndex(host, 0);
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<x-content-test id="p"></x-content-test>');
|
|
// force upgrade on polyfilled browsers
|
|
var p = host.shadyRoot.firstChild;
|
|
CustomElements.upgrade(p);
|
|
setInnerHTML(p, '<b></b><content></content>');
|
|
syncLightDOM(p);
|
|
//p.innerHTML = '<b></b><content></content>';
|
|
updateRootInsertionPoints(host.shadyRoot);
|
|
var b = p.firstChild;
|
|
var content = p.lastChild;
|
|
|
|
|
|
|
|
syncLightDOM(p);
|
|
setRootInnerHTML(p.shadyRoot,
|
|
'a: <content select=a></content>b: <content select=b></content>');
|
|
var textNodeA = p.shadyRoot.firstChild;
|
|
var contentA = p.shadyRoot.childNodes[1];
|
|
var textNodeB = p.shadyRoot.childNodes[2]
|
|
var contentB = p.shadyRoot.childNodes[3];
|
|
|
|
function testRender() {
|
|
// Simulate the correct ordering as "ready" would fire.
|
|
distributeContentNow(host);
|
|
// NOTE: needed only for this imperative test that needs
|
|
// to simulate distribution from `shadyRoot`
|
|
distributeContentNow(p);
|
|
assert.strictEqual(getComposedHTML(host),
|
|
'<x-content-test id="p">a: <a></a>b: <b></b></x-content-test>');
|
|
|
|
assertArrayEqual(host.__dom.childNodes, [a]);
|
|
assert.strictEqual(a.__dom.parentNode, host);
|
|
assertArrayEqual(host.shadyRoot.__dom.childNodes, [p]);
|
|
assert.strictEqual(p.__dom.parentNode, host.shadyRoot);
|
|
assertArrayEqual(p.__dom.childNodes, [b, content]);
|
|
assert.strictEqual(b.__dom.parentNode, p);
|
|
assert.strictEqual(content.__dom.parentNode, p);
|
|
assertArrayEqual(p.shadyRoot.__dom.childNodes,
|
|
[textNodeA, contentA, textNodeB, contentB]);
|
|
}
|
|
|
|
testRender();
|
|
testRender();
|
|
});
|
|
|
|
|
|
suite('Mutate light DOM', function() {
|
|
test('removeAllChildNodes - mutate host', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content>fallback</content>');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
host.firstChild.textContent = '';
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a></a>');
|
|
|
|
host.__dom.childNodes = [];
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), 'fallback');
|
|
});
|
|
|
|
|
|
test('removeAllChildNodes - mutate shadow', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content><b>after</b>');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b>after</b>');
|
|
|
|
host.shadyRoot.__dom.childNodes[1].textContent = '';
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b></b>');
|
|
|
|
host.shadyRoot.__dom.childNodes = [];
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '');
|
|
});
|
|
|
|
test('removeAllChildNodes - mutate shadow fallback', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content select="xxx"><b>fallback</b></content>');
|
|
var b = host.shadyRoot.firstChild.firstChild;
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<b>fallback</b>');
|
|
|
|
b.textContent = '';
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<b></b>');
|
|
|
|
host.shadyRoot.firstChild.__dom.childNodes = [];
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '');
|
|
|
|
host.shadyRoot.__dom.childNodes = [];
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '');
|
|
});
|
|
|
|
test('removeChild - mutate host', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content>fallback</content>');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
host.firstChild.removeChild(host.firstChild.firstChild);
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a></a>');
|
|
|
|
host.__dom.childNodes = [];
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), 'fallback');
|
|
});
|
|
|
|
test('removeChild - mutate host 2', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a></a><b></b>');
|
|
var a = getComposedChildAtIndex(host, 0);
|
|
var b = getComposedChildAtIndex(host, 1);
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content>fallback</content>');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a></a><b></b>');
|
|
|
|
Polymer.dom(host).removeChild(b);
|
|
Polymer.dom.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a></a>');
|
|
|
|
Polymer.dom(host).removeChild(a);
|
|
Polymer.dom.flush();
|
|
assert.strictEqual(getComposedHTML(host), 'fallback');
|
|
});
|
|
|
|
test('removeChild - mutate shadow', function() {
|
|
var host = document.createElement('x-content-test');
|
|
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content><b>after</b>');
|
|
var b = host.shadyRoot.lastChild;
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b>after</b>');
|
|
|
|
b.removeChild(b.firstChild);
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b></b>');
|
|
|
|
host.shadyRoot.__dom.childNodes.splice(1, 1); // remove b
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
host.shadyRoot.__dom.childNodes = []; // remove a
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '');
|
|
});
|
|
|
|
test('setAttribute select', function() {
|
|
// TODO(arv): DOM bindings for select.
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a><b>World</b>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content select="b">fallback b</content>' +
|
|
'<content select="a">fallback a</content>');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<b>World</b><a>Hello</a>');
|
|
|
|
host.shadyRoot.firstChild.setAttribute('select', 'xxx');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), 'fallback b<a>Hello</a>');
|
|
|
|
host.shadyRoot.firstChild.setAttribute('select', '');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b>World</b>fallback a');
|
|
});
|
|
|
|
test('appendChild - mutate host', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content>');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
Polymer.dom(host).appendChild(b);
|
|
Polymer.dom.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b></b>');
|
|
});
|
|
|
|
test('appendChild - mutate shadow', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content>');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
Polymer.dom(host.shadyRoot).appendChild(b);
|
|
Polymer.dom.flush();
|
|
//distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a><b></b>');
|
|
});
|
|
|
|
test('insertBefore - mutate host', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
var a = getComposedChildAtIndex(host, 0);
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content>');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
Polymer.dom(host).insertBefore(b, a);
|
|
Polymer.dom.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b></b><a>Hello</a>');
|
|
});
|
|
|
|
test('insertBefore - mutate shadow', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content>');
|
|
var content = host.shadyRoot.firstChild;
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
Polymer.dom(host.shadyRoot).insertBefore(b, content);
|
|
Polymer.dom.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b></b><a>Hello</a>');
|
|
});
|
|
|
|
test('replaceChild - mutate host', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
var a = host.firstChild;
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content>');
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
host.__dom.childNodes[0] = b;
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<b></b>');
|
|
});
|
|
|
|
test('replaceChild - mutate shadow', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<a>Hello</a>');
|
|
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content>');
|
|
var content = host.shadyRoot.firstChild;
|
|
distributeContentNow(host);
|
|
assert.strictEqual(getComposedHTML(host), '<a>Hello</a>');
|
|
|
|
var b = document.createElement('b');
|
|
Polymer.dom(host.shadyRoot).replaceChild(b, content);
|
|
Polymer.dom.flush();
|
|
assert.strictEqual(getComposedHTML(host), '<b></b>');
|
|
});
|
|
|
|
test('querySelectorAll (shadyRoot)', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<div id="main"></div>');
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content><span id="main"></span>' +
|
|
'<x-content-test></x-content-test>');
|
|
var hostLocalMain = getComposedChildAtIndex(host.shadyRoot, 1);
|
|
var child = getComposedChildAtIndex(host.shadyRoot, 100);
|
|
// force upgrade on polyfilled browsers
|
|
CustomElements.upgrade(child);
|
|
setInnerHTML(child, '<div id="sub"></div>');
|
|
var childLightSub = getComposedChildAtIndex(child, 0);
|
|
syncLightDOM(child);
|
|
setRootInnerHTML(child.shadyRoot, '<content></content><span id="sub"></span>');
|
|
var childLocalSub = child.shadyRoot.lastChild;
|
|
distributeContentNow(host);
|
|
// NOTE: needed only for this imperative test that needs
|
|
// to simulate distribution from `shadyRoot`
|
|
child._distributeContent();
|
|
|
|
assert.deepEqual(Polymer.dom(host.root).querySelectorAll('span#main'), [hostLocalMain]);
|
|
assert.deepEqual(Polymer.dom(host.root).querySelectorAll('div#sub'), [childLightSub]);
|
|
assert.deepEqual(Polymer.dom(child.root).querySelectorAll('span#sub'), [childLocalSub]);
|
|
});
|
|
|
|
test('querySelectorAll (light dom)', function() {
|
|
var host = document.createElement('x-content-test');
|
|
setInnerHTML(host, '<div id="main"></div>');
|
|
var hostLightMain = getComposedChildAtIndex(host, 0);
|
|
syncLightDOM(host);
|
|
setRootInnerHTML(host.shadyRoot, '<content></content><span id="main"></span>' +
|
|
'<x-content-test></x-content-test>');
|
|
var child = getComposedChildAtIndex(host.shadyRoot, 100);
|
|
// force upgrade on polyfilled browsers
|
|
CustomElements.upgrade(child);
|
|
setInnerHTML(child, '<div id="sub"></div>');
|
|
var childLightSub = getComposedChildAtIndex(child, 100) ;
|
|
syncLightDOM(child);
|
|
setRootInnerHTML(child.shadyRoot, '<content></content><span id="sub"></span>');
|
|
distributeContentNow(host);
|
|
assert.deepEqual(Polymer.dom(host).querySelectorAll('div#main'), [hostLightMain]);
|
|
assert.deepEqual(Polymer.dom(host).querySelectorAll('#sub'), []);
|
|
assert.deepEqual(Polymer.dom(child).querySelectorAll('div#sub'), [childLightSub]);
|
|
});
|
|
|
|
});
|
|
|
|
function syncLightDOM(n) {
|
|
if (n.__dom.childNodes !== undefined) {
|
|
var c$ = Array.prototype.slice.call(n.childNodes);
|
|
n.__dom.firstChild = c$[0];
|
|
n.__dom.lastChild = c$[c$.length-1];
|
|
c$.forEach(function(c, i) {
|
|
if (n.__dom.childNodes.indexOf(c) < 0) {
|
|
c.__dom = c.__dom || {};
|
|
c.__dom.parentNode = n;
|
|
c.__dom.previousSibling = c$[i-1];
|
|
c.__dom.nextSibling = c$[i+1];
|
|
n.__dom.childNodes.push(c);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
var nativeAppendChild = Element.prototype.appendChild;
|
|
|
|
function setInnerHTML(node, value) {
|
|
node.textContent = '';
|
|
var temp = node.ownerDocument.createElement('div');
|
|
temp.innerHTML = value;
|
|
var firstChild;
|
|
while (firstChild = temp.firstChild) {
|
|
nativeAppendChild.call(node, firstChild);
|
|
}
|
|
}
|
|
|
|
function setRootInnerHTML(root, value) {
|
|
setInnerHTML(root, value);
|
|
syncLightDOM(root);
|
|
updateRootInsertionPoints(root);
|
|
}
|
|
|
|
function updateRootInsertionPoints(root) {
|
|
Polymer.dom(root.host)._updateInsertionPoints(root.host);
|
|
}
|
|
|
|
function getComposedHTML(node) {
|
|
return node.innerHTML;
|
|
}
|
|
|
|
function getComposedChildAtIndex(node, index) {
|
|
var c$ = node.childNodes;
|
|
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);
|
|
}
|
|
}
|
|
|
|
function distributeContentNow(node) {
|
|
node.distributeContent();
|
|
Polymer.dom.flush();
|
|
}
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|