Bug 1487395 - Update strings on error pages, as well as convert apostrophes to use 'smart-quotes'. r=sfoster
authorJared Wein <jwein@mozilla.com>
Thu, 06 Sep 2018 19:43:19 +0000
changeset 435120 e9d83a2e788a
parent 435119 e3cdc51cdc0a
child 435121 fa6fb040f5b6
child 435143 a68f7dbde2e7
push id68885
push userjwein@mozilla.com
push dateThu, 06 Sep 2018 19:44:04 +0000
treeherderautoland@e9d83a2e788a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfoster
bugs1487395
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1487395 - Update strings on error pages, as well as convert apostrophes to use 'smart-quotes'. r=sfoster Differential Revision: https://phabricator.services.mozilla.com/D5068
browser/components/payments/res/containers/completion-error-page.js
browser/components/payments/res/paymentRequest.css
browser/components/payments/res/paymentRequest.xhtml
browser/components/payments/test/mochitest/test_completion_error_page.html
browser/components/payments/test/mochitest/test_payment_dialog.html
--- a/browser/components/payments/res/containers/completion-error-page.js
+++ b/browser/components/payments/res/containers/completion-error-page.js
@@ -15,16 +15,18 @@ import paymentRequest from "../paymentRe
  * as it will be much easier to implement and share the logic once we switch to Fluent.
  */
 
 export default class CompletionErrorPage extends PaymentStateSubscriberMixin(PaymentRequestPage) {
   constructor() {
     super();
 
     this.classList.add("error-page");
+    this.suggestionHeading = document.createElement("p");
+    this.body.append(this.suggestionHeading);
     this.suggestionsList = document.createElement("ul");
     this.suggestions = [];
     this.body.append(this.suggestionsList);
 
     this.doneButton = document.createElement("button");
     this.doneButton.classList.add("done-button", "primary");
     this.doneButton.addEventListener("click", this);
 
@@ -36,27 +38,33 @@ export default class CompletionErrorPage
 
     if (this.id && page && page.id !== this.id) {
       log.debug(`CompletionErrorPage: no need to further render inactive page: ${page.id}`);
       return;
     }
 
     let {request} = this.requestStore.getState();
     let {displayHost} = request.topLevelPrincipal.URI;
-    for (let key of ["pageTitle", "suggestion-1", "suggestion-2", "suggestion-3"]) {
-      this.dataset[key] = this.dataset[key].replace("**host-name**", displayHost);
+    for (let key of ["pageTitle", "suggestion-heading", "suggestion-1", "suggestion-2"]) {
+      if (this.dataset[key]) {
+        this.dataset[key] = this.dataset[key].replace("**host-name**", displayHost);
+      }
     }
 
     this.pageTitleHeading.textContent = this.dataset.pageTitle;
+    this.suggestionHeading.textContent = this.dataset.suggestionHeading;
     this.doneButton.textContent = this.dataset.doneButtonLabel;
 
     this.suggestionsList.textContent = "";
-    this.suggestions[0] = this.dataset["suggestion-1"];
-    this.suggestions[1] = this.dataset["suggestion-2"];
-    this.suggestions[2] = this.dataset["suggestion-3"];
+    if (this.dataset["suggestion-1"]) {
+      this.suggestions[0] = this.dataset["suggestion-1"];
+    }
+    if (this.dataset["suggestion-2"]) {
+      this.suggestions[1] = this.dataset["suggestion-2"];
+    }
 
     let suggestionsFragment = document.createDocumentFragment();
     for (let suggestionText of this.suggestions) {
       let listNode = document.createElement("li");
       listNode.textContent = suggestionText;
       suggestionsFragment.appendChild(listNode);
     }
     this.suggestionsList.appendChild(suggestionsFragment);
--- a/browser/components/payments/res/paymentRequest.css
+++ b/browser/components/payments/res/paymentRequest.css
@@ -93,16 +93,17 @@ payment-dialog > header > .page-error {
 }
 
 .page-error {
   color: #D70022;
 }
 
 .page > footer {
   align-items: center;
+  justify-content: end;
   background-color: #eaeaee;
   display: flex;
   /* from visual spec: */
   padding-top: 20px;
   padding-bottom: 18px;
 }
 
 #order-details-overlay {
--- a/browser/components/payments/res/paymentRequest.xhtml
+++ b/browser/components/payments/res/paymentRequest.xhtml
@@ -14,19 +14,19 @@
   <!ENTITY fieldRequiredSymbol        "*">
 
   <!ENTITY shippingAddressLabel       "Shipping Address">
   <!ENTITY deliveryAddressLabel       "Delivery Address">
   <!ENTITY pickupAddressLabel         "Pickup Address">
   <!ENTITY shippingOptionsLabel       "Shipping Options">
   <!ENTITY deliveryOptionsLabel       "Delivery Options">
   <!ENTITY pickupOptionsLabel         "Pickup Options">
-  <!ENTITY shippingGenericError       "Can't ship to this address. Select a different address.">
-  <!ENTITY deliveryGenericError       "Can't deliver to this address. Select a different address.">
-  <!ENTITY pickupGenericError         "Can't pick up from this address. Select a different address.">
+  <!ENTITY shippingGenericError       "Can’t ship to this address. Select a different address.">
+  <!ENTITY deliveryGenericError       "Can’t deliver to this address. Select a different address.">
+  <!ENTITY pickupGenericError         "Can’t pick up from this address. Select a different address.">
   <!ENTITY paymentMethodsLabel        "Payment Method">
   <!ENTITY address.addLink.label      "Add">
   <!ENTITY address.editLink.label     "Edit">
   <!ENTITY basicCard.addLink.label    "Add">
   <!ENTITY basicCard.editLink.label   "Edit">
   <!ENTITY payer.addLink.label        "Add">
   <!ENTITY payer.editLink.label       "Edit">
   <!ENTITY shippingAddress.addPage.title  "Add Shipping Address">
@@ -58,26 +58,24 @@
   <!ENTITY basicCardPage.updateButton.label   "Update">
   <!ENTITY basicCardPage.persistCheckbox.label     "Save credit card to &brandShortName; (Security code will not be saved)">
   <!ENTITY addressPage.error.genericSave      "There was an error saving the address.">
   <!ENTITY addressPage.cancelButton.label     "Cancel">
   <!ENTITY addressPage.backButton.label       "Back">
   <!ENTITY addressPage.addButton.label        "Add">
   <!ENTITY addressPage.updateButton.label     "Update">
   <!ENTITY addressPage.persistCheckbox.label  "Save address to &brandShortName;">
-  <!ENTITY failErrorPage.title  "Sorry! Something went wrong with the payment process.">
-  <!ENTITY failErrorPage.suggestion1  "Check your credit card has not expired.">
-  <!ENTITY failErrorPage.suggestion2  "Make sure your credit card information is accurate.">
-  <!ENTITY failErrorPage.suggestion3  "If no other solutions work, check with **host-name**.">
-  <!ENTITY failErrorPage.doneButton.label     "OK">
-  <!ENTITY timeoutErrorPage.title  "Whoops! **host-name** took too long to respond.">
-  <!ENTITY timeoutErrorPage.suggestion1  "Try again later.">
-  <!ENTITY timeoutErrorPage.suggestion2  "Check your network connection." >
-  <!ENTITY timeoutErrorPage.suggestion3  "If no other solutions work, check with **host-name**.">
-  <!ENTITY timeoutErrorPage.doneButton.label     "OK">
+  <!ENTITY failErrorPage.title                "We couldn’t complete your payment to **host-name**">
+  <!ENTITY failErrorPage.suggestionHeading    "The most likely cause is a hiccup with your credit card.">
+  <!ENTITY failErrorPage.suggestion1          "Make sure the card you’re using hasn’t expired">
+  <!ENTITY failErrorPage.suggestion2          "Double check the card number and expiration date">
+  <!ENTITY failErrorPage.doneButton.label     "Close">
+  <!ENTITY timeoutErrorPage.title             "**host-name** is taking too long to respond.">
+  <!ENTITY timeoutErrorPage.suggestionHeading "The most likely cause is a temporary connection hiccup. Open a new tab to check your network connection or click “Close” to try again.">
+  <!ENTITY timeoutErrorPage.doneButton.label     "Close">
   <!ENTITY webPaymentsBranding.label             "&brandShortName; Checkout">
   <!ENTITY invalidOption.label                   "Missing or invalid information">
 ]>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
   <title>&paymentSummaryTitle;</title>
 
   <!-- chrome: is needed for global.dtd -->
@@ -194,26 +192,24 @@
                     data-add-button-label="&addressPage.addButton.label;"
                     data-update-button-label="&addressPage.updateButton.label;"
                     data-persist-checkbox-label="&addressPage.persistCheckbox.label;"
                     data-field-required-symbol="&fieldRequiredSymbol;"
                     hidden="hidden"></address-form>
 
       <completion-error-page id="completion-timeout-error" class="illustrated"
                   data-page-title="&timeoutErrorPage.title;"
-                  data-suggestion-1="&timeoutErrorPage.suggestion1;"
-                  data-suggestion-2="&timeoutErrorPage.suggestion2;"
-                  data-suggestion-3="&timeoutErrorPage.suggestion3;"
+                  data-suggestion-heading="&timeoutErrorPage.suggestionHeading;"
                   data-done-button-label="&timeoutErrorPage.doneButton.label;"
                   hidden="hidden"></completion-error-page>
       <completion-error-page id="completion-fail-error" class="illustrated"
                   data-page-title="&failErrorPage.title;"
+                  data-suggestion-heading="&failErrorPage.suggestionHeading;"
                   data-suggestion-1="&failErrorPage.suggestion1;"
                   data-suggestion-2="&failErrorPage.suggestion2;"
-                  data-suggestion-3="&failErrorPage.suggestion3;"
                   data-done-button-label="&failErrorPage.doneButton.label;"
                   hidden="hidden"></completion-error-page>
     </div>
 
     <div id="disabled-overlay" hidden="hidden">
       <!-- overlay to prevent changes while waiting for a response from the merchant -->
     </div>
   </template>
--- a/browser/components/payments/test/mochitest/test_completion_error_page.html
+++ b/browser/components/payments/test/mochitest/test_completion_error_page.html
@@ -13,19 +13,19 @@ Test the completion-error-page component
   <script src="../../res/unprivileged-fallbacks.js"></script>
 
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
   <p id="display">
     <completion-error-page id="completion-timeout-error" class="illustrated"
             data-page-title="Sample Title"
+            data-suggestion-heading="Sample suggestion heading"
             data-suggestion-1="Sample suggestion"
             data-suggestion-2="Sample suggestion"
-            data-suggestion-3="Sample suggestion"
             data-done-button-label="OK"></completion-error-page>
   </p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
@@ -33,19 +33,22 @@ Test the completion-error-page component
 
 import "../../res/containers/completion-error-page.js";
 
 let page = document.getElementById("completion-timeout-error");
 
 add_task(async function test_no_values() {
   ok(page, "page exists");
   is(page.dataset.pageTitle, "Sample Title", "Title set on page");
-  is(page.dataset["suggestion-1"], "Sample suggestion", "Suggestion 1 set on page");
-  is(page.dataset["suggestion-2"], "Sample suggestion", "Suggestion 2 set on page");
-  is(page.dataset["suggestion-3"], "Sample suggestion", "Suggestion 3 set on page");
+  is(page.dataset.suggestionHeading, "Sample suggestion heading",
+     "Suggestion heading set on page");
+  is(page.dataset["suggestion-1"], "Sample suggestion",
+     "Suggestion 1 set on page");
+  is(page.dataset["suggestion-2"], "Sample suggestion",
+     "Suggestion 2 set on page");
 
   page.dataset.pageTitle = "Oh noes! **host-name** is having an issue";
   page.dataset["suggestion-2"] = "You should probably blame **host-name**, not us";
   const displayHost = "allizom.com";
   let request = { topLevelPrincipal: { URI: { displayHost } } };
   await page.requestStore.setState({
     changesPrevented: false,
     request: Object.assign({}, request, {completeStatus: ""}),
@@ -53,19 +56,24 @@ add_task(async function test_no_values()
     page: {
       id: "completion-timeout-error",
     },
   });
   await asyncElementRendered();
 
   is(page.requestStore.getState().request.topLevelPrincipal.URI.displayHost, displayHost,
      "State should have the displayHost set properly");
-  is(page.dataset.pageTitle, `Oh noes! ${displayHost} is having an issue`,
+  is(page.querySelector("h2").textContent,
+     `Oh noes! ${displayHost} is having an issue`,
      "Title includes host-name");
-  is(page.dataset["suggestion-1"], "Sample suggestion", "Suggestion 1 set on page");
-  is(page.dataset["suggestion-2"], `You should probably blame ${displayHost}, not us`,
+  is(page.querySelector("p").textContent,
+     "Sample suggestion heading",
+     "Suggestion heading set on page");
+  is(page.querySelector("li:nth-child(1)").textContent, "Sample suggestion",
+     "Suggestion 1 set on page");
+  is(page.querySelector("li:nth-child(2)").textContent,
+     `You should probably blame ${displayHost}, not us`,
      "Suggestion 2 includes host-name");
-  is(page.dataset["suggestion-3"], "Sample suggestion", "Suggestion 3 set on page");
 });
 </script>
 
 </body>
 </html>
--- a/browser/components/payments/test/mochitest/test_payment_dialog.html
+++ b/browser/components/payments/test/mochitest/test_payment_dialog.html
@@ -244,17 +244,17 @@ add_task(async function test_timeout_fai
     let payButton = document.getElementById("pay");
     let primaryButton = pageElem.querySelector("button.primary");
 
     ok(pageElem && !isHidden(pageElem, `page element for ${page.id} exists and is visible`));
     ok(!isHidden(primaryButton), "Primary button is visible");
     ok(payButton != primaryButton,
        `Primary button is the not pay button in the ${completeStatus} state`);
     ok(isHidden(payButton), "Pay button is not visible");
-    is(primaryButton.textContent, "OK", "Check button label");
+    is(primaryButton.textContent, "Close", "Check button label");
 
     let rect = primaryButton.getBoundingClientRect();
     let visibleElement =
       document.elementFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
     ok(primaryButton === visibleElement, "Primary button is on top of the overlay");
   }
 });