@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
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>