Bug 1429207 - Implement the 'failure' screen for when the merchant rejects the payment. r?mattn
MozReview-Commit-ID: JfsMQ8EwhqW
--- a/toolkit/components/payments/res/containers/payment-dialog.js
+++ b/toolkit/components/payments/res/containers/payment-dialog.js
@@ -151,16 +151,17 @@ class PaymentDialog extends PaymentState
}
_renderPayButton(state) {
this._payButton.disabled = state.changesPrevented;
switch (state.completionState) {
case "initial":
case "processing":
case "success":
+ case "fail":
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
@@ -27,11 +27,12 @@
<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>
+ <button id="setStateFail">Fail</button>
</div>
</body>
</html>
--- a/toolkit/components/payments/res/debugging.js
+++ b/toolkit/components/payments/res/debugging.js
@@ -294,16 +294,22 @@ let buttonActions = {
});
},
setStateSuccess() {
requestStore.setState({
completionState: "success",
});
},
+
+ setStateFail() {
+ requestStore.setState({
+ completionState: "fail",
+ });
+ },
};
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,16 +77,17 @@ payment-dialog > footer {
}
#pay {
background-color: #0060df;
color: white;
border: none;
}
+payment-dialog[changes-prevented][completion-state="fail"] #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 {
--- a/toolkit/components/payments/res/paymentRequest.xhtml
+++ b/toolkit/components/payments/res/paymentRequest.xhtml
@@ -9,16 +9,17 @@
<!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 failPaymentButton.label "Fail">
<!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"/>
@@ -84,16 +85,17 @@
<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;"
+ data-fail-label="&failPaymentButton.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
@@ -31,16 +31,22 @@ Test the payment-dialog custom element
/** Test the payment-dialog element **/
/* global sinon */
/* import-globals-from payments_common.js */
/* import-globals-from ../../res/mixins/PaymentStateSubscriberMixin.js */
let el1;
+let completionStates = [
+ ["processing", "Processing"],
+ ["success", "Done"],
+ ["fail", "Fail"],
+];
+
/* test that:
the view-all-items button exists
that clicking it changes the state on the store
that clicking it causes render to be called
that order details element's hidden state matches the state on the store
*/
@@ -112,57 +118,46 @@ add_task(async function test_changesPrev
add_task(async function test_completionState() {
await setup();
let state = el1.requestStore.getState();
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");
+ for (let [completionState, label] of completionStates) {
+ await el1.requestStore.setState({completionState});
+ await asyncElementRendered();
+ is(payButton.textContent, label, "Check payButton 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");
is(payButton.textContent, "Pay", "Check default label");
ok(!payButton.disabled, "Button is enabled");
- await el1.requestStore.setState({
- changesPrevented: true,
- completionState: "processing",
- });
- await asyncElementRendered();
- is(payButton.textContent, "Processing", "Check processing label");
- ok(payButton.disabled, "Button is disabled");
- 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");
+ for (let [completionState, label] of completionStates) {
+ await el1.requestStore.setState({
+ changesPrevented: true,
+ completionState,
+ });
+ await asyncElementRendered();
+ is(payButton.textContent, label, "Check payButton label");
+ ok(payButton.disabled, "Button is disabled");
+ 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");
+ }
});
add_task(async function test_disconnect() {
await setup();
el1.remove();
await el1.requestStore.setState({orderDetailsShowing: true});
await asyncElementRendered();