mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
529 lines
14 KiB
HTML
529 lines
14 KiB
HTML
<!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="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
|
|
<script src="wct-browser-config.js"></script>
|
|
<script src="../../node_modules/wct-browser-legacy/browser.js"></script>
|
|
<script type="module" src="../../polymer-legacy.js"></script>
|
|
</head>
|
|
<body>
|
|
<script type="module">
|
|
window.configureBehavior = {
|
|
|
|
changeHandlerCount: 0,
|
|
objectChangeHandlerCount: 0,
|
|
|
|
contentChanged: function() {
|
|
this.changeHandlerCount++;
|
|
this.stomp = 10;
|
|
},
|
|
objectChanged: function() {
|
|
this.objectChangeHandlerCount++;
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<dom-module id="x-configure-value">
|
|
<template>
|
|
<span id="content">{{content}}</span>
|
|
</template>
|
|
<script type="module">
|
|
import { Polymer } from '../../polymer-legacy.js';
|
|
Polymer({
|
|
|
|
is: 'x-configure-value',
|
|
|
|
behaviors: [window.configureBehavior],
|
|
|
|
properties: {
|
|
content: {
|
|
type: String,
|
|
notify: true,
|
|
observer: 'contentChanged',
|
|
value: 'default'
|
|
},
|
|
object: {
|
|
type: Object,
|
|
notify: true,
|
|
value: function() { return {foo: 'obj-default'}; },
|
|
observer: 'objectChanged'
|
|
},
|
|
readOnly: {
|
|
readOnly: true,
|
|
value: 'default'
|
|
},
|
|
stomp: {
|
|
value: 5
|
|
}
|
|
}
|
|
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-configure-gchild">
|
|
<template>
|
|
<span id="content">{{content}}</span>
|
|
</template>
|
|
<script type="module">
|
|
import { Polymer } from '../../polymer-legacy.js';
|
|
Polymer({
|
|
|
|
is: 'x-configure-gchild',
|
|
|
|
behaviors: [window.configureBehavior],
|
|
|
|
properties: {
|
|
content: {
|
|
type: String,
|
|
notify: true,
|
|
observer: 'contentChanged',
|
|
value: 'gchild'
|
|
},
|
|
object: {
|
|
type: Object,
|
|
notify: true,
|
|
value: function() { return {foo: 'obj-default'}; },
|
|
observer: 'objectChanged'
|
|
},
|
|
readOnly: {
|
|
readOnly: true,
|
|
value: 'default'
|
|
},
|
|
stomp: {
|
|
value: 5
|
|
}
|
|
}
|
|
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-configure-child">
|
|
<template>
|
|
<x-configure-gchild id="gchild" content="{{content}}" object="{{object}}"></x-configure-gchild>
|
|
</template>
|
|
<script type="module">
|
|
import { Polymer } from '../../polymer-legacy.js';
|
|
Polymer({
|
|
|
|
is: 'x-configure-child',
|
|
|
|
behaviors: [window.configureBehavior],
|
|
|
|
properties: {
|
|
content: {
|
|
type: String,
|
|
notify: true,
|
|
observer: 'contentChanged',
|
|
value: 'child'
|
|
},
|
|
negatedContent: {
|
|
type: Boolean,
|
|
observer: 'negatedContentChanged',
|
|
value: true
|
|
},
|
|
compoundInput: {
|
|
type: String,
|
|
observer: 'compoundInputChanged',
|
|
value: 'default'
|
|
},
|
|
object: {
|
|
type: Object,
|
|
notify: true,
|
|
value: function() { return {foo: 'obj-default'}; },
|
|
observer: 'objectChanged'
|
|
},
|
|
readOnly: {
|
|
readOnly: true,
|
|
value: 'default'
|
|
},
|
|
stomp: {
|
|
value: 5
|
|
},
|
|
attrDash: {
|
|
observer: 'attrDashChanged',
|
|
value: 'default'
|
|
},
|
|
attrNumber: {
|
|
type: Number,
|
|
observer: 'attrNumberChanged',
|
|
value: 0
|
|
},
|
|
attrBoolean: {
|
|
type: Boolean,
|
|
observer: 'attrBooleanChanged',
|
|
value: false
|
|
}
|
|
},
|
|
|
|
created: function() {
|
|
this.attrDashChanged = sinon.spy();
|
|
this.attrNumberChanged = sinon.spy();
|
|
this.attrBooleanChanged = sinon.spy();
|
|
this.negatedContentChanged = sinon.spy();
|
|
this.compoundInputChanged = sinon.spy();
|
|
}
|
|
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-configure-simple-child">
|
|
<script type="module">
|
|
import { Polymer } from '../../polymer-legacy.js';
|
|
Polymer({
|
|
|
|
is: 'x-configure-simple-child',
|
|
|
|
properties: {
|
|
noeffect: String
|
|
},
|
|
|
|
ready: function() {
|
|
this.hasPropertyAtReadyTime = (this.noeffect !== undefined);
|
|
}
|
|
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-configure-host">
|
|
<template>
|
|
<x-configure-child id="child"
|
|
content="{{content}}"
|
|
negated-content="[[!content]]"
|
|
compound-input="a [[simple]] [[content]]"
|
|
object="{{object.goo}}"
|
|
attr$="{{attrValue}}"
|
|
attr-dash$="{{attrValue}}"
|
|
attr-number$="{{attrNumber}}"
|
|
attr-boolean$="{{attrBoolean}}"
|
|
></x-configure-child>
|
|
<x-configure-simple-child id="simple" noeffect="{{simple}}"></x-configure-simple-child>
|
|
</template>
|
|
<script type="module">
|
|
import { Polymer } from '../../polymer-legacy.js';
|
|
Polymer({
|
|
|
|
is: 'x-configure-host',
|
|
|
|
behaviors: [window.configureBehavior],
|
|
|
|
properties: {
|
|
content: {
|
|
type: String,
|
|
notify: true,
|
|
observer: 'contentChanged',
|
|
value: 'host'
|
|
},
|
|
object: {
|
|
type: Object,
|
|
notify: true,
|
|
value: function() { return {goo: {foo: 'obj-host'}}; },
|
|
observer: 'objectChanged'
|
|
},
|
|
readOnly: {
|
|
readOnly: true,
|
|
value: 'default'
|
|
},
|
|
stomp: {
|
|
value: 5
|
|
},
|
|
attrValue: {
|
|
value: 'attrValue'
|
|
},
|
|
attrNumber: {
|
|
value: 42
|
|
},
|
|
attrBoolean: {
|
|
value: false
|
|
},
|
|
simple: {
|
|
value: 'simple'
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<script type="module">
|
|
window.XConfigLazy = {
|
|
is: 'x-config-lazy',
|
|
properties: {
|
|
noEffectProp: Number,
|
|
defaultUsesNoEffectProp: {
|
|
type: Number
|
|
},
|
|
boundNoEffectProp: {
|
|
type: Number,
|
|
value: 5
|
|
},
|
|
prop: {
|
|
value: 'lazy',
|
|
observer: 'propChanged'
|
|
},
|
|
readOnlyProp: {
|
|
readOnly: true,
|
|
value: 'readOnly'
|
|
},
|
|
hadAttrProp: {
|
|
value: 'hadAttrProp',
|
|
observer: 'hadAttrPropChanged'
|
|
}
|
|
},
|
|
created: function() {
|
|
this.noEffectProp = 1;
|
|
this.defaultUsesNoEffectProp = this.noEffectProp * 2;
|
|
this.propChanged = sinon.spy();
|
|
this.hadAttrPropChanged = sinon.spy();
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<dom-module id="x-config-lazy-nodefaults">
|
|
<template>
|
|
<div>x-config-lazy-nodefaults</div>
|
|
</template>
|
|
<script type="module">
|
|
window.XConfigLazyNoDefaults = {
|
|
is: 'x-config-lazy-nodefaults',
|
|
properties: {
|
|
prop: {
|
|
observer: 'propChanged'
|
|
}
|
|
},
|
|
created: function() {
|
|
this.propChanged = sinon.spy();
|
|
}
|
|
};
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-config-lazy-host">
|
|
<template>
|
|
<x-config-lazy id="lazy" prop="{{foo}}" read-only-prop="{{foo}}" had-attr-prop="attrValue" bound-no-effect-prop="{{foo}}"></x-config-lazy>
|
|
<x-config-lazy-nodefaults prop="[[foo]]"></x-config-lazy-nodefaults>
|
|
</template>
|
|
<script type="module">
|
|
import { Polymer } from '../../polymer-legacy.js';
|
|
Polymer({
|
|
is: 'x-config-lazy-host',
|
|
properties: {
|
|
foo: {
|
|
value: 'foo',
|
|
observer: 'fooChanged'
|
|
}
|
|
},
|
|
fooChanged: function(foo) {
|
|
this.$.lazy.hadAttrProp = foo;
|
|
}
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<x-configure-value></x-configure-value>
|
|
|
|
<x-configure-value content="attr" object='{"foo": "obj-attr"}'></x-configure-value>
|
|
|
|
<x-configure-host></x-configure-host>
|
|
|
|
<x-configure-host content="attr"></x-configure-host>
|
|
|
|
<script type="module">
|
|
import { Polymer } from '../../polymer-legacy.js';
|
|
|
|
function testValueAndChangeHandler(e, value) {
|
|
assert.equal(e.content, value, 'Property does not equal configured value');
|
|
assert.equal(e.changeHandlerCount, 1, 'property `change` Change handler not run when default value set');
|
|
assert.equal(e.objectChangeHandlerCount, 1, 'property `object` Change handler not run when default value set');
|
|
}
|
|
|
|
function testConfigure(e, value, objectValue) {
|
|
testValueAndChangeHandler(e, value);
|
|
assert.equal(e.object.foo, objectValue);
|
|
assert.equal(e.$.content.textContent, value, 'Bound value not propagated to dom');
|
|
}
|
|
|
|
function testConfigureHost(e, value) {
|
|
testValueAndChangeHandler(e, value);
|
|
e = e.$.child;
|
|
testValueAndChangeHandler(e, value);
|
|
e = e.$.gchild;
|
|
testValueAndChangeHandler(e, value);
|
|
assert.equal(e.$.content.textContent, value, 'Bound value not propagated to dom');
|
|
}
|
|
|
|
suite('configure', function() {
|
|
|
|
test('value set in properties initializes correctly', function() {
|
|
var e = document.querySelector('x-configure-value');
|
|
testConfigure(e, 'default', 'obj-default');
|
|
});
|
|
|
|
test('attribute overrides value set in properties', function() {
|
|
var e = document.querySelector('x-configure-value[content]');
|
|
testConfigure(e, 'attr', 'obj-attr');
|
|
});
|
|
|
|
test('configured values initialize and propagates', function() {
|
|
var e = document.querySelector('x-configure-host');
|
|
testConfigureHost(e, 'host');
|
|
});
|
|
|
|
test('negated value configured correctly', function() {
|
|
var e = document.querySelector('x-configure-host');
|
|
assert.equal(e.$.child.negatedContent, false);
|
|
assert.isTrue(e.$.child.negatedContentChanged.calledOnce, 'negated content not changed exactly once');
|
|
});
|
|
|
|
test('compound effect resulting value set once', function() {
|
|
var e = document.querySelector('x-configure-host');
|
|
|
|
assert.equal(e.$.child.compoundInput, 'a simple host');
|
|
assert.isTrue(e.$.child.compoundInputChanged.calledOnce, 'compound content not changed exactly once');
|
|
});
|
|
|
|
test('attribute overrides configured values and propagates', function() {
|
|
var e = document.querySelector('x-configure-host[content]');
|
|
testConfigureHost(e, 'attr');
|
|
});
|
|
|
|
test('property changed in change handler of another not stomped by default', function() {
|
|
var e = document.querySelector('x-configure-value');
|
|
assert.equal(e.stomp, 10);
|
|
});
|
|
|
|
test('read-only property initialized to default value', function() {
|
|
var e = document.querySelector('x-configure-value');
|
|
assert.equal(e.readOnly, 'default');
|
|
});
|
|
|
|
test('attribute bindings to properties without effects not configured', function() {
|
|
var e = document.querySelector('x-configure-host');
|
|
assert.equal(e.$.child.getAttribute('attr'), 'attrValue');
|
|
assert.equal(e.$.child.attr, undefined);
|
|
});
|
|
|
|
test('attribute bindings to properties with effects configured', function() {
|
|
var e = document.createElement('x-configure-host');
|
|
document.body.appendChild(e);
|
|
|
|
assert.equal(e.$.child.getAttribute('attr-dash'), 'attrValue');
|
|
assert.notProperty(e.$.child, 'attr-dash');
|
|
assert.equal(e.$.child.attrDash, 'attrValue');
|
|
assert.isTrue(e.$.child.attrDashChanged.calledOnce);
|
|
assert.equal(e.$.child.attrDashChanged.getCall(0).args[0], 'attrValue');
|
|
|
|
assert.equal(e.$.child.getAttribute('attr-number'), '42');
|
|
assert.notProperty(e.$.child, 'attr-number');
|
|
assert.strictEqual(e.$.child.attrNumber, 42);
|
|
assert.isTrue(e.$.child.attrNumberChanged.calledOnce);
|
|
assert.strictEqual(e.$.child.attrNumberChanged.getCall(0).args[0], 42);
|
|
|
|
assert.equal(e.$.child.hasAttribute('attr-boolean'), false);
|
|
assert.notProperty(e.$.child, 'attr-boolean');
|
|
// Attribute bindings are no longer specially
|
|
// configured to properties as they were with 1.0. This should
|
|
// only affect bindings that set false (removing a non-existing attribute)
|
|
// to override a default of true (which is an odd default for a boolean attr).
|
|
assert.strictEqual(e.$.child.attrBoolean, false);
|
|
assert.isTrue(e.$.child.attrBooleanChanged.calledOnce);
|
|
assert.strictEqual(e.$.child.attrBooleanChanged.getCall(0).args[0], false);
|
|
});
|
|
|
|
test('bindings to properties without effects configured', function() {
|
|
var e = document.createElement('x-configure-host');
|
|
document.body.appendChild(e);
|
|
assert.isTrue(e.$.simple.hasPropertyAtReadyTime, 'property value not configured and therefore not set at ready time');
|
|
});
|
|
|
|
test('pre-register property assignment does not break getters and setters', function() {
|
|
var x = document.createElement('x-late-register');
|
|
document.body.appendChild(x);
|
|
// set property
|
|
x.shouldChange = '1';
|
|
// now register element
|
|
Polymer({
|
|
is: 'x-late-register',
|
|
properties: {
|
|
shouldChange : {
|
|
observer: 'shouldChangeCallback',
|
|
type: String
|
|
}
|
|
},
|
|
shouldChangeCallback: function() {
|
|
this.textContent = this.shouldChange;
|
|
}
|
|
});
|
|
assert.equal(x.shouldChange, '1');
|
|
assert.equal(x.shouldChange, x.textContent);
|
|
x.shouldChange = '2';
|
|
assert.equal(x.shouldChange, '2');
|
|
assert.equal(x.shouldChange, x.textContent);
|
|
document.body.removeChild(x);
|
|
});
|
|
|
|
// Created is no longer called before
|
|
// default properties are set. This means values set in created cannot
|
|
// be used to calculate defaults. However, defaults can now be set for
|
|
// any property (including those with effects) in created.
|
|
test('setting properties in created works with configuration', function() {
|
|
var x = document.createElement('x-late-register2');
|
|
document.body.appendChild(x);
|
|
// now register element
|
|
Polymer({
|
|
is: 'x-late-register2',
|
|
properties: {
|
|
a: {
|
|
type: Number,
|
|
value: 0
|
|
},
|
|
b: {
|
|
type: Number
|
|
}
|
|
},
|
|
created: function() {
|
|
this.a = 1;
|
|
this.b = this.a * 2;
|
|
}
|
|
});
|
|
assert.equal(x.b, 2);
|
|
document.body.removeChild(x);
|
|
});
|
|
|
|
test('lazy upgrade binding use cases', function() {
|
|
var el = document.createElement('x-config-lazy-host');
|
|
document.body.appendChild(el);
|
|
Polymer(window.XConfigLazy);
|
|
// The purpose of this test is to test lazy upgrading an element that
|
|
// has a property pre-bound to it (that has an accessor) but that has
|
|
// no defaults for it (stresses a prior bug in ready() code that called
|
|
// _attachDom twice, which throws in Safari's native SD
|
|
Polymer(window.XConfigLazyNoDefaults);
|
|
assert.equal(el.$.lazy.noEffectProp, 1);
|
|
assert.equal(el.$.lazy.defaultUsesNoEffectProp, 2);
|
|
assert.equal(el.$.lazy.boundNoEffectProp, 'foo');
|
|
assert.equal(el.$.lazy.prop, 'foo');
|
|
assert.isTrue(el.$.lazy.propChanged.calledOnce);
|
|
assert.equal(el.$.lazy.readOnlyProp, 'readOnly');
|
|
assert.equal(el.$.lazy.hadAttrProp, 'foo');
|
|
assert.isTrue(el.$.lazy.hadAttrPropChanged.calledOnce);
|
|
document.body.removeChild(el);
|
|
});
|
|
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|