Bug 1417749 - Create a currency-amount Custom Element. r=marcosc

MozReview-Commit-ID: 1XF7UqvhQSy

--HG--
extra : rebase_source : 9eeb71ddaed32b0b9bde6a704d8bc87def0d4d1c
This commit is contained in:
Matthew Noorenberghe 2017-11-16 21:58:29 -08:00
Родитель 173968bc7a
Коммит 12e4204b4d
16 изменённых файлов: 487 добавлений и 10 удалений

Просмотреть файл

@ -353,6 +353,7 @@ toolkit/components/microformats/test/**
toolkit/components/microformats/microformat-shiv.js
toolkit/components/reader/Readability.js
toolkit/components/reader/JSDOMParser.js
toolkit/components/payments/res/vendor/*
# Uses preprocessing
toolkit/content/widgets/wizard.xml

Просмотреть файл

@ -12,3 +12,6 @@ toolkit.jar:
res/payments (res/paymentRequest.*)
res/payments/debugging.html (res/debugging.html)
res/payments/debugging.js (res/debugging.js)
res/payments/components/ (res/components/*.js)
res/payments/mixins/ (res/mixins/*.js)
res/payments/vendor/ (res/vendor/*)

Просмотреть файл

@ -16,6 +16,8 @@ EXTRA_COMPONENTS += [
JAR_MANIFESTS += ['jar.mn']
MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
SPHINX_TREES['docs'] = 'docs'
TESTING_JS_MODULES += [

Просмотреть файл

@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* <currency-amount value="7.5" currency="USD"></currency-amount>
*/
/* global ObservedPropertiesMixin */
class CurrencyAmount extends ObservedPropertiesMixin(HTMLElement) {
static get observedAttributes() {
return ["currency", "value"];
}
render() {
let output = "";
try {
if (this.value && this.currency) {
let number = Number.parseFloat(this.value);
if (Number.isNaN(number) || !Number.isFinite(number)) {
throw new RangeError("currency-amount value must be a finite number");
}
const formatter = new Intl.NumberFormat(navigator.languages, {
style: "currency",
currency: this.currency,
currencyDisplay: "symbol",
});
output = formatter.format(this.value);
}
} finally {
this.textContent = output;
}
}
}
customElements.define("currency-amount", CurrencyAmount);

Просмотреть файл

@ -0,0 +1,66 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Define getters and setters for observedAttributes converted to camelCase and
* trigger a batched aynchronous call to `render` upon observed
* attribute/property changes.
*/
/* exported ObservedPropertiesMixin */
function ObservedPropertiesMixin(superClass) {
return class ObservedProperties extends superClass {
constructor() {
super();
this._observedPropertiesMixin = {
pendingRender: false,
};
// Reflect property changes for `observedAttributes` to attributes.
for (let name of (this.constructor.observedAttributes || [])) {
if (name in this) {
// Don't overwrite existing properties.
continue;
}
// Convert attribute names from kebab-case to camelCase properties
Object.defineProperty(this, name.replace(/-([a-z])/g, ($0, $1) => $1.toUpperCase()), {
configurable: true,
get() {
return this.getAttribute(name);
},
set(value) {
if (value === null || value === undefined) {
this.removeAttribute(name);
} else {
this.setAttribute(name, value);
}
},
});
}
}
async _invalidateFromObservedPropertiesMixin() {
if (this._observedPropertiesMixin.pendingRender) {
return;
}
this._observedPropertiesMixin.pendingRender = true;
await Promise.resolve();
try {
this.render();
} finally {
this._observedPropertiesMixin.pendingRender = false;
}
}
attributeChangedCallback(attr, oldValue, newValue) {
if (oldValue === newValue) {
return;
}
this._invalidateFromObservedPropertiesMixin();
}
};
}

Просмотреть файл

@ -104,8 +104,9 @@ let PaymentRequest = {
let totalItem = this.request.paymentDetails.totalItem;
let totalEl = document.getElementById("total");
totalEl.querySelector(".value").textContent = totalItem.amount.value;
totalEl.querySelector(".currency").textContent = totalItem.amount.currency;
let currencyEl = totalEl.querySelector("currency-amount");
currencyEl.value = totalItem.amount.value;
currencyEl.currency = totalItem.amount.currency;
totalEl.querySelector(".label").textContent = totalItem.label;
},

Просмотреть файл

@ -8,6 +8,9 @@
<meta http-equiv="Content-Security-Policy" content="default-src 'self'"/>
<title></title>
<link rel="stylesheet" href="paymentRequest.css"/>
<script src="vendor/custom-elements.min.js"></script>
<script src="mixins/ObservedPropertiesMixin.js"></script>
<script src="components/currency-amount.js"></script>
<script src="paymentRequest.js"></script>
</head>
<body>
@ -16,8 +19,7 @@
<div id="total">
<h2 class="label"></h2>
<span class="value"></span>
<span class="currency"></span>
<currency-amount></currency-amount>
</div>
<div id="controls-container">
<button id="cancel">Cancel payment</button>

37
toolkit/components/payments/res/vendor/custom-elements.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,37 @@
(function(){
'use strict';var h=new function(){};var aa=new Set("annotation-xml color-profile font-face font-face-src font-face-uri font-face-format font-face-name missing-glyph".split(" "));function n(b){var a=aa.has(b);b=/^[a-z][.0-9_a-z]*-[\-.0-9_a-z]*$/.test(b);return!a&&b}function p(b){var a=b.isConnected;if(void 0!==a)return a;for(;b&&!(b.__CE_isImportDocument||b instanceof Document);)b=b.parentNode||(window.ShadowRoot&&b instanceof ShadowRoot?b.host:void 0);return!(!b||!(b.__CE_isImportDocument||b instanceof Document))}
function q(b,a){for(;a&&a!==b&&!a.nextSibling;)a=a.parentNode;return a&&a!==b?a.nextSibling:null}
function t(b,a,c){c=c?c:new Set;for(var d=b;d;){if(d.nodeType===Node.ELEMENT_NODE){var e=d;a(e);var f=e.localName;if("link"===f&&"import"===e.getAttribute("rel")){d=e.import;if(d instanceof Node&&!c.has(d))for(c.add(d),d=d.firstChild;d;d=d.nextSibling)t(d,a,c);d=q(b,e);continue}else if("template"===f){d=q(b,e);continue}if(e=e.__CE_shadowRoot)for(e=e.firstChild;e;e=e.nextSibling)t(e,a,c)}d=d.firstChild?d.firstChild:q(b,d)}}function u(b,a,c){b[a]=c};function v(){this.a=new Map;this.o=new Map;this.f=[];this.b=!1}function ba(b,a,c){b.a.set(a,c);b.o.set(c.constructor,c)}function w(b,a){b.b=!0;b.f.push(a)}function x(b,a){b.b&&t(a,function(a){return y(b,a)})}function y(b,a){if(b.b&&!a.__CE_patched){a.__CE_patched=!0;for(var c=0;c<b.f.length;c++)b.f[c](a)}}function z(b,a){var c=[];t(a,function(b){return c.push(b)});for(a=0;a<c.length;a++){var d=c[a];1===d.__CE_state?b.connectedCallback(d):A(b,d)}}
function B(b,a){var c=[];t(a,function(b){return c.push(b)});for(a=0;a<c.length;a++){var d=c[a];1===d.__CE_state&&b.disconnectedCallback(d)}}
function C(b,a,c){c=c?c:{};var d=c.w||new Set,e=c.s||function(a){return A(b,a)},f=[];t(a,function(a){if("link"===a.localName&&"import"===a.getAttribute("rel")){var c=a.import;c instanceof Node&&"complete"===c.readyState?(c.__CE_isImportDocument=!0,c.__CE_hasRegistry=!0):a.addEventListener("load",function(){var c=a.import;if(!c.__CE_documentLoadHandled){c.__CE_documentLoadHandled=!0;c.__CE_isImportDocument=!0;c.__CE_hasRegistry=!0;var f=new Set(d);f.delete(c);C(b,c,{w:f,s:e})}})}else f.push(a)},d);
if(b.b)for(a=0;a<f.length;a++)y(b,f[a]);for(a=0;a<f.length;a++)e(f[a])}
function A(b,a){if(void 0===a.__CE_state){var c=b.a.get(a.localName);if(c){c.constructionStack.push(a);var d=c.constructor;try{try{if(new d!==a)throw Error("The custom element constructor did not produce the element being upgraded.");}finally{c.constructionStack.pop()}}catch(m){throw a.__CE_state=2,m;}a.__CE_state=1;a.__CE_definition=c;if(c.attributeChangedCallback)for(c=c.observedAttributes,d=0;d<c.length;d++){var e=c[d],f=a.getAttribute(e);null!==f&&b.attributeChangedCallback(a,e,null,f,null)}p(a)&&
b.connectedCallback(a)}}}v.prototype.connectedCallback=function(b){var a=b.__CE_definition;a.connectedCallback&&a.connectedCallback.call(b)};v.prototype.disconnectedCallback=function(b){var a=b.__CE_definition;a.disconnectedCallback&&a.disconnectedCallback.call(b)};v.prototype.attributeChangedCallback=function(b,a,c,d,e){var f=b.__CE_definition;f.attributeChangedCallback&&-1<f.observedAttributes.indexOf(a)&&f.attributeChangedCallback.call(b,a,c,d,e)};function D(b,a){this.c=b;this.a=a;this.b=void 0;C(this.c,this.a);"loading"===this.a.readyState&&(this.b=new MutationObserver(this.f.bind(this)),this.b.observe(this.a,{childList:!0,subtree:!0}))}function E(b){b.b&&b.b.disconnect()}D.prototype.f=function(b){var a=this.a.readyState;"interactive"!==a&&"complete"!==a||E(this);for(a=0;a<b.length;a++)for(var c=b[a].addedNodes,d=0;d<c.length;d++)C(this.c,c[d])};function ca(){var b=this;this.b=this.a=void 0;this.f=new Promise(function(a){b.b=a;b.a&&a(b.a)})}function F(b){if(b.a)throw Error("Already resolved.");b.a=void 0;b.b&&b.b(void 0)};function G(b){this.i=!1;this.c=b;this.m=new Map;this.j=function(b){return b()};this.g=!1;this.l=[];this.u=new D(b,document)}
G.prototype.define=function(b,a){var c=this;if(!(a instanceof Function))throw new TypeError("Custom element constructors must be functions.");if(!n(b))throw new SyntaxError("The element name '"+b+"' is not valid.");if(this.c.a.get(b))throw Error("A custom element with name '"+b+"' has already been defined.");if(this.i)throw Error("A custom element is already being defined.");this.i=!0;var d,e,f,m,l;try{var g=function(b){var a=k[b];if(void 0!==a&&!(a instanceof Function))throw Error("The '"+b+"' callback must be a function.");
return a},k=a.prototype;if(!(k instanceof Object))throw new TypeError("The custom element constructor's prototype is not an object.");d=g("connectedCallback");e=g("disconnectedCallback");f=g("adoptedCallback");m=g("attributeChangedCallback");l=a.observedAttributes||[]}catch(r){return}finally{this.i=!1}a={localName:b,constructor:a,connectedCallback:d,disconnectedCallback:e,adoptedCallback:f,attributeChangedCallback:m,observedAttributes:l,constructionStack:[]};ba(this.c,b,a);this.l.push(a);this.g||
(this.g=!0,this.j(function(){return da(c)}))};function da(b){if(!1!==b.g){b.g=!1;for(var a=b.l,c=[],d=new Map,e=0;e<a.length;e++)d.set(a[e].localName,[]);C(b.c,document,{s:function(a){if(void 0===a.__CE_state){var e=a.localName,f=d.get(e);f?f.push(a):b.c.a.get(e)&&c.push(a)}}});for(e=0;e<c.length;e++)A(b.c,c[e]);for(;0<a.length;){for(var f=a.shift(),e=f.localName,f=d.get(f.localName),m=0;m<f.length;m++)A(b.c,f[m]);(e=b.m.get(e))&&F(e)}}}G.prototype.get=function(b){if(b=this.c.a.get(b))return b.constructor};
G.prototype.whenDefined=function(b){if(!n(b))return Promise.reject(new SyntaxError("'"+b+"' is not a valid custom element name."));var a=this.m.get(b);if(a)return a.f;a=new ca;this.m.set(b,a);this.c.a.get(b)&&!this.l.some(function(a){return a.localName===b})&&F(a);return a.f};G.prototype.v=function(b){E(this.u);var a=this.j;this.j=function(c){return b(function(){return a(c)})}};window.CustomElementRegistry=G;G.prototype.define=G.prototype.define;G.prototype.get=G.prototype.get;
G.prototype.whenDefined=G.prototype.whenDefined;G.prototype.polyfillWrapFlushCallback=G.prototype.v;var H=window.Document.prototype.createElement,ea=window.Document.prototype.createElementNS,fa=window.Document.prototype.importNode,ga=window.Document.prototype.prepend,ha=window.Document.prototype.append,ia=window.DocumentFragment.prototype.prepend,ja=window.DocumentFragment.prototype.append,I=window.Node.prototype.cloneNode,J=window.Node.prototype.appendChild,K=window.Node.prototype.insertBefore,L=window.Node.prototype.removeChild,M=window.Node.prototype.replaceChild,N=Object.getOwnPropertyDescriptor(window.Node.prototype,
"textContent"),O=window.Element.prototype.attachShadow,P=Object.getOwnPropertyDescriptor(window.Element.prototype,"innerHTML"),Q=window.Element.prototype.getAttribute,R=window.Element.prototype.setAttribute,S=window.Element.prototype.removeAttribute,T=window.Element.prototype.getAttributeNS,U=window.Element.prototype.setAttributeNS,ka=window.Element.prototype.removeAttributeNS,la=window.Element.prototype.insertAdjacentElement,ma=window.Element.prototype.prepend,na=window.Element.prototype.append,
V=window.Element.prototype.before,oa=window.Element.prototype.after,pa=window.Element.prototype.replaceWith,qa=window.Element.prototype.remove,ra=window.HTMLElement,W=Object.getOwnPropertyDescriptor(window.HTMLElement.prototype,"innerHTML"),sa=window.HTMLElement.prototype.insertAdjacentElement;function ta(){var b=X;window.HTMLElement=function(){function a(){var a=this.constructor,d=b.o.get(a);if(!d)throw Error("The custom element being constructed was not registered with `customElements`.");var e=d.constructionStack;if(!e.length)return e=H.call(document,d.localName),Object.setPrototypeOf(e,a.prototype),e.__CE_state=1,e.__CE_definition=d,y(b,e),e;var d=e.length-1,f=e[d];if(f===h)throw Error("The HTMLElement constructor was either called reentrantly for this constructor or called multiple times.");
e[d]=h;Object.setPrototypeOf(f,a.prototype);y(b,f);return f}a.prototype=ra.prototype;return a}()};function Y(b,a,c){function d(a){return function(d){for(var c=[],e=0;e<arguments.length;++e)c[e-0]=arguments[e];for(var e=[],f=[],k=0;k<c.length;k++){var r=c[k];r instanceof Element&&p(r)&&f.push(r);if(r instanceof DocumentFragment)for(r=r.firstChild;r;r=r.nextSibling)e.push(r);else e.push(r)}a.apply(this,c);for(c=0;c<f.length;c++)B(b,f[c]);if(p(this))for(c=0;c<e.length;c++)f=e[c],f instanceof Element&&z(b,f)}}c.h&&(a.prepend=d(c.h));c.append&&(a.append=d(c.append))};function ua(){var b=X;u(Document.prototype,"createElement",function(a){if(this.__CE_hasRegistry){var c=b.a.get(a);if(c)return new c.constructor}a=H.call(this,a);y(b,a);return a});u(Document.prototype,"importNode",function(a,c){a=fa.call(this,a,c);this.__CE_hasRegistry?C(b,a):x(b,a);return a});u(Document.prototype,"createElementNS",function(a,c){if(this.__CE_hasRegistry&&(null===a||"http://www.w3.org/1999/xhtml"===a)){var d=b.a.get(c);if(d)return new d.constructor}a=ea.call(this,a,c);y(b,a);return a});
Y(b,Document.prototype,{h:ga,append:ha})};function va(){var b=X;function a(a,d){Object.defineProperty(a,"textContent",{enumerable:d.enumerable,configurable:!0,get:d.get,set:function(a){if(this.nodeType===Node.TEXT_NODE)d.set.call(this,a);else{var c=void 0;if(this.firstChild){var e=this.childNodes,l=e.length;if(0<l&&p(this))for(var c=Array(l),g=0;g<l;g++)c[g]=e[g]}d.set.call(this,a);if(c)for(a=0;a<c.length;a++)B(b,c[a])}}})}u(Node.prototype,"insertBefore",function(a,d){if(a instanceof DocumentFragment){var c=Array.prototype.slice.apply(a.childNodes);
a=K.call(this,a,d);if(p(this))for(d=0;d<c.length;d++)z(b,c[d]);return a}c=p(a);d=K.call(this,a,d);c&&B(b,a);p(this)&&z(b,a);return d});u(Node.prototype,"appendChild",function(a){if(a instanceof DocumentFragment){var d=Array.prototype.slice.apply(a.childNodes);a=J.call(this,a);if(p(this))for(var c=0;c<d.length;c++)z(b,d[c]);return a}d=p(a);c=J.call(this,a);d&&B(b,a);p(this)&&z(b,a);return c});u(Node.prototype,"cloneNode",function(a){a=I.call(this,a);this.ownerDocument.__CE_hasRegistry?C(b,a):x(b,a);
return a});u(Node.prototype,"removeChild",function(a){var d=p(a),c=L.call(this,a);d&&B(b,a);return c});u(Node.prototype,"replaceChild",function(a,d){if(a instanceof DocumentFragment){var c=Array.prototype.slice.apply(a.childNodes);a=M.call(this,a,d);if(p(this))for(B(b,d),d=0;d<c.length;d++)z(b,c[d]);return a}var c=p(a),f=M.call(this,a,d),m=p(this);m&&B(b,d);c&&B(b,a);m&&z(b,a);return f});N&&N.get?a(Node.prototype,N):w(b,function(b){a(b,{enumerable:!0,configurable:!0,get:function(){for(var a=[],b=
0;b<this.childNodes.length;b++)a.push(this.childNodes[b].textContent);return a.join("")},set:function(a){for(;this.firstChild;)L.call(this,this.firstChild);J.call(this,document.createTextNode(a))}})})};function wa(b){var a=Element.prototype;function c(a){return function(d){for(var c=[],e=0;e<arguments.length;++e)c[e-0]=arguments[e];for(var e=[],l=[],g=0;g<c.length;g++){var k=c[g];k instanceof Element&&p(k)&&l.push(k);if(k instanceof DocumentFragment)for(k=k.firstChild;k;k=k.nextSibling)e.push(k);else e.push(k)}a.apply(this,c);for(c=0;c<l.length;c++)B(b,l[c]);if(p(this))for(c=0;c<e.length;c++)l=e[c],l instanceof Element&&z(b,l)}}V&&(a.before=c(V));V&&(a.after=c(oa));pa&&u(a,"replaceWith",function(a){for(var c=
[],d=0;d<arguments.length;++d)c[d-0]=arguments[d];for(var d=[],m=[],l=0;l<c.length;l++){var g=c[l];g instanceof Element&&p(g)&&m.push(g);if(g instanceof DocumentFragment)for(g=g.firstChild;g;g=g.nextSibling)d.push(g);else d.push(g)}l=p(this);pa.apply(this,c);for(c=0;c<m.length;c++)B(b,m[c]);if(l)for(B(b,this),c=0;c<d.length;c++)m=d[c],m instanceof Element&&z(b,m)});qa&&u(a,"remove",function(){var a=p(this);qa.call(this);a&&B(b,this)})};function xa(){var b=X;function a(a,c){Object.defineProperty(a,"innerHTML",{enumerable:c.enumerable,configurable:!0,get:c.get,set:function(a){var d=this,e=void 0;p(this)&&(e=[],t(this,function(a){a!==d&&e.push(a)}));c.set.call(this,a);if(e)for(var f=0;f<e.length;f++){var k=e[f];1===k.__CE_state&&b.disconnectedCallback(k)}this.ownerDocument.__CE_hasRegistry?C(b,this):x(b,this);return a}})}function c(a,c){u(a,"insertAdjacentElement",function(a,d){var e=p(d);a=c.call(this,a,d);e&&B(b,d);p(a)&&z(b,d);
return a})}O&&u(Element.prototype,"attachShadow",function(a){return this.__CE_shadowRoot=a=O.call(this,a)});P&&P.get?a(Element.prototype,P):W&&W.get?a(HTMLElement.prototype,W):w(b,function(b){a(b,{enumerable:!0,configurable:!0,get:function(){return I.call(this,!0).innerHTML},set:function(a){var b="template"===this.localName,c=b?this.content:this,d=H.call(document,this.localName);for(d.innerHTML=a;0<c.childNodes.length;)L.call(c,c.childNodes[0]);for(a=b?d.content:d;0<a.childNodes.length;)J.call(c,
a.childNodes[0])}})});u(Element.prototype,"setAttribute",function(a,c){if(1!==this.__CE_state)return R.call(this,a,c);var d=Q.call(this,a);R.call(this,a,c);c=Q.call(this,a);b.attributeChangedCallback(this,a,d,c,null)});u(Element.prototype,"setAttributeNS",function(a,c,f){if(1!==this.__CE_state)return U.call(this,a,c,f);var d=T.call(this,a,c);U.call(this,a,c,f);f=T.call(this,a,c);b.attributeChangedCallback(this,c,d,f,a)});u(Element.prototype,"removeAttribute",function(a){if(1!==this.__CE_state)return S.call(this,
a);var c=Q.call(this,a);S.call(this,a);null!==c&&b.attributeChangedCallback(this,a,c,null,null)});u(Element.prototype,"removeAttributeNS",function(a,c){if(1!==this.__CE_state)return ka.call(this,a,c);var d=T.call(this,a,c);ka.call(this,a,c);var e=T.call(this,a,c);d!==e&&b.attributeChangedCallback(this,c,d,e,a)});sa?c(HTMLElement.prototype,sa):la?c(Element.prototype,la):console.warn("Custom Elements: `Element#insertAdjacentElement` was not patched.");Y(b,Element.prototype,{h:ma,append:na});wa(b)};/*
Copyright (c) 2016 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
*/
var Z=window.customElements;if(!Z||Z.forcePolyfill||"function"!=typeof Z.define||"function"!=typeof Z.get){var X=new v;ta();ua();Y(X,DocumentFragment.prototype,{h:ia,append:ja});va();xa();document.__CE_hasRegistry=!0;var customElements=new G(X);Object.defineProperty(window,"customElements",{configurable:!0,enumerable:!0,value:customElements})};
}).call(self);
//# sourceMappingURL=custom-elements.min.js.map

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -3,12 +3,9 @@
/* eslint-disable mozilla/no-cpows-in-tests */
add_task(async function test_total() {
const testTask = ({methodData, details}) => {
is(content.document.querySelector("#total > .value").textContent,
details.total.amount.value,
"Check total value");
is(content.document.querySelector("#total > .currency").textContent,
details.total.amount.currency,
"Check currency");
is(content.document.querySelector("#total > currency-amount").textContent,
"$60.00",
"Check total currency amount");
};
const args = {
methodData: [PTU.MethodData.basicCard],

Просмотреть файл

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"plugin:mozilla/mochitest-test"
],
};

Просмотреть файл

@ -0,0 +1,10 @@
[DEFAULT]
support-files =
../../res/components/currency-amount.js
../../res/mixins/ObservedPropertiesMixin.js
../../res/vendor/custom-elements.min.js
../../res/vendor/custom-elements.min.js.map
payments_common.js
[test_currency_amount.html]
[test_ObservedPropertiesMixin.html]

Просмотреть файл

@ -0,0 +1,12 @@
"use strict";
/* exported asyncElementRendered */
/**
* A helper to await on while waiting for an asynchronous rendering of a Custom
* Element.
* @returns {Promise}
*/
function asyncElementRendered() {
return Promise.resolve();
}

Просмотреть файл

@ -0,0 +1,119 @@
<!DOCTYPE HTML>
<html>
<!--
Test the ObservedPropertiesMixin
-->
<head>
<meta charset="utf-8">
<title>Test the ObservedPropertiesMixin</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script src="payments_common.js"></script>
<script src="custom-elements.min.js"></script>
<script src="ObservedPropertiesMixin.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display">
<test-element id="el1" one="foo" two-word="bar"></test-element>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script type="application/javascript">
/** Test the ObservedPropertiesMixin **/
/* import-globals-from payments_common.js */
/* import-globals-from ../../res/mixins/ObservedPropertiesMixin.js */
class TestElement extends ObservedPropertiesMixin(HTMLElement) {
static get observedAttributes() {
return ["one", "two-word"];
}
render() {
this.textContent = JSON.stringify({
one: this.one,
twoWord: this.twoWord,
});
}
}
customElements.define("test-element", TestElement);
let el1 = document.getElementById("el1");
add_task(async function test_default_properties() {
is(el1.one, "foo", "Check .one matches @one");
is(el1.twoWord, "bar", "Check .twoWord matches @two-word");
let expected = `{"one":"foo","twoWord":"bar"}`;
is(el1.textContent, expected, "Check textContent");
});
add_task(async function test_set_properties() {
el1.one = "a";
el1.twoWord = "b";
is(el1.one, "a", "Check .one value");
is(el1.getAttribute("one"), "a", "Check @one");
is(el1.twoWord, "b", "Check .twoWord value");
is(el1.getAttribute("two-word"), "b", "Check @two-word");
let expected = `{"one":"a","twoWord":"b"}`;
await asyncElementRendered();
is(el1.textContent, expected, "Check textContent");
});
add_task(async function test_set_attributes() {
el1.setAttribute("one", "X");
el1.setAttribute("two-word", "Y");
is(el1.one, "X", "Check .one value");
is(el1.getAttribute("one"), "X", "Check @one");
is(el1.twoWord, "Y", "Check .twoWord value");
is(el1.getAttribute("two-word"), "Y", "Check @two-word");
let expected = `{"one":"X","twoWord":"Y"}`;
await asyncElementRendered();
is(el1.textContent, expected, "Check textContent");
});
add_task(async function test_async_render() {
// Setup
el1.setAttribute("one", "1");
el1.setAttribute("two-word", "2");
await asyncElementRendered(); // Wait for the async render
el1.setAttribute("one", "new1");
is(el1.one, "new1", "Check .one value");
is(el1.getAttribute("one"), "new1", "Check @one");
is(el1.twoWord, "2", "Check .twoWord value");
is(el1.getAttribute("two-word"), "2", "Check @two-word");
let expected = `{"one":"1","twoWord":"2"}`;
is(el1.textContent, expected, "Check textContent is still old value due to async rendering");
await asyncElementRendered();
expected = `{"one":"new1","twoWord":"2"}`;
is(el1.textContent, expected, "Check textContent now has the new value");
});
add_task(async function test_batched_render() {
// Setup
el1.setAttribute("one", "1");
el1.setAttribute("two-word", "2");
await asyncElementRendered();
el1.setAttribute("one", "new1");
el1.setAttribute("two-word", "new2");
is(el1.one, "new1", "Check .one value");
is(el1.getAttribute("one"), "new1", "Check @one");
is(el1.twoWord, "new2", "Check .twoWord value");
is(el1.getAttribute("two-word"), "new2", "Check @two-word");
let expected = `{"one":"1","twoWord":"2"}`;
is(el1.textContent, expected, "Check textContent is still old value due to async rendering");
await asyncElementRendered();
expected = `{"one":"new1","twoWord":"new2"}`;
is(el1.textContent, expected, "Check textContent now has the new value");
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,143 @@
<!DOCTYPE HTML>
<html>
<!--
Test the currency-amount component
-->
<head>
<meta charset="utf-8">
<title>Test the currency-amount component</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script src="payments_common.js"></script>
<script src="custom-elements.min.js"></script>
<script src="ObservedPropertiesMixin.js"></script>
<script src="currency-amount.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display">
<currency-amount id="amount1"></currency-amount>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script type="application/javascript">
/** Test the currency-amount component **/
/* import-globals-from payments_common.js */
let amount1 = document.getElementById("amount1");
add_task(async function test_no_value() {
ok(amount1, "amount1 exists");
is(amount1.textContent, "", "Initially empty");
amount1.currency = "USD";
await asyncElementRendered();
is(amount1.getAttribute("currency"), "USD", "Check @currency");
ok(!amount1.hasAttribute("value"), "Check @value");
is(amount1.currency, "USD", "Check .currency");
is(amount1.value, null, "Check .value");
is(amount1.textContent, "", "Empty while missing an amount");
amount1.currency = null;
await asyncElementRendered();
ok(!amount1.hasAttribute("currency"), "Setting to null should remove @currency");
ok(!amount1.hasAttribute("value"), "Check @value");
is(amount1.currency, null, "Check .currency");
is(amount1.value, null, "Check .value");
});
add_task(async function test_no_value() {
amount1.value = 1.23;
await asyncElementRendered();
is(amount1.getAttribute("value"), "1.23", "Check @value");
ok(!amount1.hasAttribute("currency"), "Check @currency");
is(amount1.currency, null, "Check .currency");
is(amount1.value, "1.23", "Check .value");
is(amount1.textContent, "", "Empty while missing a currency");
amount1.value = null;
await asyncElementRendered();
ok(!amount1.hasAttribute("value"), "Setting to null should remove @value");
is(amount1.currency, null, "Check .currency");
is(amount1.value, null, "Check .value");
});
add_task(async function test_valid_currency_amount_cad() {
amount1.value = 12.34;
info("waiting to set second property");
await asyncElementRendered();
amount1.currency = "CAD";
await asyncElementRendered();
is(amount1.getAttribute("value"), "12.34", "Check @value");
is(amount1.value, "12.34", "Check .value");
is(amount1.getAttribute("currency"), "CAD", "Check @currency");
is(amount1.currency, "CAD", "Check .currency");
is(amount1.textContent, "CA$12.34", "Check output format");
});
add_task(async function test_valid_currency_amount_eur_batched_prop() {
info("setting two properties in a row synchronously");
amount1.value = 98.76;
amount1.currency = "EUR";
await asyncElementRendered();
is(amount1.getAttribute("value"), "98.76", "Check @value");
is(amount1.value, "98.76", "Check .value");
is(amount1.getAttribute("currency"), "EUR", "Check @currency");
is(amount1.currency, "EUR", "Check .currency");
is(amount1.textContent, "€98.76", "Check output format");
});
add_task(async function test_valid_currency_amount_eur_batched_attr() {
info("setting two attributes in a row synchronously");
amount1.setAttribute("value", 11.88);
amount1.setAttribute("currency", "CAD");
await asyncElementRendered();
is(amount1.getAttribute("value"), "11.88", "Check @value");
is(amount1.value, "11.88", "Check .value");
is(amount1.getAttribute("currency"), "CAD", "Check @currency");
is(amount1.currency, "CAD", "Check .currency");
is(amount1.textContent, "CA$11.88", "Check output format");
});
add_task(async function test_invalid_currency() {
isnot(amount1.textContent, "", "Start with initial content");
amount1.value = 33.33;
amount1.currency = "__invalid__";
await asyncElementRendered();
is(amount1.getAttribute("value"), "33.33", "Check @value");
is(amount1.value, "33.33", "Check .value");
is(amount1.getAttribute("currency"), "__invalid__", "Check @currency");
is(amount1.currency, "__invalid__", "Check .currency");
is(amount1.textContent, "", "Invalid currency should clear output");
});
add_task(async function test_invalid_value() {
info("setting some initial values");
amount1.value = 4.56;
amount1.currency = "GBP";
await asyncElementRendered();
isnot(amount1.textContent, "", "Start with initial content");
info("setting an alphabetical invalid value");
amount1.value = "abcdef";
await asyncElementRendered();
is(amount1.getAttribute("value"), "abcdef", "Check @value");
is(amount1.value, "abcdef", "Check .value");
is(amount1.getAttribute("currency"), "GBP", "Check @currency");
is(amount1.currency, "GBP", "Check .currency");
is(amount1.textContent, "", "Invalid value should clear output");
});
</script>
</body>
</html>

Просмотреть файл

@ -145,6 +145,7 @@
<li><a href="about:license#pbkdf2-sha256">pbkdf2_sha256 License</a></li>
<li><a href="about:license#pdfium">PDFium License</a></li>
<li><a href="about:license#phf">phf, phf_codegen, phf_generator, phf_shared License</a></li>
<li><a href="about:license#polymer">Polymer License</a></li>
<li><a href="about:license#praton">praton License</a></li>
<li><a href="about:license#praton1">praton and inet_ntop License</a></li>
<li><a href="about:license#precomputed-hash">precomputed-hash License</a></li>
@ -5302,6 +5303,44 @@ SOFTWARE.
</pre>
<hr>
<h1><a id="polymer"></a>Polymer License</h1>
<p>This license applies to the file
<code>toolkit/components/payments/res/vendor/custom-elements.min.js</code>.</p>
<pre>
Copyright (c) 2014 The Polymer Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
<hr>
<h1><a id="precomputed-hash"></a>precomputed-hash License</h1>