Bug 1429207 - Implement the 'failure' screen for when the merchant rejects the payment. r?mattn draft
authorJared Wein <jwein@mozilla.com>
Tue, 27 Feb 2018 22:09:34 -0500
changeset 761918 10dd4073f18ab762b89606b79d3bdd3ecf09b33a
parent 761916 169e6305bc922339dc8f6e50cb24f4ee3baac9b2
child 762077 9ac0bc382acfe7bcc4c00cdd877cad9ef274f914
child 762344 0cbf576eab74ae9d257c4fb260988227bcb36d18
child 762819 e19e68428994cfb605729c263250d7012290b89d
push id101051
push userbmo:jaws@mozilla.com
push dateThu, 01 Mar 2018 17:42:49 +0000
reviewersmattn
bugs1429207
milestone60.0a1
Bug 1429207 - Implement the 'failure' screen for when the merchant rejects the payment. r?mattn MozReview-Commit-ID: JfsMQ8EwhqW
toolkit/components/payments/res/containers/payment-dialog.js
toolkit/components/payments/res/debugging.html
toolkit/components/payments/res/debugging.js
toolkit/components/payments/res/paymentRequest.css
toolkit/components/payments/res/paymentRequest.xhtml
toolkit/components/payments/test/mochitest/test_payment_dialog.html
--- 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();