UNPKG

@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

906 lines (810 loc) 37.6 kB
<!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="../../../webcomponentsjs/webcomponents-lite.js"></script> <script src="../../../web-component-tester/browser.js"></script> <link rel="import" href="../../polymer.html"> <link rel="import" href="dom-if-elements.html"> </head> <body> <x-nested-if-configured id="configured"></x-nested-if-configured> <x-nested-if-individual id="individual"></x-nested-if-individual> <dom-bind id="unconfigured"> <template> <x-nested-if id="unconfigured1"></x-nested-if> <x-nested-if id="unconfigured2"></x-nested-if> </template> </dom-bind> <div id="inDocumentContainer"> <dom-if id="inDocumentIf"> <template> <x-foo prop="{{prop}}" item-prop="{{item.prop}}"> </x-foo> <template is="dom-if"> <x-foo prop="{{prop}}" item-prop="{{item.prop}}"> </x-foo> <template is="dom-if"> <x-foo prop="{{prop}}" item-prop="{{item.prop}}"> </x-foo> </template> </template> </template> </dom-if> </div> <div id="structuredContainer"> <dom-bind id="structuredDomBind"> <template> <template is="dom-if" id="structuredDomIf" if="{{item.show}}"> <div class="showing"></div> </template> </template> </dom-bind> </div> <div id="outerContainer"> <dom-if id="simple"> <template> <x-client></x-client> <x-client></x-client> <x-client></x-client> </template> </dom-if> <div id="innerContainer"> </div> </div> <div id="removalContainer"> <dom-if if id="toBeRemoved"> <template><div id="shouldBeRemoved"></div></template> </dom-if> </div> <script> /* force non-upgrade, to test MO-based template finding below */ </script> <div id="nonUpgrade"> <dom-if if> <template>stamped</template> </dom-if> </div> <script> /* global configured individual unconfigured1 unconfigured2 inDocumentContainer inDocumentIf structuredContainer structuredDomIf structuredDomBind outerContainer innerContainer shouldBeRemoved toBeRemoved removalContainer nonUpgrade*/ suite('nested pre-configured dom-if', function() { test('parent scope binding', function() { let stamped = configured.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); assert.equal(stamped[0].prop, 'outer'); assert.equal(stamped[0].itemProp, 'outerItem'); assert.equal(stamped[1].prop, 'outer'); assert.equal(stamped[1].itemProp, 'outerItem'); assert.equal(stamped[2].prop, 'outer'); assert.equal(stamped[2].itemProp, 'outerItem'); }); test('parent scope downward notification', function() { let stamped = configured.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); configured.prop = 'yes'; assert.equal(stamped[0].prop, 'yes'); assert.equal(stamped[1].prop, 'yes'); assert.equal(stamped[2].prop, 'yes'); configured.set('item.prop', 'yay'); assert.equal(stamped[0].itemProp, 'yay'); assert.equal(stamped[1].itemProp, 'yay'); assert.equal(stamped[2].itemProp, 'yay'); }); test('parent upward upward notification', function() { let stamped = configured.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); stamped[2].prop = 'nice'; assert.equal(configured.prop, 'nice'); assert.equal(stamped[0].prop, 'nice'); assert.equal(stamped[1].prop, 'nice'); assert.equal(stamped[2].prop, 'nice'); }); test('dom-change event composed, bubbles outside dom-if scope', function() { let domChangeFired = 0; let domIf = configured.$['if-1']; configured.addEventListener('dom-change', function() { domChangeFired++; }); domIf.if = !domIf.if; domIf.render(); domIf.if = !domIf.if; domIf.render(); assert.equal(domChangeFired, 2); }); }); suite('nested individually-controlled dom-if', function() { test('nothing stamped', function() { let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 0, 'total stamped count incorrect'); }); test('show 1', function() { individual.shouldStamp1 = true; individual.render(); let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 1, 'total stamped count incorrect'); assert.equal(stamped[0].prop, 'prop1'); assert.equal(getComputedStyle(stamped[0]).display, 'inline', 'stamped 1 display wrong'); }); test('show 2', function() { individual.shouldStamp2 = true; individual.render(); let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 2, 'total stamped count incorrect'); assert.equal(stamped[0].prop, 'prop1'); assert.equal(stamped[1].prop, 'prop2'); assert.equal(getComputedStyle(stamped[0]).display, 'inline', 'stamped 1 display wrong'); assert.equal(getComputedStyle(stamped[1]).display, 'inline', 'stamped 2 display wrong'); }); test('show 3', function() { individual.shouldStamp3 = true; individual.render(); let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); assert.equal(stamped[0].prop, 'prop1'); assert.equal(stamped[1].prop, 'prop2'); assert.equal(stamped[2].prop, 'prop3'); assert.equal(getComputedStyle(stamped[0]).display, 'inline', 'stamped 1 display wrong'); assert.equal(getComputedStyle(stamped[1]).display, 'inline', 'stamped 2 display wrong'); assert.equal(getComputedStyle(stamped[2]).display, 'inline', 'stamped 3 display wrong'); }); test('hide 3', function() { individual.shouldStamp3 = false; individual.render(); let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); assert.equal(getComputedStyle(stamped[0]).display, 'inline', 'stamped 1 display wrong'); assert.equal(getComputedStyle(stamped[1]).display, 'inline', 'stamped 2 display wrong'); assert.equal(getComputedStyle(stamped[2]).display, 'none', 'stamped 3 display wrong'); }); test('hide 2', function() { individual.shouldStamp2 = false; individual.render(); let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); assert.equal(getComputedStyle(stamped[0]).display, 'inline', 'stamped 1 display wrong'); assert.equal(getComputedStyle(stamped[1]).display, 'none', 'stamped 2 display wrong'); assert.equal(getComputedStyle(stamped[2]).display, 'none', 'stamped 3 display wrong'); }); test('hide 1', function() { individual.shouldStamp1 = false; individual.render(); let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); assert.equal(getComputedStyle(stamped[0]).display, 'none', 'stamped 1 display wrong'); assert.equal(getComputedStyle(stamped[1]).display, 'none', 'stamped 2 display wrong'); assert.equal(getComputedStyle(stamped[2]).display, 'none', 'stamped 3 display wrong'); }); test('show 1', function() { individual.shouldStamp1 = true; individual.render(); let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); assert.equal(getComputedStyle(stamped[0]).display, 'inline', 'stamped 1 display wrong'); assert.equal(getComputedStyle(stamped[1]).display, 'none', 'stamped 2 display wrong'); assert.equal(getComputedStyle(stamped[2]).display, 'none', 'stamped 3 display wrong'); }); test('show 2', function() { individual.shouldStamp2 = true; individual.render(); let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); assert.equal(getComputedStyle(stamped[0]).display, 'inline', 'stamped 1 display wrong'); assert.equal(getComputedStyle(stamped[1]).display, 'inline', 'stamped 2 display wrong'); assert.equal(getComputedStyle(stamped[2]).display, 'none', 'stamped 3 display wrong'); }); test('show 3', function() { individual.shouldStamp3 = true; individual.render(); let stamped = individual.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); assert.equal(getComputedStyle(stamped[0]).display, 'inline', 'stamped 1 display wrong'); assert.equal(getComputedStyle(stamped[1]).display, 'inline', 'stamped 2 display wrong'); assert.equal(getComputedStyle(stamped[2]).display, 'inline', 'stamped 3 display wrong'); }); }); suite('nested un-configured dom-if in document', function() { test('if=false: nothing rendered', function() { let stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if)'); assert.equal(stamped.length, 0, 'total stamped count incorrect'); }); test('if=true: everything rendered and visible', function() { // first dom-if inDocumentIf.if = true; inDocumentIf.render(); let stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 1, 'total stamped count incorrect'); // second dom-if let xif = inDocumentContainer.querySelector('dom-if'); xif.if = true; xif.render(); stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 2, 'total stamped count incorrect'); // third dom-if xif = inDocumentContainer.querySelector('dom-if'); xif.if = true; xif.render(); stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if)'); stamped.forEach(function(n) { assert.equal(getComputedStyle(n).display, 'inline', 'node was hidden but should not have been'); }); }); test('if=false, restamp=false: everything hidden', function() { inDocumentIf.if = false; inDocumentIf.render(); let stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if)'); stamped.forEach(function(n) { assert.equal(getComputedStyle(n).display, 'none', 'node was not hidden but should have been'); }); }); test('if=true, restamp=true, everything rendered and visible', function() { inDocumentIf.restamp = true; inDocumentIf.if = true; inDocumentIf.render(); let stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if)'); stamped.forEach(function(n) { assert.equal(getComputedStyle(n).display, 'inline', 'node was hidden but should not have been'); }); }); test('if=false, restamp=true, everything gone', function() { inDocumentIf.restamp = true; inDocumentIf.if = false; inDocumentIf.render(); // 2nd one needed to force nested if to detach let stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if)'); assert.equal(stamped.length, 0, 'total stamped count incorrect'); }); // repeat, just to get everything rendered again... test('if=true: everything rendered and visible', function() { // first dom-if inDocumentIf.if = true; inDocumentIf.render(); let stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 1, 'total stamped count incorrect'); // second dom-if let xif = inDocumentContainer.querySelector('dom-if'); xif.if = true; xif.render(); stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 2, 'total stamped count incorrect'); // third dom-if xif = inDocumentContainer.querySelector('dom-if'); xif.if = true; xif.render(); stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if)'); stamped.forEach(function(n) { assert.equal(getComputedStyle(n).display, 'inline', 'node was hidden but should not have been'); }); }); test('parent scope binding', function() { let stamped = inDocumentContainer.querySelectorAll('*:not(template):not(dom-if):not(span)'); stamped[0].prop = 'outer'; assert.equal(stamped[1].prop, 'outer'); assert.equal(stamped[2].prop, 'outer'); }); }); suite('nested un-configured dom-if', function() { test('if=false: nothing rendered', function() { let stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if)'); assert.equal(stamped.length, 0, 'total stamped count incorrect'); }); test('if=true: everything rendered and visible', function() { unconfigured1.domUpdateHandlerCount = 0; unconfigured1.shouldStamp = true; unconfigured2.shouldStamp = true; unconfigured1.render(); let stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); stamped[0].prop = 'outer'; assert.equal(unconfigured1.domUpdateHandlerCount, 1); }); test('if=false, restamp=false: everything hidden', function() { unconfigured1.domUpdateHandlerCount = 0; unconfigured1.shouldStamp = false; unconfigured1.render(); let stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if)'); stamped.forEach(function(n) { assert.equal(getComputedStyle(n).display, 'none', 'node was not hidden but should have been'); }); assert.equal(unconfigured1.domUpdateHandlerCount, 1); }); test('if=true, restamp=true, everything rendered and visible', function() { unconfigured1.domUpdateHandlerCount = 0; unconfigured1.$['if-1'].restamp = true; unconfigured1.shouldStamp = true; unconfigured1.$['if-1'].render(); let stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if)'); stamped.forEach(function(n) { assert.equal(getComputedStyle(n).display, 'inline', 'node was hidden but should not have been'); }); assert.equal(unconfigured1.domUpdateHandlerCount, 1); }); test('if=false, restamp=true, everything gone', function() { unconfigured1.domUpdateHandlerCount = 0; unconfigured1.$['if-1'].restamp = true; unconfigured1.shouldStamp = false; unconfigured1.$['if-1'].render(); let stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if)'); assert.equal(unconfigured1.domUpdateHandlerCount, 1); assert.equal(stamped.length, 0, 'total stamped count incorrect'); assert.equal(unconfigured1.domUpdateHandlerCount, 1); }); // repeat, just to get everything rendered again... test('if=true: everything rendered and visible', function() { unconfigured1.domUpdateHandlerCount = 0; unconfigured1.shouldStamp = true; unconfigured2.shouldStamp = true; unconfigured1.render(); unconfigured2.render(); let stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped.length, 3, 'total stamped count incorrect'); stamped[0].prop = 'outer'; assert.equal(unconfigured1.domUpdateHandlerCount, 1); }); test('parent scope binding', function() { let stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); assert.equal(stamped[1].prop, 'outer'); assert.equal(stamped[2].prop, 'outer'); }); test('parent upward upward notification', function() { let stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); stamped[2].prop = 'nice'; assert.equal(stamped[0].prop, 'nice'); assert.equal(stamped[1].prop, 'nice'); }); test('event handlers', function() { let stamped = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); stamped[0].fire('test1'); assert.equal(unconfigured1.testHandler1Count, 1); stamped[1].fire('test2'); assert.equal(unconfigured1.testHandler2Count, 1); stamped[2].fire('test3'); assert.equal(unconfigured1.testHandler3Count, 1); }); }); suite('notification between two dom-ifs', function() { test('change to one scope doesn\'t affect other dom-if', function() { let stamped1 = unconfigured1.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); let stamped2 = unconfigured2.shadowRoot.querySelectorAll('*:not(template):not(dom-if):not(span)'); unconfigured1.prop = 'foo'; unconfigured2.prop = 'bar'; assert.equal(stamped1[0].prop, 'foo'); assert.equal(stamped1[1].prop, 'foo'); assert.equal(stamped1[2].prop, 'foo'); assert.equal(stamped2[0].prop, 'bar'); assert.equal(stamped2[1].prop, 'bar'); assert.equal(stamped2[2].prop, 'bar'); }); }); suite('structured data controlling if', function() { test('item changed with no if field', function() { let showing; showing = structuredContainer.querySelector('.showing'); assert.notOk(showing); structuredDomBind.item = {show: true}; structuredDomIf.render(); showing = structuredContainer.querySelector('.showing'); assert.ok(showing); assert.equal(getComputedStyle(showing).display, 'block'); structuredDomBind.item = {}; structuredDomIf.render(); showing = structuredContainer.querySelector('.showing'); assert.ok(showing); assert.equal(getComputedStyle(showing).display, 'none'); structuredDomBind.item = {show: true}; structuredDomIf.render(); showing = structuredContainer.querySelector('.showing'); assert.ok(showing); assert.equal(getComputedStyle(showing).display, 'block'); }); test('item changed with no if field (restamp)', function() { let showing; structuredDomIf.restamp = true; structuredDomIf.if = false; structuredDomIf.render(); showing = structuredContainer.querySelector('.showing'); assert.notOk(showing); structuredDomBind.item = {show: true}; structuredDomIf.render(); showing = structuredContainer.querySelector('.showing'); assert.ok(showing); structuredDomBind.item = {}; structuredDomIf.render(); showing = structuredContainer.querySelector('.showing'); assert.notOk(showing); structuredDomBind.item = {show: true}; structuredDomIf.render(); showing = structuredContainer.querySelector('.showing'); assert.ok(showing); }); }); suite('text node handling', function() { test('text nodes cleared on if=false', function() { let x = document.createElement('x-textcontent'); document.body.appendChild(x); x.$.domIf.render(); let stamped = x.shadowRoot.childNodes; assert.equal(stamped.length, 12); assert.equal(stamped[7].textContent.trim(), 'Stuff'); x.$.domIf.if = false; x.$.domIf.render(); stamped = x.shadowRoot.childNodes; assert.equal(stamped.length, 12); assert.equal(stamped[7].textContent.trim(), ''); x.$.domIf.if = true; x.$.domIf.render(); stamped = x.shadowRoot.childNodes; assert.equal(stamped.length, 12); assert.equal(stamped[7].textContent.trim(), 'Stuff'); document.body.removeChild(x); }); test('binding to text nodes changed while if=false', function() { let x = document.createElement('x-textcontent'); document.body.appendChild(x); x.$.domIf.render(); let stamped = x.shadowRoot.childNodes; assert.equal(stamped.length, 12); assert.equal(stamped[7].textContent.trim(), 'Stuff'); x.$.domIf.if = false; x.$.domIf.render(); x.text = 'Hollaaaaa!'; stamped = x.shadowRoot.childNodes; assert.equal(stamped.length, 12); assert.equal(stamped[7].textContent.trim(), ''); x.$.domIf.if = true; x.$.domIf.render(); stamped = x.shadowRoot.childNodes; assert.equal(stamped.length, 12); assert.equal(stamped[7].textContent.trim(), 'Hollaaaaa!'); document.body.removeChild(x); }); }); suite('slot handling', function() { test('slots added/removed on if=true/false', function() { let x = document.createElement('x-slot'); let one = document.createElement('div'); one.slot = 'one'; x.appendChild(one); let two = document.createElement('div'); two.slot = 'two'; x.appendChild(two); let three = document.createElement('div'); three.slot = 'three'; x.appendChild(three); document.body.appendChild(x); x.$.domIf.render(); let stamped = x.shadowRoot.childNodes; assert.equal(stamped.length, 14); assert.equal(stamped[4].assignedNodes()[0], one); assert.equal(stamped[8].assignedNodes()[0], two); assert.equal(stamped[10].assignedNodes()[0], three); x.$.domIf.if = false; x.$.domIf.render(); stamped = x.shadowRoot.childNodes; assert.equal(stamped.length, 14); x.$.domIf.if = true; x.$.domIf.render(); stamped = x.shadowRoot.childNodes; assert.equal(stamped.length, 14); assert.equal(stamped[4].assignedNodes()[0], one); assert.equal(stamped[8].assignedNodes()[0], two); assert.equal(stamped[10].assignedNodes()[0], three); x.$.domIf.if = false; x.$.domIf.render(); const innerIf = x.shadowRoot.querySelector('#innerIf'); innerIf.if = false; innerIf.render(); x.$.domIf.if = true; x.$.domIf.render(); stamped = x.shadowRoot.childNodes; assert.equal(stamped[4].assignedNodes()[0], one); assert.equal(stamped[7].assignedNodes()[0], two); assert.equal(stamped[9].assignedNodes()[0], three); document.body.removeChild(x); }); }); suite('attach/detach tests', function() { test('move domif (clients persist)', function(done) { let domif = document.querySelector('#simple'); domif.if = true; innerContainer.appendChild(domif); setTimeout(function() { let clients = innerContainer.querySelectorAll('x-client'); // Same clients as before since move happened in one turn assert.equal(clients[0].uid, 0); assert.equal(clients[1].uid, 1); assert.equal(clients[2].uid, 2); assert.equal(clients[1].previousElementSibling, clients[0]); assert.equal(clients[2].previousElementSibling, clients[1]); assert.equal(domif.previousElementSibling, clients[2]); done(); }); }); test('remove, wait, append domif (clients recreated)', function(done) { let domif = document.querySelector('#simple'); domif.if = true; innerContainer.removeChild(domif); setTimeout(function() { let clients = innerContainer.querySelectorAll('x-client'); assert.equal(clients.length, 0); innerContainer.appendChild(domif); setTimeout(function() { let clients = outerContainer.querySelectorAll('x-client'); // New clients since removed for a turn assert.equal(clients[0].uid, 3); assert.equal(clients[1].uid, 4); assert.equal(clients[2].uid, 5); assert.equal(clients[1].previousElementSibling, clients[0]); assert.equal(clients[2].previousElementSibling, clients[1]); assert.equal(domif.previousElementSibling, clients[2]); done(); }); }); }); test('move host with domif (clients persist)', function(done) { let host = document.createElement('x-host'); outerContainer.appendChild(host); setTimeout(function() { let clients = host.shadowRoot.querySelectorAll('x-client'); // New clients created in host instance assert.equal(clients[0].uid, 6); assert.equal(clients[1].uid, 7); assert.equal(clients[2].uid, 8); assert.equal(clients[1].previousElementSibling, clients[0]); assert.equal(clients[2].previousElementSibling, clients[1]); assert.equal(host.$.domif.previousElementSibling, clients[2]); innerContainer.appendChild(host); setTimeout(function() { let clients = host.shadowRoot.querySelectorAll('x-client'); // Clients in removed host persist assert.equal(clients[0].uid, 6); assert.equal(clients[1].uid, 7); assert.equal(clients[2].uid, 8); assert.equal(clients[1].previousElementSibling, clients[0]); assert.equal(clients[2].previousElementSibling, clients[1]); assert.equal(host.$.domif.previousElementSibling, clients[2]); done(); }); }); }); test('remove, wait, append host with domif (clients persist)', function(done) { let host = document.createElement('x-host'); outerContainer.appendChild(host); setTimeout(function() { let clients = host.shadowRoot.querySelectorAll('x-client'); // New clients created in host instance assert.equal(clients[0].uid, 9); assert.equal(clients[1].uid, 10); assert.equal(clients[2].uid, 11); assert.equal(clients[1].previousElementSibling, clients[0]); assert.equal(clients[2].previousElementSibling, clients[1]); assert.equal(host.$.domif.previousElementSibling, clients[2]); outerContainer.removeChild(host); setTimeout(function() { // Clients in removed host persist assert.equal(clients[0].uid, 9); assert.equal(clients[1].uid, 10); assert.equal(clients[2].uid, 11); assert.equal(clients[1].previousElementSibling, clients[0]); assert.equal(clients[2].previousElementSibling, clients[1]); assert.equal(host.$.domif.previousElementSibling, clients[2]); innerContainer.appendChild(host); setTimeout(function() { // Clients in removed host persist let clients = host.shadowRoot.querySelectorAll('x-client'); assert.equal(clients[0].uid, 9); assert.equal(clients[1].uid, 10); assert.equal(clients[2].uid, 11); assert.equal(clients[1].previousElementSibling, clients[0]); assert.equal(clients[2].previousElementSibling, clients[1]); assert.equal(host.$.domif.previousElementSibling, clients[2]); done(); }); }); }); }); test('remove, append domif', function(done) { let domif = document.querySelector('#simple'); let parent = domif.parentNode; domif.if = true; parent.removeChild(domif); setTimeout(function() { let clients = parent.querySelectorAll('x-client'); assert.equal(clients.length, 0); parent.appendChild(domif); setTimeout(function() { let clients = parent.querySelectorAll('x-client'); assert.equal(clients[0].uid, 12); assert.equal(clients[1].uid, 13); assert.equal(clients[2].uid, 14); assert.equal(clients[1].previousElementSibling, clients[0]); assert.equal(clients[2].previousElementSibling, clients[1]); assert.equal(domif.previousElementSibling, clients[2]); done(); }); }); }); test('move into doc fragment', function(done) { let el = shouldBeRemoved; assert.equal(el.parentNode, removalContainer); let frag = document.createDocumentFragment(); frag.appendChild(toBeRemoved); setTimeout(function() { assert.equal(el.parentNode, null); removalContainer.appendChild(frag); setTimeout(function() { assert.equal(shouldBeRemoved.parentNode, removalContainer); done(); }); }); }); test('move into shadow root', function(done) { if (Polymer.Settings.hasShadow) { let el = shouldBeRemoved; assert.equal(el.parentNode, removalContainer); let div = document.createElement('div'); document.body.appendChild(div); let frag = div.createShadowRoot(); frag.appendChild(toBeRemoved); setTimeout(function() { assert.equal(el.parentNode, frag); done(); }); } else { done(); } }); }); suite('timing', function() { test('non-upgrade case finds template', function() { assert.equal(nonUpgrade.textContent.trim(), 'stamped'); }); }); [true, false].forEach(function(restamp) { suite('ordering, restamp: ' + restamp, function() { test('effects in if not run when `if` goes false via property', function() { let el = document.createElement('x-guard-prop'); el.restamp = restamp; document.body.appendChild(el); el.bool = true; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), 'true'); el.bool = false; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), ''); document.body.removeChild(el); }); test('effects in if not run when `if` goes false via inline function', function() { let el = document.createElement('x-guard-inline'); el.restamp = restamp; document.body.appendChild(el); el.bool = true; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), 'true'); el.bool = false; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), ''); document.body.removeChild(el); }); test('effects in if not run when `if` goes false via computed property', function() { let el = document.createElement('x-guard-computed'); el.restamp = restamp; document.body.appendChild(el); el.bool = true; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), 'true'); el.bool = false; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), ''); document.body.removeChild(el); }); test('effects in if not run when `if` goes false via object sub-property', function() { let el = document.createElement('x-guard-object'); el.restamp = restamp; document.body.appendChild(el); el.obj = {bool: true}; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), 'true'); el.obj = {bool: false}; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), ''); document.body.removeChild(el); }); test('effects in if not run when `if` goes false via computed from object sub-property', function() { let el = document.createElement('x-guard-object-computed'); el.restamp = restamp; document.body.appendChild(el); el.obj = {bool: true}; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), 'true'); el.obj = {bool: false}; Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), ''); document.body.removeChild(el); }); test('effects in if not run when `if` goes false via setProperties batch', function() { let el = document.createElement('x-guard-separate-props'); el.restamp = restamp; document.body.appendChild(el); el.setProperties({a: 'ok', b: true}); Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), 'ok'); el.setProperties({a: 'notok', b: false}); Polymer.flush(); assert.equal(el.guarded.callCount, 1); assert.equal(el.shadowRoot.textContent.trim(), ''); document.body.removeChild(el); }); test('host properties in sync when changed while false', function() { let el = document.createElement('x-guard-separate-props'); el.restamp = restamp; document.body.appendChild(el); el.a = 'ok'; el.b = true; Polymer.flush(); assert.equal(el.shadowRoot.textContent.trim(), 'ok'); el.b = false; el.a = 'notok'; Polymer.flush(); assert.equal(el.shadowRoot.textContent.trim(), ''); el.a = 'changed'; el.b = true; Polymer.flush(); assert.equal(el.shadowRoot.textContent.trim(), 'changed'); document.body.removeChild(el); }); test('host paths in sync when changed while false', function() { let el = document.createElement('x-guard-separate-paths'); el.restamp = restamp; document.body.appendChild(el); el.obj = {a: 'ok', b: true}; Polymer.flush(); assert.equal(el.shadowRoot.textContent.trim(), 'ok'); el.set('obj.b', false); el.set('obj.a', 'notok'); Polymer.flush(); assert.equal(el.shadowRoot.textContent.trim(), ''); el.set('obj.a', 'changed'); el.set('obj.b', true); Polymer.flush(); assert.equal(el.shadowRoot.textContent.trim(), 'changed'); document.body.removeChild(el); }); }); }); </script> </body> </html>