Bug 1429211 - Implement the 'success' screen for when the merchant accepts the payment. r?mattn
MozReview-Commit-ID: 5AAKzKMqXVx
--- a/toolkit/components/payments/res/containers/payment-dialog.js
+++ b/toolkit/components/payments/res/containers/payment-dialog.js
@@ -150,16 +150,17 @@ class PaymentDialog extends PaymentState
}
}
_renderPayButton(state) {
this._payButton.disabled = state.changesPrevented;
switch (state.completionState) {
case "initial":
case "processing":
+ case "success":
break;
default:
throw new Error("Invalid completionState");
}
this._payButton.textContent = this._payButton.dataset[state.completionState + "Label"];
}
--- a/toolkit/components/payments/res/debugging.html
+++ b/toolkit/components/payments/res/debugging.html
@@ -26,11 +26,12 @@
<button id="setBasicCards1">Set Basic Cards 1</button>
<button id="delete1Card">Delete 1 Card</button>
<h1>States</h1>
<button id="setChangesPrevented">Prevent changes</button>
<button id="setChangesAllowed">Allow changes</button>
<button id="setShippingError">Shipping Error</button>
<button id="setStateDefault">Default</button>
<button id="setStateProcessing">Processing</button>
+ <button id="setStateSuccess">Success</button>
</div>
</body>
</html>
--- a/toolkit/components/payments/res/debugging.js
+++ b/toolkit/components/payments/res/debugging.js
@@ -288,16 +288,22 @@ let buttonActions = {
});
},
setStateProcessing() {
requestStore.setState({
completionState: "processing",
});
},
+
+ setStateSuccess() {
+ requestStore.setState({
+ completionState: "success",
+ });
+ },
};
window.addEventListener("click", function onButtonClick(evt) {
let id = evt.target.id;
if (!id || typeof(buttonActions[id]) != "function") {
return;
}
--- a/toolkit/components/payments/res/paymentRequest.css
+++ b/toolkit/components/payments/res/paymentRequest.css
@@ -77,17 +77,18 @@ payment-dialog > footer {
}
#pay {
background-color: #0060df;
color: white;
border: none;
}
-payment-dialog[changes-prevented][completion-state="processing"] #pay {
+payment-dialog[changes-prevented][completion-state="processing"] #pay,
+payment-dialog[changes-prevented][completion-state="success"] #pay {
/* Show the pay button above #disabled-overlay */
position: relative;
z-index: 1;
}
#disabled-overlay {
background: white;
opacity: 0.6;
--- a/toolkit/components/payments/res/paymentRequest.xhtml
+++ b/toolkit/components/payments/res/paymentRequest.xhtml
@@ -8,16 +8,17 @@
<!ENTITY shippingAddressLabel "Shipping Address">
<!ENTITY deliveryAddressLabel "Delivery Address">
<!ENTITY pickupAddressLabel "Pickup Address">
<!ENTITY shippingOptionsLabel "Shipping Options">
<!ENTITY paymentMethodsLabel "Payment Method">
<!ENTITY cancelPaymentButton.label "Cancel">
<!ENTITY approvePaymentButton.label "Pay">
<!ENTITY processingPaymentButton.label "Processing">
+ <!ENTITY successPaymentButton.label "Done">
<!ENTITY orderDetailsLabel "Order Details">
<!ENTITY orderTotalLabel "Total">
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'"/>
<title></title>
<link rel="stylesheet" href="paymentRequest.css"/>
@@ -82,17 +83,18 @@
<div><label>&paymentMethodsLabel;</label></div>
<payment-method-picker selected-state-key="selectedPaymentCard"></payment-method-picker>
</section>
<footer id="controls-container">
<button id="cancel">&cancelPaymentButton.label;</button>
<button id="pay"
data-initial-label="&approvePaymentButton.label;"
- data-processing-label="&processingPaymentButton.label;"></button>
+ data-processing-label="&processingPaymentButton.label;"
+ data-success-label="&successPaymentButton.label;"></button>
</footer>
</section>
<section id="order-details-overlay" hidden="hidden">
<h1>&orderDetailsLabel;</h1>
<order-details></order-details>
</section>
</div>
--- a/toolkit/components/payments/test/mochitest/test_payment_dialog.html
+++ b/toolkit/components/payments/test/mochitest/test_payment_dialog.html
@@ -116,16 +116,20 @@ add_task(async function test_completionS
is(state.completionState, "initial", "completionState is initially initial");
let payButton = document.getElementById("pay");
is(payButton.textContent, "Pay", "Check default label");
ok(!payButton.disabled, "Button is enabled");
await el1.requestStore.setState({completionState: "processing"});
await asyncElementRendered();
is(payButton.textContent, "Processing", "Check processing label");
ok(!payButton.disabled, "Button is still enabled");
+ await el1.requestStore.setState({completionState: "success"});
+ await asyncElementRendered();
+ is(payButton.textContent, "Done", "Check success label");
+ ok(!payButton.disabled, "Button is still enabled");
});
add_task(async function test_completionStateChangesPrevented() {
await setup();
let state = el1.requestStore.getState();
is(state.completionState, "initial", "completionState is initially initial");
is(state.changesPrevented, false, "changesPrevented is initially false");
let payButton = document.getElementById("pay");
@@ -134,23 +138,30 @@ add_task(async function test_completionS
await el1.requestStore.setState({
changesPrevented: true,
completionState: "processing",
});
await asyncElementRendered();
is(payButton.textContent, "Processing", "Check processing label");
ok(payButton.disabled, "Button is disabled");
- let {
- x,
- y,
- width,
- height,
- } = payButton.getBoundingClientRect();
- let visibleElement = document.elementFromPoint(x + width / 2, y + height / 2);
+ let rect = payButton.getBoundingClientRect();
+ let visibleElement =
+ document.elementFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+ ok(payButton === visibleElement, "Pay button is on top of the overlay");
+
+ await el1.requestStore.setState({
+ changesPrevented: true,
+ completionState: "success",
+ });
+ await asyncElementRendered();
+ is(payButton.textContent, "Done", "Check success label");
+ ok(payButton.disabled, "Button is disabled");
+ rect = payButton.getBoundingClientRect();
+ visibleElement = document.elementFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
ok(payButton === visibleElement, "Pay button is on top of the overlay");
});
add_task(async function test_disconnect() {
await setup();
el1.remove();
await el1.requestStore.setState({orderDetailsShowing: true});