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

359 lines (333 loc) 13.2 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> <script src="../../../webcomponentsjs/webcomponents-lite.js"></script> <script> Polymer = { strictTemplatePolicy: true }; // Errors thrown in custom element reactions are not thrown up // the call stack to the dom methods that provoked them, so need // to catch them here and prevent mocha from complaining about them window.addEventListener('error', event => { if (window.uncaughtErrorFilter && window.uncaughtErrorFilter(event)) { event.preventDefault(); event.stopImmediatePropagation(); } }); </script> <script src="../../../web-component-tester/browser.js"></script> <link rel="import" href="../../polymer.html"> <script> HTMLImports.whenReady(() => { // Errors thrown in Polymer's debouncer queue get re-thrown // via setTimeout, making them particulary difficult to verify; // Wrap debouncer callbacks and store on the globalError to test later const debounce = Polymer.Debouncer.debounce; Polymer.Debouncer.debounce = function(debouncer, asyncModule, callback) { return debounce(debouncer, asyncModule, function() { try { callback(); } catch(error) { if (!window.uncaughtErrorFilter || !window.uncaughtErrorFilter(error)) { throw error; } } }); }; }); </script> </head> <body> <dom-module id="trusted-element"> <template>Trusted</template> <script> HTMLImports.whenReady(function() { class TrustedElement extends Polymer.Element { static get is() { return 'trusted-element'; } } customElements.define(TrustedElement.is, TrustedElement); }); </script> </dom-module> <dom-module id="trusted-element-legacy"> <template>Trusted</template> <script> HTMLImports.whenReady(function() { Polymer({is: 'trusted-element-legacy'}); }); </script> </dom-module> <dom-module id="trusted-templates"> <template> <dom-repeat items="[0]"> <template> <div id="dom-repeat-ok"></div> <dom-if if> <template><div id="nested-dom-if-ok"></div></template> </dom-if> </template> </dom-repeat> <dom-if if> <template> <div id="dom-if-ok"></div> <dom-repeat items="[0]"> <template> <div id="nested-dom-repeat-ok"></div> </template> </dom-repeat> </template> </dom-if> </template> <script> HTMLImports.whenReady(function() { class TrustedTemplates extends Polymer.Element { static get is() { return 'trusted-templates'; } } customElements.define(TrustedTemplates.is, TrustedTemplates); }); </script> </dom-module> <dom-module id="trusted-templates-legacy"> <template> <template is="dom-repeat" items="[0]"> <div id="dom-repeat-ok"></div> <template is="dom-if" if><div id="nested-dom-if-ok"></div></template> </template> <template is="dom-if" if> <div id="dom-if-ok"></div> <template is="dom-repeat" items="[0]"><div id="nested-dom-repeat-ok"></div></template> </template> </template> <script> HTMLImports.whenReady(function() { Polymer({is: 'trusted-templates-legacy'}); }); </script> </dom-module> <div id="target"></div> <script> suite('strictTemplatePolicy', function() { // Capture mocha's default onerror const onerror = window.onerror; const topOnerror = window.top.topOnerror; function restoreOnError() { window.onerror = onerror; window.top.onerror = topOnerror; window.uncaughtErrorFilter = window.top.uncaughtErrorFilter = null; } teardown(function() { // Restore mocha's onerror restoreOnError(); document.getElementById('target').textContent = ''; }); // Errors thrown in custom element reactions are not thrown up // the call stack to the dom methods that provoked them, so this // wraps Chai's assert.throws to re-throw uncaught errors function assertThrows(fn, re) { // Safari does not forward error messages re = new RegExp('(' + re.toString().slice(1,-1) + ')|(Script error\\.)', re.flags); // Catch uncaught errors; note when running in iframe sometimes // Safari errors are thrown on the top window, sometimes not, so // catch in both places let uncaughtError = null; window.onerror = window.top.onerror = window.uncaughtErrorFilter = window.top.uncaughtErrorFilter = function(err) { if (!uncaughtError) { uncaughtError = err instanceof Error ? err : new Error(err.message || err); } return true; }; assert.throws(function() { fn(); // Re-throw any uncaughtErrors if (uncaughtError) { throw uncaughtError; } // Force polyfill reactions and/or async template stamping Polymer.flush(); // Re-throw any uncaughtErrors if (uncaughtError) { throw uncaughtError; } }, re); restoreOnError(); } test('dom-bind', function() { assertThrows(function() { document.getElementById('target').innerHTML = '<dom-bind>' + ' <template>' + ' <div id="injected"></div>'+ ' </template>`' + '</dom-bind>'; }, /dom-bind not allowed/); assert.notOk(document.getElementById('injected')); }); test('dom-if', function() { assertThrows(function() { document.getElementById('target').innerHTML = '<dom-if if>' + ' <template>' + ' <div id="injected"></div>'+ ' </template>' + '</dom-if>'; }, /template owner not trusted/); assert.notOk(document.getElementById('injected')); }); test('dom-repeat', function() { assertThrows(function() { document.getElementById('target').innerHTML = '<dom-repeat items="[0]">' + ' <template>' + ' <div id="injected"></div>'+ ' </template>`' + '</dom-repeat>'; }, /template owner not trusted/); assert.notOk(document.getElementById('injected')); }); test('dom-module after registration', function() { assertThrows(function() { document.getElementById('target').innerHTML = '<dom-module id="trusted-element">' + ' <template>' + ' <div id="injected"></div>'+ ' </template>`' + '</dom-module>'; }, /trusted-element re-registered/); let el; assertThrows(function() { el = document.createElement('trusted-element'); document.getElementById('target').appendChild(el); }, /expecting dom-module or null template for trusted-element/); assert.notOk(el && el.shadowRoot); assert.notOk(document.getElementById('injected')); }); test('dom-module after registration, again', function() { assertThrows(function() { document.getElementById('target').innerHTML = '<dom-module id="trusted-element">' + ' <template>' + ' <div id="injected"></div>'+ ' </template>`' + '</dom-module>'; }, /trusted-element re-registered/); const el = document.createElement('trusted-element'); document.getElementById('target').appendChild(el); assert.notOk(el.shadowRoot); assert.notOk(document.getElementById('injected')); }); test('dom-module before registration', function() { document.getElementById('target').innerHTML = '<dom-module id="has-no-template">' + ' <template>' + ' <div id="injected"></div>'+ ' </template>`' + '</dom-module>'; class HasNoTemplate extends Polymer.Element { static get is() { return 'has-no-template'; } static get template() { return null; } } customElements.define(HasNoTemplate.is, HasNoTemplate); let el = document.createElement('has-no-template'); document.getElementById('target').appendChild(el); assert.notOk(el.shadowRoot); assert.notOk(document.getElementById('injected')); }); test('dom-module after registration (legacy)', function() { assertThrows(function() { document.getElementById('target').innerHTML = '<dom-module id="trusted-element-legacy">' + ' <template>' + ' <div id="injected"></div>'+ ' </template>`' + '</dom-module>'; }, /trusted-element-legacy re-registered/); let el; assertThrows(function() { el = document.createElement('trusted-element-legacy'); document.getElementById('target').appendChild(el); }, /expecting dom-module or null template for trusted-element-legacy/); assert.notOk(el && el.shadowRoot); assert.notOk(document.getElementById('injected')); }); test('dom-module after registration, again (legacy)', function() { assertThrows(function() { document.getElementById('target').innerHTML = '<dom-module id="trusted-element-legacy">' + ' <template>' + ' <div id="injected"></div>'+ ' </template>`' + '</dom-module>'; }, /trusted-element-legacy re-registered/); const el = document.createElement('trusted-element-legacy'); document.getElementById('target').appendChild(el); assert.notOk(el.shadowRoot); assert.notOk(document.getElementById('injected')); }); test('dom-module before registration (legacy)', function() { document.getElementById('target').innerHTML = '<dom-module id="has-no-template-legacy">' + ' <template>' + ' <div id="injected"></div>'+ ' </template>`' + '</dom-module>'; Polymer({ is: 'has-no-template-legacy', _template: null }); let el = document.createElement('has-no-template-legacy'); document.getElementById('target').appendChild(el); assert.notOk(el.shadowRoot); assert.notOk(document.getElementById('injected')); }); test('element without explicit template throws', function() { assertThrows(function() { class HasNoTemplateThrows extends Polymer.Element { static get is() { return 'has-no-template-throws'; } } customElements.define(HasNoTemplateThrows.is, HasNoTemplateThrows); var el = document.createElement('has-no-template-throws'); document.getElementById('target').appendChild(el); }, /expecting dom-module or null template/); }); test('element without explicit template throws (legacy)', function() { assertThrows(function() { Polymer({ is: 'has-no-template-throws-legacy' }); var el = document.createElement('has-no-template-throws-legacy'); document.getElementById('target').appendChild(el); }, /expecting dom-module or null template/); }); test('template helpers in trusted templates work', function() { var el = document.createElement('trusted-templates'); document.getElementById('target').appendChild(el); Polymer.flush(); assert.ok(el.shadowRoot.querySelector('#dom-repeat-ok')); assert.ok(el.shadowRoot.querySelector('#dom-if-ok')); assert.ok(el.shadowRoot.querySelector('#nested-dom-repeat-ok')); assert.ok(el.shadowRoot.querySelector('#nested-dom-if-ok')); }); test('template helpers in trusted templates work (legacy)', function() { var el = document.createElement('trusted-templates-legacy'); document.getElementById('target').appendChild(el); Polymer.flush(); assert.ok(el.shadowRoot.querySelector('#dom-repeat-ok')); assert.ok(el.shadowRoot.querySelector('#dom-if-ok')); assert.ok(el.shadowRoot.querySelector('#nested-dom-repeat-ok')); assert.ok(el.shadowRoot.querySelector('#nested-dom-if-ok')); }); }); </script> </body> </html>