Skip to content

Commit 9e106d8

Browse files
committed
Add runtime stamping tests around linking & unlinking effects.
1 parent 5e1a8b6 commit 9e106d8

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

lib/mixins/property-effects.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2866,7 +2866,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
28662866
// parent list, a template's `parent` reference is never removed, since
28672867
// this is is determined by the tree structure and applied at
28682868
// `applyTemplateInfo` time.
2869-
let templateInfo = dom.templateInfo;
2869+
const templateInfo = dom.templateInfo;
28702870
const {previousSibling, nextSibling, parent} = templateInfo;
28712871
if (previousSibling) {
28722872
previousSibling.nextSibling = nextSibling;
@@ -2878,6 +2878,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
28782878
} else if (parent) {
28792879
parent.lastChild = previousSibling;
28802880
}
2881+
templateInfo.nextSibling = templateInfo.previousSibling = null;
28812882
// Remove stamped nodes
28822883
let nodes = templateInfo.childNodes;
28832884
for (let i=0; i<nodes.length; i++) {

test/unit/property-effects-template.html

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,30 @@
162162
</script>
163163
</dom-module>
164164

165+
<script type="module">
166+
import { PolymerElement, html } from '../../polymer-element.js';
167+
customElements.define('x-runtime-nested', class extends PolymerElement {
168+
static get template() {
169+
return html`<template id="t1">
170+
<span>t1-[[prop1]]</span>
171+
<template id="t2">
172+
<span>t2-[[prop2]]</span>
173+
<template id="t3">
174+
<span>t3-[[prop3]]</span>
175+
</template>
176+
</template>
177+
</template>`;
178+
}
179+
static get properties() {
180+
return {
181+
prop1: { value: 'prop1'},
182+
prop2: { value: 'prop2'},
183+
prop3: { value: 'prop3'}
184+
};
185+
}
186+
});
187+
</script>
188+
165189
<template id="custom-template">
166190
<x-special name="el1" special="attr1" binding="[[prop]]" on-event="handler"></x-special>
167191
<div name="el2" special="attr2">
@@ -707,6 +731,85 @@
707731

708732
});
709733

734+
suite('nested runtime template stamping', () => {
735+
736+
let el;
737+
738+
// Accumulates any spans that are stamped into a single ordered set; once
739+
// added, a span is never removed, so we can test that updates stop happening
740+
// when bound DOM is removed
741+
const spans = new Set();
742+
const accumulatedContent = () => {
743+
Array.from(el.shadowRoot.querySelectorAll('span')).forEach(s => spans.add(s));
744+
return Array.from(spans).map(e => e.textContent);
745+
};
746+
747+
setup(() => {
748+
el = document.createElement('x-runtime-nested');
749+
document.body.appendChild(el);
750+
});
751+
teardown(() => {
752+
document.body.removeChild(el);
753+
});
754+
755+
test('nested stamping', () => {
756+
// Stamp 1
757+
const dom1 = el._stampTemplate(el.shadowRoot.querySelector('#t1'));
758+
el.shadowRoot.appendChild(dom1);
759+
assert.deepEqual(accumulatedContent(), ['t1-prop1']);
760+
// Stamp 2
761+
const dom2 = el._stampTemplate(el.shadowRoot.querySelector('#t2'));
762+
el.shadowRoot.appendChild(dom2);
763+
assert.deepEqual(accumulatedContent(), ['t1-prop1', 't2-prop2']);
764+
// Stamp 3-1
765+
const dom3_1 = el._stampTemplate(el.shadowRoot.querySelector('#t3'));
766+
el.shadowRoot.appendChild(dom3_1);
767+
assert.deepEqual(accumulatedContent(), ['t1-prop1', 't2-prop2', 't3-prop3']);
768+
// Stamp 3_2
769+
const dom3_2 = el._stampTemplate(el.shadowRoot.querySelector('#t3'));
770+
el.shadowRoot.appendChild(dom3_2);
771+
assert.deepEqual(accumulatedContent(), ['t1-prop1', 't2-prop2', 't3-prop3', 't3-prop3']);
772+
// Stamp 3_3
773+
const dom3_3 = el._stampTemplate(el.shadowRoot.querySelector('#t3'));
774+
el.shadowRoot.appendChild(dom3_3);
775+
assert.deepEqual(accumulatedContent(), ['t1-prop1', 't2-prop2', 't3-prop3', 't3-prop3', 't3-prop3']);
776+
// Modify all
777+
el.setProperties({
778+
prop1: el.prop1 + '*',
779+
prop2: el.prop2 + '*',
780+
prop3: el.prop3 + '*'
781+
});
782+
assert.deepEqual(accumulatedContent(), ['t1-prop1*', 't2-prop2*', 't3-prop3*', 't3-prop3*', 't3-prop3*']);
783+
// Remove 3-1 & modify all
784+
el._removeBoundDom(dom3_1);
785+
el.setProperties({
786+
prop1: el.prop1 + '*',
787+
prop2: el.prop2 + '*',
788+
prop3: el.prop3 + '*'
789+
});
790+
assert.deepEqual(accumulatedContent(), ['t1-prop1**', 't2-prop2**', 't3-prop3*', 't3-prop3**', 't3-prop3**']);
791+
// Remove 3-3 & modify all
792+
el._removeBoundDom(dom3_3);
793+
el.setProperties({
794+
prop1: el.prop1 + '*',
795+
prop2: el.prop2 + '*',
796+
prop3: el.prop3 + '*'
797+
});
798+
assert.deepEqual(accumulatedContent(), ['t1-prop1***', 't2-prop2***', 't3-prop3*', 't3-prop3***', 't3-prop3**']);
799+
// Stamp 3-4
800+
const dom3_4 = el._stampTemplate(el.shadowRoot.querySelector('#t3'));
801+
el.shadowRoot.appendChild(dom3_4);
802+
assert.deepEqual(accumulatedContent(), ['t1-prop1***', 't2-prop2***', 't3-prop3*', 't3-prop3***', 't3-prop3**', 't3-prop3***']);
803+
// Modify all
804+
el.setProperties({
805+
prop1: el.prop1 + '*',
806+
prop2: el.prop2 + '*',
807+
prop3: el.prop3 + '*'
808+
});
809+
assert.deepEqual(accumulatedContent(), ['t1-prop1****', 't2-prop2****', 't3-prop3*', 't3-prop3****', 't3-prop3**', 't3-prop3****']);
810+
});
811+
});
812+
710813
suite('template parsing hooks', () => {
711814

712815
test('custom parsing', () => {

0 commit comments

Comments
 (0)