@polymer/polymer
Version:
The Polymer library makes it easy to create your own web components. Give your element some markup and properties, and then use it on a site. Polymer provides features like dynamic templates and data binding to reduce the amount of boilerplate you need to
1,058 lines (994 loc) • 34.1 kB
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="../../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../../web-component-tester/browser.js"></script>
<link rel="import" href="../../polymer-element.html">
<link rel="import" href="../../lib/utils/flattened-nodes-observer.html">
</head>
<body>
<dom-module id='test-self-observe'>
<template>
<slot id="slot"></slot>
</template>
<script>
HTMLImports.whenReady(function() {
class TestSelfObserve extends Polymer.Element {
static get is() { return 'test-self-observe';}
connectedCallback() {
super.connectedCallback();
this._observer = new Polymer.FlattenedNodesObserver(this, (info) => {
this.info = info;
});
}
disconnectedCallback() {
super.disconnectedCallback();
this._observer.disconnect();
}
}
customElements.define(TestSelfObserve.is, TestSelfObserve);
});
</script>
</dom-module>
<dom-module id='test-static'>
<template>
<div>static</div>
</template>
<script>
HTMLImports.whenReady(function() {
class TestStatic extends Polymer.Element {
static get is() { return 'test-static'; }
}
customElements.define(TestStatic.is, TestStatic);
});
</script>
</dom-module>
<dom-module id='test-slot'>
<template>
<span id="slotContainer">[<slot id="slot"></slot>]</span>
</template>
<script>
HTMLImports.whenReady(function() {
class TestSlot extends Polymer.Element {
static get is() { return 'test-slot'; }
}
customElements.define(TestSlot.is, TestSlot);
});
</script>
</dom-module>
<dom-module id='test-slot1'>
<template>
<test-slot id="slot"><slot></slot></test-slot>
</template>
<script>
HTMLImports.whenReady(function() {
class TestSlot1 extends Polymer.Element {
static get is() { return 'test-slot1'; }
}
customElements.define(TestSlot1.is, TestSlot1);
});
</script>
</dom-module>
<dom-module id='test-slot2'>
<template>
<test-slot1 id="slot"><slot></slot></test-slot1>
</template>
<script>
HTMLImports.whenReady(function() {
class TestSlot2 extends Polymer.Element {
static get is() { return 'test-slot2'; }
}
customElements.define(TestSlot2.is, TestSlot2);
});
</script>
</dom-module>
<dom-module id='test-slot3'>
<template>
<test-slot2 id="slot"><slot></slot></test-slot2>
</template>
<script>
HTMLImports.whenReady(function() {
class TestSlot3 extends Polymer.Element {
static get is() { return 'test-slot3'; }
}
customElements.define(TestSlot3.is, TestSlot3);
});
</script>
</dom-module>
<dom-module id='test-slot-raw'>
<template>
<div id="slot"><slot></slot></div>
</template>
<script>
HTMLImports.whenReady(function() {
class TestSlotRaw extends Polymer.Element {
static get is() { return 'test-slot-raw'; }
}
customElements.define(TestSlotRaw.is, TestSlotRaw);
});
</script>
</dom-module>
<dom-module id='test-slot-attr'>
<template>
[<slot id="slot" name="d"></slot>]
</template>
<script>
HTMLImports.whenReady(function() {
class El extends Polymer.Element {
static get is() { return 'test-slot-attr'; }
}
customElements.define(El.is, El);
});
</script>
</dom-module>
<dom-module id='test-slot-attr1'>
<template>
<test-slot-attr id="slot"><slot name="c" slot="d"></slot></test-slot-attr>
</template>
<script>
HTMLImports.whenReady(function() {
class El extends Polymer.Element {
static get is() { return 'test-slot-attr1'; }
}
customElements.define(El.is, El);
});
</script>
</dom-module>
<dom-module id='test-slot-attr2'>
<template>
<test-slot-attr1 id="slot"><slot name="b" slot="c"></slot></test-slot-attr1>
</template>
<script>
HTMLImports.whenReady(function() {
class El extends Polymer.Element {
static get is() { return 'test-slot-attr2'; }
}
customElements.define(El.is, El);
});
</script>
</dom-module>
<dom-module id='test-slot-attr3'>
<template>
<test-slot-attr2 id="slot"><slot name="a" slot="b"></slot></test-slot-attr2>
</template>
<script>
HTMLImports.whenReady(function() {
class El extends Polymer.Element {
static get is() { return 'test-slot-attr3'; }
}
customElements.define(El.is, El);
});
</script>
</dom-module>
<dom-module id='test-slot-attr-inside'>
<template>
<test-slot-attr3 id="slot"><slot name="a" slot="a"></slot></test-slot-attr3>
</template>
<script>
HTMLImports.whenReady(function() {
class El extends Polymer.Element {
static get is() { return 'test-slot-attr-inside'; }
}
customElements.define(El.is, El);
});
</script>
</dom-module>
<test-slot><div>A</div><div>B</div></test-slot>
<test-static><div>static A</div><div>static B</div></test-static>
<div id="staticDiv"></div>
<script>
suite('observeNodes', function() {
test('observe initial state of distributing element', function() {
var recordedA;
var el = document.querySelector('test-slot');
var observer1 = new Polymer.FlattenedNodesObserver(el, function(info) {
recordedA = info;
});
observer1.flush();
assert.equal(recordedA.addedNodes.length, 2);
recordedA = null;
var recordedB;
var observer2 = new Polymer.FlattenedNodesObserver(el, function(info) {
recordedB = info;
});
observer2.flush();
assert.equal(recordedA, null);
assert.equal(recordedB.addedNodes.length, 2);
observer1.disconnect();
observer2.disconnect();
});
test('observe initial state of non-distributing element', function() {
var recordedA;
var el = document.querySelector('test-static');
var observer1 = new Polymer.FlattenedNodesObserver(el, function(info) {
recordedA = info;
});
observer1.flush();
assert.equal(recordedA.addedNodes.length, 2);
recordedA = null;
var recordedB;
var observer2 = new Polymer.FlattenedNodesObserver(el, function(info) {
recordedB = info;
});
observer2.flush();
assert.equal(recordedA, null);
assert.equal(recordedB.addedNodes.length, 2);
observer1.disconnect();
observer2.disconnect();
});
test('observeNodes called in observed node context', function(done) {
var el = document.createElement('test-slot');
document.body.appendChild(el);
var observer = new Polymer.FlattenedNodesObserver(el, function() {
assert.equal(this, el);
done();
});
// add
var d = document.createElement('div');
el.appendChild(d);
observer.flush();
});
test('observe children changes to distributing element', function() {
var el = document.createElement('test-slot');
document.body.appendChild(el);
var recorded;
var observer = new Polymer.FlattenedNodesObserver(el, function(info) {
recorded = info;
});
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// remove
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 2);
assert.equal(recorded.removedNodes[0], d);
assert.equal(recorded.removedNodes[1], d1);
// add
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// reset, unobserve and remove
recorded = null;
observer.disconnect();
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded, null);
document.body.removeChild(el);
});
test('observe children changes to distributing element that provoke additional changes', function() {
var el = document.createElement('test-slot');
document.body.appendChild(el);
var recordedInfo, elAddedInObserver;
var observerCallCount = 0;
var observer = new Polymer.FlattenedNodesObserver(el, function(info) {
observerCallCount++;
recordedInfo = info;
if (info.target.childNodes.length < 5) {
elAddedInObserver = document.createElement('div');
info.target.appendChild(elAddedInObserver);
}
});
// add
var d = document.createElement('div');
el.appendChild(d);
while (observer.flush()) {
// re-flush until done
}
assert.equal(observerCallCount, 5);
assert.equal(recordedInfo.addedNodes.length, 1);
assert.equal(recordedInfo.addedNodes[0], elAddedInObserver);
assert.equal(el.childNodes.length, 5);
document.body.removeChild(el);
observer.disconnect();
});
test('observe children changes to distributing element (async)', function(done) {
var el = document.createElement('test-slot');
document.body.appendChild(el);
var nodes = [];
var handle = new Polymer.FlattenedNodesObserver(el, function(info) {
for (var i=0, at; i < info.removedNodes.length; i++) {
at = nodes.indexOf(info.removedNodes[i]);
assert.isAbove(at, -1);
nodes.splice(at, 1);
}
nodes = nodes.concat(info.addedNodes);
});
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
let getFlattenedNodes = Polymer.FlattenedNodesObserver.getFlattenedNodes;
setTimeout(function() {
assert.sameMembers(getFlattenedNodes(el), nodes);
// remove
el.removeChild(d);
el.removeChild(d1);
setTimeout(function() {
assert.sameMembers(getFlattenedNodes(el), nodes);
// add
el.appendChild(d);
el.appendChild(d1);
setTimeout(function() {
assert.sameMembers(getFlattenedNodes(el), nodes);
handle.disconnect();
el.removeChild(d);
el.removeChild(d1);
setTimeout(function() {
assert.notEqual(nodes.length, getFlattenedNodes(el).length);
document.body.removeChild(el);
done();
});
});
});
});
});
test('observe children changes to non-distributing element', function() {
var el = document.createElement('test-static');
document.body.appendChild(el);
var recorded;
var observer = new Polymer.FlattenedNodesObserver(el, function(info) {
recorded = info;
});
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// remove
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 2);
assert.equal(recorded.removedNodes[0], d);
assert.equal(recorded.removedNodes[1], d1);
// add
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// reset, unobserve and remove
recorded = null;
observer.disconnect();
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded, null);
document.body.removeChild(el);
});
test('observe changes to inner node wrapping <slot>', function() {
var el = document.createElement('test-slot');
document.body.appendChild(el);
var observedInfo;
var observer = new Polymer.FlattenedNodesObserver(el.$.slotContainer, function(info) {
observedInfo = info;
});
observer.flush();
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(observedInfo.target, el.$.slotContainer);
assert.equal(observedInfo.addedNodes.length, 2);
assert.equal(observedInfo.removedNodes.length, 0);
// remove
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(observedInfo.addedNodes.length, 0);
assert.equal(observedInfo.removedNodes.length, 2);
// add
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(observedInfo.addedNodes.length, 2);
assert.equal(observedInfo.removedNodes.length, 0);
// reset, unobserve and remove
observedInfo = null;
observer.disconnect();
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(observedInfo, null);
document.body.removeChild(el);
});
test('observe changes to <slot>', function() {
var el = document.createElement('test-slot');
document.body.appendChild(el);
var observedInfo;
var observer = new Polymer.FlattenedNodesObserver(el.$.slot, function(info) {
observedInfo = info;
});
observer.flush();
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(observedInfo.target, el.$.slot);
assert.equal(observedInfo.addedNodes.length, 2);
assert.equal(observedInfo.removedNodes.length, 0);
// remove
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(observedInfo.addedNodes.length, 0);
assert.equal(observedInfo.removedNodes.length, 2);
// add
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(observedInfo.addedNodes.length, 2);
assert.equal(observedInfo.removedNodes.length, 0);
// reset, unobserve and remove
observedInfo = null;
observer.disconnect();
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(observedInfo, null);
document.body.removeChild(el);
});
test('observe effective children inside distributing element', function() {
var el = document.createElement('test-slot1');
document.body.appendChild(el);
var recorded;
var observer = new Polymer.FlattenedNodesObserver(el.$.slot, function(info) {
recorded = info;
});
observer.flush();
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// remove
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 2);
assert.equal(recorded.removedNodes[0], d);
assert.equal(recorded.removedNodes[1], d1);
// add
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// reset, unobserve and remove
recorded = null;
observer.disconnect();
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded, null);
document.body.removeChild(el);
});
test('observe effective children changes when adding to another host', function() {
var el = document.createElement('test-slot1');
document.body.appendChild(el);
var recorded;
var observer = new Polymer.FlattenedNodesObserver(el.$.slot, function(info) {
recorded = info;
});
observer.flush();
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// add somewhere else... we should see these as removes
document.body.appendChild(d);
document.body.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 2);
assert.equal(recorded.removedNodes[0], d);
assert.equal(recorded.removedNodes[1], d1);
// cleanup
document.body.removeChild(d);
document.body.removeChild(d1);
document.body.removeChild(el);
observer.disconnect();
});
test('observe effective children changes in static slot when adding to another host', function() {
var el = document.createElement('staticDiv');
document.body.appendChild(el);
var recorded;
var observer = new Polymer.FlattenedNodesObserver(el, function(info) {
recorded = info;
});
observer.flush();
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// add somewhere else... we should see these as removes
document.body.appendChild(d);
document.body.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 2);
assert.equal(recorded.removedNodes[0], d);
assert.equal(recorded.removedNodes[1], d1);
// cleanup
document.body.removeChild(d);
document.body.removeChild(d1);
document.body.removeChild(el);
observer.disconnect();
});
test('observe effective children inside deep distributing element', function() {
var el = document.createElement('test-slot3');
document.body.appendChild(el);
var recorded;
var slot = el.$.slot.$.slot.$.slot;
var observer = new Polymer.FlattenedNodesObserver(slot, function(info) {
recorded = info;
});
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// remove
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 2);
assert.equal(recorded.removedNodes[0], d);
assert.equal(recorded.removedNodes[1], d1);
// add
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// reset, unobserve and remove
recorded = null;
observer.disconnect();
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded, null);
document.body.removeChild(el);
});
test('observe <slot> inside deep distributing element', function() {
var el = document.createElement('test-slot3');
document.body.appendChild(el);
var recorded;
var slot = el.$.slot.$.slot.$.slot.$.slot;
assert.equal(slot.localName, 'slot');
var observer = new Polymer.FlattenedNodesObserver(slot, function(info) {
recorded = info;
});
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// remove
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 2);
assert.equal(recorded.removedNodes[0], d);
assert.equal(recorded.removedNodes[1], d1);
// add
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// reset, unobserve and remove
recorded = null;
observer.disconnect();
el.removeChild(d);
el.removeChild(d1);
observer.flush();
assert.equal(recorded, null);
document.body.removeChild(el);
});
test('observe effective children inside deep distributing element (async)', function(done) {
var el = document.createElement('test-slot3');
document.body.appendChild(el);
var recorded;
var slot = el.$.slot.$.slot.$.slot;
var observer = new Polymer.FlattenedNodesObserver(slot, function(info) {
recorded = info;
});
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
setTimeout(function() {
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// remove
el.removeChild(d);
el.removeChild(d1);
setTimeout(function() {
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 2);
assert.equal(recorded.removedNodes[0], d);
assert.equal(recorded.removedNodes[1], d1);
// add
el.appendChild(d);
el.appendChild(d1);
setTimeout(function() {
assert.equal(recorded.addedNodes.length, 2);
assert.equal(recorded.addedNodes[0], d);
assert.equal(recorded.addedNodes[1], d1);
// reset, unobserve and remove
recorded = null;
observer.disconnect();
el.removeChild(d);
el.removeChild(d1);
setTimeout(function() {
assert.equal(recorded, null);
document.body.removeChild(el);
done();
});
});
});
});
});
test('observe effective children attr changes inside deep distributing element (async)', function(done) {
var el = document.createElement('test-slot-attr3');
document.body.appendChild(el);
var recorded;
var slot = el.$.slot.$.slot.$.slot;
var observer = new Polymer.FlattenedNodesObserver(slot, function(info) {
recorded = info;
});
observer.flush();
recorded = null;
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded, null);
setTimeout(function() {
assert.equal(recorded, null);
d.setAttribute('slot', 'a');
setTimeout(function() {
assert.equal(recorded.addedNodes.length, 1);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
d.removeAttribute('slot');
setTimeout(function() {
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 1);
assert.equal(recorded.removedNodes[0], d);
recorded = null;
observer.disconnect();
d.setAttribute('slot', 'a');
setTimeout(function() {
assert.equal(recorded, null);
document.body.removeChild(el);
done();
});
});
});
});
});
test('observe effective children attr changes inside deep distributing element without outer select (async)', function(done) {
var el = document.createElement('test-slot-attr-inside');
document.body.appendChild(el);
var recorded;
var slot = el.$.slot.$.slot.$.slot.$.slot;
var observer = new Polymer.FlattenedNodesObserver(slot, function(info) {
recorded = info;
});
observer.flush();
recorded = null;
// add
var d = document.createElement('div');
var d1 = document.createElement('div');
el.appendChild(d);
el.appendChild(d1);
observer.flush();
assert.equal(recorded, null);
setTimeout(function() {
assert.equal(recorded, null);
d.setAttribute('slot', 'a');
setTimeout(function() {
assert.equal(recorded.addedNodes.length, 1);
assert.equal(recorded.removedNodes.length, 0);
assert.equal(recorded.addedNodes[0], d);
d.removeAttribute('slot');
setTimeout(function() {
assert.equal(recorded.addedNodes.length, 0);
assert.equal(recorded.removedNodes.length, 1);
assert.equal(recorded.removedNodes[0], d);
recorded = null;
observer.disconnect();
d.setAttribute('slot', 'a');
setTimeout(function() {
assert.equal(recorded, null);
document.body.removeChild(el);
done();
});
});
});
});
});
test('add/remove multiple observers', function() {
var el = document.createElement('test-slot1');
document.body.appendChild(el);
var r1 = 0;
var h1 = new Polymer.FlattenedNodesObserver(el.$.slot, function() {
r1++;
});
var r2 = 0;
var h2 = new Polymer.FlattenedNodesObserver(el.$.slot, function() {
r2++;
});
var r3 = 0;
var h3 = new Polymer.FlattenedNodesObserver(el.$.slot, function() {
r3++;
});
// add
var d = document.createElement('div');
el.appendChild(d);
h1.flush();
h2.flush();
h3.flush();
assert.equal(r1, 1);
assert.equal(r2, 1);
assert.equal(r3, 1);
h1.disconnect();
d = document.createElement('div');
el.appendChild(d);
h1.flush();
h2.flush();
h3.flush();
assert.equal(r1, 1);
assert.equal(r2, 2);
assert.equal(r3, 2);
h2.disconnect();
d = document.createElement('div');
el.appendChild(d);
h1.flush();
h2.flush();
h3.flush();
assert.equal(r1, 1);
assert.equal(r2, 2);
assert.equal(r3, 3);
h3.disconnect();
d = document.createElement('div');
el.appendChild(d);
h1.flush();
h2.flush();
h3.flush();
assert.equal(r1, 1);
assert.equal(r2, 2);
assert.equal(r3, 3);
h1 = new Polymer.FlattenedNodesObserver(el.$.slot, h1.callback);
h2 = new Polymer.FlattenedNodesObserver(el.$.slot, h2.callback);
h3 = new Polymer.FlattenedNodesObserver(el.$.slot, h3.callback);
h1.flush();
h2.flush();
h3.flush();
assert.equal(r1, 2);
assert.equal(r2, 3);
assert.equal(r3, 4);
d = document.createElement('div');
el.appendChild(d);
h1.flush();
h2.flush();
h3.flush();
assert.equal(r1, 3);
assert.equal(r2, 4);
assert.equal(r3, 5);
h3.disconnect();
d = document.createElement('div');
el.appendChild(d);
h1.flush();
h2.flush();
h3.flush();
assert.equal(r1, 4);
assert.equal(r2, 5);
assert.equal(r3, 5);
h2.disconnect();
d = document.createElement('div');
el.appendChild(d);
h1.flush();
h2.flush();
h3.flush();
assert.equal(r1, 5);
assert.equal(r2, 5);
assert.equal(r3, 5);
h1.disconnect();
d = document.createElement('div');
el.appendChild(d);
h1.flush();
h2.flush();
h3.flush();
assert.equal(r1, 5);
assert.equal(r2, 5);
assert.equal(r3, 5);
});
test('observe changes of target with dynamically added <slot>', function() {
var el = document.createElement('test-static');
document.body.appendChild(el);
var container = el.shadowRoot.childNodes[1];
var recorded = null;
var observer = new Polymer.FlattenedNodesObserver(container, function(info) {
recorded = info;
});
var slot = document.createElement('slot');
container.appendChild(slot);
observer.flush();
recorded = null;
var child = document.createElement('div');
el.appendChild(child);
observer.flush();
assert.equal(recorded.addedNodes.length, 1);
assert.equal(recorded.addedNodes[0], child);
recorded = null;
el.removeChild(child);
observer.flush();
assert.equal(recorded.removedNodes.length, 1);
assert.equal(recorded.removedNodes[0], child);
recorded = null;
container.removeChild(slot);
observer.flush();
el.appendChild(child);
assert.equal(recorded, null);
observer.disconnect();
document.body.removeChild(el);
});
test('observe changes of target with dynamically added <slot> (flush/async)', function(done) {
var el = document.createElement('test-static');
document.body.appendChild(el);
var container = el.shadowRoot.childNodes[1];
var recorded = null;
var observer = new Polymer.FlattenedNodesObserver(container, function(info) {
recorded = info;
});
var slot = document.createElement('slot');
container.appendChild(slot);
observer.flush();
recorded = null;
var child = document.createElement('div');
el.appendChild(child);
setTimeout(function() {
assert.equal(recorded.addedNodes.length, 1);
assert.equal(recorded.addedNodes[0], child);
done();
});
});
test('observe changes of target with dynamically added <slot> (async)', function(done) {
var el = document.createElement('test-static');
document.body.appendChild(el);
var container = el.shadowRoot.childNodes[1];
var recorded = null;
var observer = new Polymer.FlattenedNodesObserver(container, function(info) {
recorded = info;
});
var slot = document.createElement('slot');
container.appendChild(slot);
observer.flush();
recorded = null;
var child = document.createElement('div');
el.appendChild(child);
setTimeout(function() {
assert.equal(recorded.addedNodes.length, 1);
assert.equal(recorded.addedNodes[0], child);
recorded = null;
el.removeChild(child);
setTimeout(function() {
assert.equal(recorded.removedNodes.length, 1);
assert.equal(recorded.removedNodes[0], child);
recorded = null;
container.removeChild(slot);
setTimeout(function() {
el.appendChild(child);
assert.equal(recorded, null);
observer.disconnect();
document.body.removeChild(el);
done();
});
});
});
});
test('element distributed to insertion point observing itself', function() {
var host = document.createElement('test-slot');
var el = document.createElement('test-self-observe');
host.appendChild(el);
document.body.appendChild(host);
if (window.ShadyDOM) {
ShadyDOM.flush();
}
assert.ok(el._observer);
var div = document.createElement('div');
el.appendChild(div);
el._observer.flush();
assert.equal(el.info.addedNodes[0], div);
document.body.removeChild(host);
});
test('should not fail on node without children', function() {
var recorded;
var el = document;
var observer = new Polymer.FlattenedNodesObserver(el, function(info) {
recorded = info;
});
assert.equal(recorded, null);
observer.disconnect();
});
});
</script>
</body>
</html>