Bug 1469464 - Display the currency code with the total. r=sfoster
MozReview-Commit-ID: JJIbFBAYC9U
--- a/browser/components/payments/res/components/currency-amount.js
+++ b/browser/components/payments/res/components/currency-amount.js
@@ -1,39 +1,74 @@
/* 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/. */
"use strict";
/**
- * <currency-amount value="7.5" currency="USD"></currency-amount>
+ * <currency-amount value="7.5" currency="USD" display-code></currency-amount>
*/
import ObservedPropertiesMixin from "../mixins/ObservedPropertiesMixin.js";
export default class CurrencyAmount extends ObservedPropertiesMixin(HTMLElement) {
static get observedAttributes() {
- return ["currency", "value"];
+ return [
+ "currency",
+ "display-code",
+ "value",
+ ];
+ }
+
+ constructor() {
+ super();
+ this._currencyAmountTextNode = document.createTextNode("");
+ this._currencyCodeElement = document.createElement("span");
+ this._currencyCodeElement.classList.add("currency-code");
+ }
+
+ connectedCallback() {
+ if (super.connectedCallback) {
+ super.connectedCallback();
+ }
+
+ this.append(this._currencyAmountTextNode, this._currencyCodeElement);
}
render() {
- let output = "";
+ let currencyAmount = "";
+ let currencyCode = "";
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, {
+ const symbolFormatter = new Intl.NumberFormat(navigator.languages, {
style: "currency",
currency: this.currency,
currencyDisplay: "symbol",
});
- output = formatter.format(this.value);
+ currencyAmount = symbolFormatter.format(this.value);
+
+ if (this.displayCode !== null) {
+ // XXX: Bug 1473772 will move the separator to a Fluent string.
+ currencyAmount += " ";
+
+ const codeFormatter = new Intl.NumberFormat(navigator.languages, {
+ style: "currency",
+ currency: this.currency,
+ currencyDisplay: "code",
+ });
+ let parts = codeFormatter.formatToParts(this.value);
+ let currencyPart = parts.find(part => part.type == "currency");
+ currencyCode = currencyPart.value;
+ }
}
} finally {
- this.textContent = output;
+ this._currencyAmountTextNode.textContent = currencyAmount;
+ this._currencyCodeElement.textContent = currencyCode;
}
}
}
customElements.define("currency-amount", CurrencyAmount);
--- a/browser/components/payments/res/paymentRequest.css
+++ b/browser/components/payments/res/paymentRequest.css
@@ -85,16 +85,21 @@ payment-dialog > footer {
align-items: baseline;
display: flex;
}
#total {
flex: 1 1 auto;
margin: 5px;
}
+
+#total > currency-amount > .currency-code {
+ color: GrayText;
+}
+
#view-all {
flex: 0 1 auto;
}
#total .label {
font-size: 15px;
font-weight: bold;
}
--- a/browser/components/payments/res/paymentRequest.xhtml
+++ b/browser/components/payments/res/paymentRequest.xhtml
@@ -78,18 +78,17 @@
<script src="formautofill/autofillEditForms.js"></script>
<script type="module" src="containers/payment-dialog.js"></script>
<script type="module" src="paymentRequest.js"></script>
<template id="payment-dialog-template">
<header>
<div id="total">
- <h2 class="label"></h2>
- <currency-amount></currency-amount>
+ <currency-amount display-code="display-code"></currency-amount>
<div>&header.payTo; <span id="host-name"></span></div>
</div>
<div id="top-buttons" hidden="hidden">
<button id="view-all" class="closed">&viewAllItems;</button>
</div>
</header>
<div id="main-container">
--- a/browser/components/payments/test/browser/browser_change_shipping.js
+++ b/browser/components/payments/test/browser/browser_change_shipping.js
@@ -64,17 +64,17 @@ add_task(async function test_change_ship
await spawnPaymentDialogTask(frame, async function() {
let {
PaymentTestUtils: PTU,
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
// verify update of total
// Note: The update includes a modifier, and modifiers must include a total
// so the expected total is that one
is(content.document.querySelector("#total > currency-amount").textContent,
- "\u20AC2.50",
+ "\u20AC2.50 EUR",
"Check updated total currency amount");
let btn = content.document.querySelector("#view-all");
btn.click();
await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.orderDetailsShowing;
}, "Order details show be showing now");
--- a/browser/components/payments/test/browser/browser_total.js
+++ b/browser/components/payments/test/browser/browser_total.js
@@ -1,45 +1,45 @@
"use strict";
add_task(async function test_total() {
const testTask = ({methodData, details}) => {
is(content.document.querySelector("#total > currency-amount").textContent,
- "$60.00",
+ "$60.00 USD",
"Check total currency amount");
};
const args = {
methodData: [PTU.MethodData.basicCard],
details: PTU.Details.total60USD,
};
await spawnInDialogForMerchantTask(PTU.ContentTasks.createAndShowRequest, testTask, args);
});
add_task(async function test_modifier_with_no_method_selected() {
const testTask = async ({methodData, details}) => {
// There are no payment methods installed/setup so we expect the original (unmodified) total.
is(content.document.querySelector("#total > currency-amount").textContent,
- "$2.00",
+ "$2.00 USD",
"Check unmodified total currency amount");
};
const args = {
methodData: [PTU.MethodData.bobPay, PTU.MethodData.basicCard],
details: Object.assign({}, PTU.Details.bobPayPaymentModifier, PTU.Details.total2USD),
};
await spawnInDialogForMerchantTask(PTU.ContentTasks.createAndShowRequest, testTask, args);
});
add_task(async function test_modifier_with_no_method_selected() {
info("adding a basic-card");
await addSampleAddressesAndBasicCard();
const testTask = async ({methodData, details}) => {
// We expect the *only* payment method (the one basic-card) to be selected initially.
is(content.document.querySelector("#total > currency-amount").textContent,
- "$2.50",
+ "$2.50 USD",
"Check modified total currency amount");
};
const args = {
methodData: [PTU.MethodData.bobPay, PTU.MethodData.basicCard],
details: Object.assign({}, PTU.Details.bobPayPaymentModifier, PTU.Details.total2USD),
};
await spawnInDialogForMerchantTask(PTU.ContentTasks.createAndShowRequest, testTask, args);
await cleanupFormAutofillStorage();
--- a/browser/components/payments/test/mochitest/test_currency_amount.html
+++ b/browser/components/payments/test/mochitest/test_currency_amount.html
@@ -75,16 +75,36 @@ add_task(async function test_valid_curre
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_displayCode() {
+ amount1.value = 12.34;
+ info("showing the currency code");
+ await asyncElementRendered();
+ amount1.currency = "CAD";
+ await asyncElementRendered();
+ amount1.displayCode = true;
+ 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 CAD", "Check output format");
+
+ amount1.displayCode = false;
+ await asyncElementRendered();
+});
+
+
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");