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

372 lines (314 loc) 13.4 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="templatize-elements.html"> </head> <body> <template id="standalone"><div prop="[[prop]]">[[text]]</div></template> <script> suite('templatize basic', function() { let host; let childA; setup(function() { host = document.createElement('x-host'); document.body.appendChild(host); host.$.templatizeA.go(true); childA = host.shadowRoot.querySelector('#childA'); assert.ok(childA); }); teardown(function() { document.body.removeChild(host); }); test('stamped with initial data', function() { assert.equal(childA.outerProp, 'outerProp'); assert.equal(childA.outerObj, host.outerObj); assert.equal(childA.outerObjProp, 'outerObj.prop'); assert.equal(childA.prop, 'prop-a'); assert.equal(childA.obj, host.objA); assert.equal(childA.objProp, 'objA.prop'); }); test('host properties propagated in', function() { host.outerProp = 'outerProp++'; assert.equal(childA.outerProp, 'outerProp++'); host.outerObj = { prop: 'outerObj++.prop' }; assert.equal(childA.outerObj, host.outerObj); assert.equal(childA.outerObjProp, 'outerObj++.prop'); }); test('host paths propagated in', function() { sinon.spy(childA, 'outerObjChanged'); host.set('outerObj.prop', 'outerObj.prop++'); assert.equal(childA.outerObjProp, 'outerObj.prop++'); assert.isTrue(childA.outerObjChanged.calledOnce); assert.equal(childA.outerObjChanged.getCall(0).args[0].path, 'outerObj.prop'); assert.equal(childA.outerObjChanged.getCall(0).args[0].value, 'outerObj.prop++'); }); test('host properties propagated out', function() { childA.outerProp = 'outerProp++'; assert.equal(host.outerProp, 'outerProp++'); childA.outerObj = { prop: 'outerObj++.prop' }; assert.equal(host.outerObj.prop, 'outerObj++.prop'); }); test('host paths propagated out', function() { sinon.spy(host, 'outerObjChanged'); childA.set('outerObj.prop', 'outerObj.prop++'); assert.equal(host.outerObj.prop, 'outerObj.prop++'); assert.isTrue(host.outerObjChanged.calledOnce); assert.equal(host.outerObjChanged.getCall(0).args[0].path, 'outerObj.prop'); assert.equal(host.outerObjChanged.getCall(0).args[0].value, 'outerObj.prop++'); }); test('instance properties propagated in', function() { host.propA = 'prop-a++'; assert.equal(childA.prop, 'prop-a++'); host.objA = { prop: 'objA++.prop' }; assert.equal(childA.obj, host.objA); assert.equal(childA.objProp, 'objA++.prop'); }); test('instance paths propagated in', function() { sinon.spy(childA, 'objChanged'); host.set('objA.prop', 'objA.prop++'); assert.equal(childA.obj.prop, 'objA.prop++'); assert.isTrue(childA.objChanged.calledOnce); assert.equal(childA.objChanged.getCall(0).args[0].path, 'obj.prop'); assert.equal(childA.objChanged.getCall(0).args[0].value, 'objA.prop++'); }); test('instance properties propagated out', function() { childA.prop = 'prop-a++'; assert.equal(host.propA, 'prop-a++'); childA.obj = { prop: 'objA++.prop' }; assert.equal(host.objA.prop, 'objA++.prop'); }); test('instance paths propagated out', function() { sinon.spy(host, 'objAChanged'); childA.set('obj.prop', 'objA.prop++'); assert.equal(host.objA.prop, 'objA.prop++'); assert.isTrue(host.objAChanged.calledOnce); assert.equal(host.objAChanged.getCall(0).args[0].path, 'objA.prop'); assert.equal(host.objAChanged.getCall(0).args[0].value, 'objA.prop++'); }); test('outer & inner props conflict', function() { assert.equal(childA.conflict, 'bar'); host.set('outerInnerConflict.prop', 'foo'); assert.equal(childA.conflict, 'bar'); }); test('inline computed functions', function() { assert.equal(childA.computedFromLiteral, '33-prop-a'); }); test('ensure literals are not forwarded to templates', function() { assert.notOk(host._hasAccessor(33)); assert.notOk(Object.getOwnPropertyDescriptor(Object.getPrototypeOf(host), 33)); }); test('ensure undefined is not set on templatizee', function() { assert.equal(host.$.templatizeA[undefined], undefined); }); test('able to add gesture listeners', function() { assert.equal(host.handleTap.callCount, 0); childA.click(); assert.equal(host.handleTap.callCount, 1); }); test('listener event decorated with model', function() { host.outerProp = 'foo'; childA.click(); assert.equal(host.handleTap.callCount, 1); let event = host.handleTap.firstCall.args[0]; assert.instanceOf(event, Event); assert.ok(event.model); assert.equal(event.model.outerProp, 'foo'); host.outerProp = 'bar'; assert.equal(event.model.outerProp, 'bar'); assert.equal(event.model.parentModel, host); }); }); suite('templatize client with/without props', function() { let host; let childB; setup(function() { host = document.createElement('x-host'); document.body.appendChild(host); }); teardown(function() { document.body.removeChild(host); }); test('templatize with no dataHost', function() { host.shadowRoot.querySelector('[name=templatizeB]').go(true); childB = host.shadowRoot.querySelector('#childB'); assert.ok(childB); assert.equal(childB.computedFromLiteral, '33-prop-a'); }); test('templatize with no props', function() { host.shadowRoot.querySelector('[name=templatizeB]').go(false); childB = host.shadowRoot.querySelector('#childB'); assert.ok(childB); assert.isUndefined(childB.computedFromLiteral); }); test('templatize with no props, instance manually flushes', function() { let templatizeA = host.shadowRoot.querySelector('[id=templatizeA]'); templatizeA.go(false); let childA = host.shadowRoot.querySelector('#childA'); assert.ok(childA); sinon.spy(childA, 'objChanged'); assert.isUndefined(childA.obj); let o = {foo: true}; templatizeA.instance._setPendingProperty('obj', o); templatizeA.instance._flushProperties(); assert.equal(childA.obj, o); assert.isTrue(childA.objChanged.calledOnce); }); }); suite('templatizer behavior', function() { let host; let childC; setup(function() { host = document.createElement('x-host'); document.body.appendChild(host); host.$.templatizeC.go(true); childC = host.shadowRoot.querySelector('#childC'); assert.ok(childC); }); teardown(function() { document.body.removeChild(host); }); test('stamped with initial data', function() { assert.equal(childC.outerProp, 'outerProp'); assert.equal(childC.outerObj, host.outerObj); assert.equal(childC.outerObjProp, 'outerObj.prop'); assert.equal(childC.prop, 'prop-a'); assert.equal(childC.obj, host.objA); assert.equal(childC.objProp, 'objA.prop'); }); test('host properties propagated in', function() { host.outerProp = 'outerProp++'; assert.equal(childC.outerProp, 'outerProp++'); host.outerObj = { prop: 'outerObj++.prop' }; assert.equal(childC.outerObj, host.outerObj); assert.equal(childC.outerObjProp, 'outerObj++.prop'); }); test('host paths propagated in', function() { sinon.spy(childC, 'outerObjChanged'); host.set('outerObj.prop', 'outerObj.prop++'); assert.equal(childC.outerObjProp, 'outerObj.prop++'); assert.isTrue(childC.outerObjChanged.calledOnce); assert.equal(childC.outerObjChanged.getCall(0).args[0].path, 'outerObj.prop'); assert.equal(childC.outerObjChanged.getCall(0).args[0].value, 'outerObj.prop++'); }); test('host properties propagated out', function() { childC.outerProp = 'outerProp++'; assert.equal(host.outerProp, 'outerProp++'); childC.outerObj = { prop: 'outerObj++.prop' }; assert.equal(host.outerObj.prop, 'outerObj++.prop'); }); test('host paths propagated out', function() { sinon.spy(host, 'outerObjChanged'); childC.set('outerObj.prop', 'outerObj.prop++'); assert.equal(host.outerObj.prop, 'outerObj.prop++'); assert.isTrue(host.outerObjChanged.calledOnce); assert.equal(host.outerObjChanged.getCall(0).args[0].path, 'outerObj.prop'); assert.equal(host.outerObjChanged.getCall(0).args[0].value, 'outerObj.prop++'); }); test('instance properties propagated in', function() { host.propA = 'prop-a++'; assert.equal(childC.prop, 'prop-a++'); host.objA = { prop: 'objA++.prop' }; assert.equal(childC.obj, host.objA); assert.equal(childC.objProp, 'objA++.prop'); }); test('instance paths propagated in', function() { sinon.spy(childC, 'objChanged'); host.set('objA.prop', 'objA.prop++'); assert.equal(childC.obj.prop, 'objA.prop++'); assert.isTrue(childC.objChanged.calledOnce); assert.equal(childC.objChanged.getCall(0).args[0].path, 'obj.prop'); assert.equal(childC.objChanged.getCall(0).args[0].value, 'objA.prop++'); }); test('instance properties propagated out', function() { childC.prop = 'prop-a++'; assert.equal(host.propA, 'prop-a++'); childC.obj = { prop: 'objA++.prop' }; assert.equal(host.objA.prop, 'objA++.prop'); }); test('instance paths propagated out', function() { sinon.spy(host, 'objAChanged'); childC.set('obj.prop', 'objA.prop++'); assert.equal(host.objA.prop, 'objA.prop++'); assert.isTrue(host.objAChanged.calledOnce); assert.equal(host.objAChanged.getCall(0).args[0].path, 'objA.prop'); assert.equal(host.objAChanged.getCall(0).args[0].value, 'objA.prop++'); }); test('outer & inner props conflict', function() { assert.equal(childC.conflict, 'bar'); host.set('outerInnerConflict.prop', 'foo'); assert.equal(childC.conflict, 'bar'); }); test('inline computed functions', function() { assert.equal(childC.computedFromLiteral, '33-prop-a'); }); test('ensure literals are not forwarded to templates', function() { assert.notOk(host._hasAccessor(33)); assert.notOk(Object.getOwnPropertyDescriptor(Object.getPrototypeOf(host), 33)); }); test('ensure undefined is not set on templatizee', function() { assert.equal(host.$.templatizeA[undefined], undefined); }); test('able to add gesture listeners', function() { assert.equal(host.handleTap.callCount, 0); childC.click(); assert.equal(host.handleTap.callCount, 1); }); test('listener event decorated with model', function() { host.outerProp = 'foo'; childC.click(); assert.equal(host.handleTap.callCount, 1); let event = host.handleTap.firstCall.args[0]; assert.instanceOf(event, Event); assert.ok(event.model); assert.equal(event.model.outerProp, 'foo'); host.outerProp = 'bar'; assert.equal(event.model.outerProp, 'bar'); }); }); suite('templatize with no host', function() { test('stamped with initial data', function() { const template = document.getElementById('standalone').cloneNode(true); const Template = Polymer.Templatize.templatize(template); const inst = new Template({prop: 'prop', text: 'text'}); const div = inst.root.firstChild; assert.equal(div.prop, 'prop'); assert.equal(div.textContent, 'text'); }); test('stamped with no initial data', function() { const template = document.getElementById('standalone').cloneNode(true); const Template = Polymer.Templatize.templatize(template); const inst = new Template(); const div = inst.root.firstChild; assert.equal(div.prop, undefined); assert.equal(div.textContent.trim(), ''); inst.setProperties({prop: 'prop', text: 'text'}); assert.equal(div.prop, 'prop'); assert.equal(div.textContent, 'text'); }); test('notifies path data changes', function() { const template = document.getElementById('standalone').cloneNode(true); const Template = Polymer.Templatize.templatize(template); const inst = new Template(); const div = inst.root.firstChild; inst.setProperties({prop: {foo: true}}); assert.equal(div.prop.foo, true); inst.set('prop.foo', false); assert.equal(div.prop.foo, false); }); }); </script> </body> </html>