Bug 1375345 - Mochitests for basic card payment implementation. r=baku
authorEden Chuang <echuang@mozilla.com>
Mon, 24 Jul 2017 17:17:03 +0800
changeset 422412 cce9237283c936c62de6765a4aef690f848abc48
parent 422411 2a26a2f147e4d556e4c4329fe33e2d7febe7cd9f
child 422413 1455629cb663e28c373d3808dd605e749d03131b
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1375345
milestone56.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 1375345 - Mochitests for basic card payment implementation. r=baku
dom/payments/test/BasiccardChromeScript.js
dom/payments/test/ConstructorChromeScript.js
dom/payments/test/ShowPaymentChromeScript.js
dom/payments/test/head.js
dom/payments/test/mochitest.ini
dom/payments/test/test_basiccard.html
dom/payments/test/test_constructor.html
dom/payments/test/test_showPayment.html
dom/payments/test/test_validate_decimal_value.html
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/BasiccardChromeScript.js
@@ -0,0 +1,213 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+
+function emitTestFail(message) {
+  sendAsyncMessage("test-fail", message);
+}
+
+const billingAddress = Cc["@mozilla.org/dom/payments/payment-address;1"].
+                           createInstance(Ci.nsIPaymentAddress);
+const addressLine = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+const address = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+address.data = "Easton Ave";
+addressLine.appendElement(address);
+billingAddress.init("USA",              // country
+                     addressLine,        // address line
+                     "CA",               // region
+                     "San Bruno",        // city
+                     "",                 // dependent locality
+                     "94066",            // postal code
+                     "123456",           // sorting code
+                     "en",               // language code
+                     "",                 // organization
+                     "Bill A. Pacheco",  // recipient
+                     "+14344413879"); // phone
+
+const basiccardResponseData = Cc["@mozilla.org/dom/payments/basiccard-response-data;1"].
+                                 createInstance(Ci.nsIBasicCardResponseData);
+
+const showResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"].
+                        createInstance(Ci.nsIPaymentShowActionResponse);
+
+function abortPaymentResponse(requestId) {
+  let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"].
+                         createInstance(Ci.nsIPaymentAbortActionResponse);
+  abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
+  return abortResponse.QueryInterface(Ci.nsIPaymentActionResponse);
+}
+
+function completePaymentResponse(requestId) {
+  let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
+                            createInstance(Ci.nsIPaymentCompleteActionResponse);
+  completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
+  return completeResponse;
+}
+
+const detailedResponseUI = {
+  canMakePayment: function(requestId) {
+    return null;
+  },
+  showPayment: function(requestId) {
+    try {
+      basiccardResponseData.initData("Bill A. Pacheco",  // cardholderName
+                                     "4916855166538720", // cardNumber
+                                     "01",               // expiryMonth
+                                     "2024",             // expiryYear
+                                     "180",              // cardSecurityCode
+                                     billingAddress);   // billingAddress
+    } catch (e) {
+      emitTestFail("Fail to initialize basic card response data.");
+    }
+    showResponse.init(requestId,
+                      Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED,
+                      "basic-card",         // payment method
+                      basiccardResponseData,// payment method data
+                      "Bill A. Pacheco",    // payer name
+                      "",                   // payer email
+                      "");                  // payer phone
+    return showResponse;
+  },
+  abortPayment: abortPaymentResponse,
+  completePayment: completePaymentResponse,
+  updatePayment: function(requestId) {
+    return null;
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
+};
+
+const simpleResponseUI = {
+  canMakePayment: function(requestId) {
+    return null;
+  },
+  showPayment: function(requestId) {
+    try {
+      basiccardResponseData.initData("",                 // cardholderName
+                                     "4916855166538720", // cardNumber
+                                     "",                 // expiryMonth
+                                     "",                 // expiryYear
+                                     "",                 // cardSecurityCode
+                                     null);              // billingAddress
+    } catch (e) {
+      emitTestFail("Fail to initialize basic card response data.");
+    }
+    showResponse.init(requestId,
+                      Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED,
+                      "basic-card",         // payment method
+                      basiccardResponseData,// payment method data
+                      "Bill A. Pacheco",    // payer name
+                      "",                   // payer email
+                      "");                  // payer phone
+    return showResponse;
+  },
+  abortPayment: abortPaymentResponse,
+  completePayment: completePaymentResponse,
+  updatePayment: function(requestId) {
+    return null;
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
+};
+
+addMessageListener("set-detailed-ui-service", function() {
+  paymentSrv.setTestingUIService(detailedResponseUI.QueryInterface(Ci.nsIPaymentUIService));
+});
+
+addMessageListener("set-simple-ui-service", function() {
+  paymentSrv.setTestingUIService(simpleResponseUI.QueryInterface(Ci.nsIPaymentUIService));
+});
+
+addMessageListener("error-response-test", function() {
+  // test empty cardNumber
+  try {
+    basiccardResponseData.initData("", "", "", "", "", null);
+    emitTestFail("BasicCardResponse should not be initialized with empty cardNumber.");
+  } catch (e) {
+    if (e.name != "NS_ERROR_FAILURE") {
+      emitTestFail("Empty cardNumber expected 'NS_ERROR_FAILURE', but got " + e.name + ".");
+    }
+  }
+
+  // test invalid expiryMonth 123
+  try {
+    basiccardResponseData.initData("", "4916855166538720", "123", "", "", null);
+    emitTestFail("BasicCardResponse should not be initialized with invalid expiryMonth '123'.");
+  } catch (e) {
+    if (e.name != "NS_ERROR_FAILURE") {
+      emitTestFail("expiryMonth 123 expected 'NS_ERROR_FAILURE', but got " + e.name + ".");
+    }
+  }
+  // test invalid expiryMonth 99
+  try {
+    basiccardResponseData.initData("", "4916855166538720", "99", "", "", null);
+    emitTestFail("BasicCardResponse should not be initialized with invalid expiryMonth '99'.");
+  } catch (e) {
+    if (e.name != "NS_ERROR_FAILURE") {
+      emitTestFail("expiryMonth 99 xpected 'NS_ERROR_FAILURE', but got " + e.name + ".");
+    }
+  }
+  // test invalid expiryMonth ab
+  try {
+    basiccardResponseData.initData("", "4916855166538720", "ab", "", "", null);
+    emitTestFail("BasicCardResponse should not be initialized with invalid expiryMonth 'ab'.");
+  } catch (e) {
+    if (e.name != "NS_ERROR_FAILURE") {
+      emitTestFail("expiryMonth ab expected 'NS_ERROR_FAILURE', but got " + e.name + ".");
+    }
+  }
+  // test invalid expiryYear abcd
+  try {
+    basiccardResponseData.initData("", "4916855166538720", "", "abcd", "", null);
+    emitTestFail("BasicCardResponse should not be initialized with invalid expiryYear 'abcd'.");
+  } catch (e) {
+    if (e.name != "NS_ERROR_FAILURE") {
+      emitTestFail("expiryYear abcd expected 'NS_ERROR_FAILURE', but got " + e.name + ".");
+    }
+  }
+  // test invalid expiryYear 11111
+  try {
+    basiccardResponseData.initData("", "4916855166538720", "", "11111", "", null);
+    emitTestFail("BasicCardResponse should not be initialized with invalid expiryYear '11111'.");
+  } catch (e) {
+    if (e.name != "NS_ERROR_FAILURE") {
+      emitTestFail("expiryYear 11111 expected 'NS_ERROR_FAILURE', but got " + e.name + ".");
+    }
+  }
+
+
+  const responseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
+                          createInstance(Ci.nsIGeneralResponseData);
+  try {
+    responseData.initData({});
+  } catch (e) {
+    emitTestFail("Fail to initialize response data with empty object.");
+  }
+
+  try {
+    showResponse.init("testid",
+                      Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED,
+                      "basic-card",         // payment method
+                      responseData,         // payment method data
+                      "Bill A. Pacheco",    // payer name
+                      "",                   // payer email
+                      "");                  // payer phone
+    emitTestFail("nsIPaymentShowActionResponse should not be initialized with basic-card method and nsIGeneralResponseData.");
+  } catch (e) {
+    if (e.name != "NS_ERROR_FAILURE") {
+      emitTestFail("ShowResponse init expected 'NS_ERROR_FAILURE', but got " + e.name + ".");
+    }
+  }
+  sendAsyncMessage("error-response-complete");
+});
+
+addMessageListener("teardown", function() {
+  paymentSrv.cleanup();
+  paymentSrv.setTestingUIService(null);
+  sendAsyncMessage("teardown-complete");
+});
--- a/dom/payments/test/ConstructorChromeScript.js
+++ b/dom/payments/test/ConstructorChromeScript.js
@@ -21,16 +21,19 @@ function checkSimplestRequest(payRequest
   const methodData = payRequest.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
   if (!methodData) {
     emitTestFail("Fail to get payment methodData.");
   }
   const supportedMethod = methodData.supportedMethods;
   if (supportedMethod != "basic-card") {
     emitTestFail("supported method should be 'basic-card'.");
   }
+  if (methodData.data) {
+    emitTestFail("methodData.data should not exist.");
+  }
 
   // checking the passed PaymentDetails parameter
   const details = payRequest.paymentDetails;
   if (details.totalItem.label != "Total") {
     emitTestFail("total item's label should be 'Total'.");
   }
   if (details.totalItem.amount.currency != "USD") {
     emitTestFail("total item's currency should be 'USD'.");
@@ -77,18 +80,44 @@ function checkComplexRequest(payRequest)
   if (!methodData) {
     emitTestFail("Fail to get payment methodData.");
   }
   let supportedMethod = methodData.supportedMethods;
   if (supportedMethod != "basic-card") {
     emitTestFail("supported method should be 'basic-card'.");
   }
   const data = methodData.data;
-  if (data != "{\"supportedNetworks\":[\"unionpay\",\"visa\",\"mastercard\",\"amex\",\"discover\",\"diners\",\"jcb\",\"mir\"],\"supportedTypes\":[\"prepaid\",\"debit\",\"credit\"]}") {
-    emitTestFail("method data should be '{\"supportedNetworks\":[\"unionpay\",\"visa\",\"mastercard\",\"amex\",\"discover\",\"diners\",\"jcb\",\"mir\"],\"supportedTypes\":[\"prepaid\",\"debit\",\"credit\"]}', but got '" + data + "'.");
+  const supportedNetworks = data.supportedNetworks;
+  const expectedSupportedNetworks = ["unionpay", "visa", "mastercard", "amex",
+                                     "discover", "diners", "jcb", "mir"];
+  if (supportedNetworks.length !=  expectedSupportedNetworks.length) {
+    emitTestFail("supportedNetworks.length should be " +
+                 expectedSupportedNetworks.length +
+                 ", but got " + supportedNetworks.length + ".");
+  }
+  for (let idx = 0; idx < supportedNetworks.length; idx++) {
+    if (supportedNetworks[idx] != expectedSupportedNetworks[idx]) {
+      emitTestFail("supportedNetworks[" + idx + "] should be '" +
+                   expectedSupportedNetworks[idx] + "', but got '" +
+                   supportedNetworks[idx] + "'.");
+    }
+  }
+  const supportedTypes = data.supportedTypes;
+  const expectedSupportedTypes = ["prepaid", "debit", "credit"];
+  if (supportedTypes.length != expectedSupportedTypes.length) {
+    emitTestFail("supportedTypes.length should be '" +
+                 expectedSupportedTypes.length + "', but got '" +
+                 supportedTypes.length + "'.");
+  }
+  for (let idx = 0; idx < supportedTypes.length; idx++) {
+    if (supportedTypes[idx] != expectedSupportedTypes[idx]) {
+      emitTestFail("supportedTypes[" + idx + "] should be '" +
+                   expectedSupportedTypes[idx] + "', but got '" +
+                   supportedTypes[idx] + "'.");
+    }
   }
   // checking the passed PaymentDetails parameter
   const details = payRequest.paymentDetails;
   if (details.id != "payment details" ) {
     emitTestFail("details.id should be 'payment details'.");
   }
   if (details.totalItem.label != "Total") {
     emitTestFail("total item's label should be 'Total'.");
@@ -159,18 +188,19 @@ function checkComplexRequest(payRequest)
     emitTestFail("additional item's label should be 'basic-card discount'.");
   }
   if (additionalItem.amount.currency != "USD") {
     emitTestFail("additional item's currency should be 'USD'.");
   }
   if (additionalItem.amount.value != "-10.00") {
     emitTestFail("additional item's value should be '-10.00'.");
   }
-  if (modifier.data != "{\"discountProgramParticipantId\":\"86328764873265\"}") {
-    emitTestFail("modifier's data should be '{\"discountProgramParticipantId\":\"86328764873265\"}'.");
+  if (modifier.data.discountProgramParticipantId != "86328764873265") {
+    emitTestFail("modifier's data should be '86328764873265', but got '" +
+                 modifier.data.discountProgramParticipantId + "'.");
   }
 
   const shippingOptions = details.shippingOptions;
   if (!shippingOptions) {
     emitTestFail("details.shippingOptions should not be undefined.");
   }
   if (shippingOptions.length != 2) {
     emitTestFail("shippingOptions' length should be 2.");
@@ -222,16 +252,80 @@ function checkComplexRequest(payRequest)
   if (!paymentOptions.requestShipping) {
     emitTestFail("requestShipping option should be true.");
   }
   if (paymentOptions.shippingType != "shipping") {
     emitTestFail("shippingType option should be 'shipping'.")
   }
 }
 
+function checkNonBasicCardRequest(payRequest) {
+  if (payRequest.paymentMethods.length != 1) {
+    emitTestFail("paymentMethods' length should be 1.");
+  }
+
+  const methodData = payRequest.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
+  if (!methodData) {
+    emitTestFail("Fail to get payment methodData.");
+  }
+  const supportedMethod = methodData.supportedMethods;
+  if (supportedMethod != "testing-payment-method") {
+    emitTestFail("supported method should be 'testing-payment-method'.");
+  }
+
+  const paymentId = methodData.data.paymentId;
+  if (paymentId != "P3892940") {
+    emitTestFail("methodData.data.paymentId should be 'P3892940', but got " + paymentId + ".");
+  }
+  const paymentType = methodData.data.paymentType;
+  if (paymentType != "prepaid") {
+    emitTestFail("methodData.data.paymentType should be 'prepaid', but got " + paymentType + ".");
+  }
+
+  // checking the passed PaymentDetails parameter
+  const details = payRequest.paymentDetails;
+  if (details.totalItem.label != "Total") {
+    emitTestFail("total item's label should be 'Total'.");
+  }
+  if (details.totalItem.amount.currency != "USD") {
+    emitTestFail("total item's currency should be 'USD'.");
+  }
+  if (details.totalItem.amount.value != "1.00") {
+    emitTestFail("total item's value should be '1.00'.");
+  }
+
+  if (details.displayItems) {
+    emitTestFail("details.displayItems should be undefined.");
+  }
+  if (details.modifiers) {
+    emitTestFail("details.displayItems should be undefined.");
+  }
+  if (details.shippingOptions) {
+    emitTestFail("details.shippingOptions should be undefined.");
+  }
+
+  // checking the default generated PaymentOptions parameter
+  const paymentOptions = payRequest.paymentOptions;
+  if (paymentOptions.requestPayerName) {
+    emitTestFail("requestPayerName option should be false.");
+  }
+  if (paymentOptions.requestPayerEmail) {
+    emitTestFail("requestPayerEmail option should be false.");
+  }
+  if (paymentOptions.requestPayerPhone) {
+    emitTestFail("requestPayerPhone option should be false.");
+  }
+  if (paymentOptions.requestShipping) {
+    emitTestFail("requestShipping option should be false.");
+  }
+  if (paymentOptions.shippingType != "shipping") {
+    emitTestFail("shippingType option should be 'shipping'.")
+  }
+}
+
 function checkDuplicateShippingOptionsRequest(payRequest) {
   if (payRequest.paymentMethods.length != 1) {
     emitTestFail("paymentMethods' length should be 1.");
   }
 
   const methodData = payRequest.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
   if (!methodData) {
     emitTestFail("Fail to get payment methodData.");
@@ -317,16 +411,33 @@ function checkComplexRequestHandler() {
       break;
     }
     checkComplexRequest(payRequest);
   }
   paymentSrv.cleanup();
   sendAsyncMessage("check-complete");
 }
 
+function checkNonBasicCardRequestHandler() {
+  const paymentEnum = paymentSrv.enumerate();
+  if (!paymentEnum.hasMoreElements()) {
+    emitTestFail("PaymentRequestService should have at least one payment request.");
+  }
+  while (paymentEnum.hasMoreElements()) {
+    let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+    if (!payRequest) {
+      emitTestFail("Fail to get existing payment request.");
+      break;
+    }
+    checkNonBasicCardRequest(payRequest);
+  }
+  paymentSrv.cleanup();
+  sendAsyncMessage("check-complete");
+}
+
 function checkDuplicateShippingOptionsRequestHandler() {
   const paymentEnum = paymentSrv.enumerate();
   if (!paymentEnum.hasMoreElements()) {
     emitTestFail("PaymentRequestService should have at least one payment request.");
   }
   while (paymentEnum.hasMoreElements()) {
     let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
     if (!payRequest) {
@@ -361,13 +472,14 @@ function checkMultipleRequestsHandler ()
   paymentSrv.cleanup();
   sendAsyncMessage("check-complete");
 }
 
 addMessageListener("check-simplest-request", checkSimplestRequestHandler);
 addMessageListener("check-complex-request", checkComplexRequestHandler);
 addMessageListener("check-duplicate-shipping-options-request", checkDuplicateShippingOptionsRequestHandler);
 addMessageListener("check-multiple-requests", checkMultipleRequestsHandler);
+addMessageListener("check-nonbasiccard-request", checkNonBasicCardRequestHandler);
 
 addMessageListener("teardown", function() {
   paymentSrv.cleanup();
   sendAsyncMessage("teardown-complete");
 });
--- a/dom/payments/test/ShowPaymentChromeScript.js
+++ b/dom/payments/test/ShowPaymentChromeScript.js
@@ -8,39 +8,40 @@ const { classes: Cc, interfaces: Ci, uti
 const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
 
 function emitTestFail(message) {
   sendAsyncMessage("test-fail", message);
 }
 
+const shippingAddress = Cc["@mozilla.org/dom/payments/payment-address;1"].
+                           createInstance(Ci.nsIPaymentAddress);
+const addressLine = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+const address = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+address.data = "Easton Ave";
+addressLine.appendElement(address);
+shippingAddress.init("USA",              // country
+                     addressLine,        // address line
+                     "CA",               // region
+                     "San Bruno",        // city
+                     "",                 // dependent locality
+                     "94066",            // postal code
+                     "123456",           // sorting code
+                     "en",               // language code
+                     "",                 // organization
+                     "Bill A. Pacheco",  // recipient
+                     "+1-434-441-3879"); // phone
+
 const NormalUIService = {
   shippingOptionChanged: false,
   canMakePayment: function(requestId) {
     return null;
   },
   showPayment: function(requestId) {
-    const shippingAddress = Cc["@mozilla.org/dom/payments/payment-address;1"].
-                            createInstance(Ci.nsIPaymentAddress);
-    const addressLine = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
-    const address = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
-    address.data = "Easton Ave";
-    addressLine.appendElement(address);
-    shippingAddress.init("USA",              // country
-                         addressLine,        // address line
-                         "CA",               // region
-                         "San Bruno",        // city
-                         "",                 // dependent locality
-                         "94066",            // postal code
-                         "123456",           // sorting code
-                         "en",               // language code
-                         "",                 // organization
-                         "Bill A. Pacheco",  // recipient
-                         "+1-434-441-3879"); // phone
     paymentSrv.changeShippingAddress(requestId, shippingAddress);
     return null;
   },
   abortPayment: function(requestId) {
     return null;
   },
   completePayment: function(requestId) {
     let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
@@ -62,46 +63,63 @@ const NormalUIService = {
       let shippingOption = shippingOptions.queryElementAt(0, Ci.nsIPaymentShippingOption);
       if (shippingOption.selected) {
         emitTestFail(shippingOption.label + " should not be selected.");
       }
       shippingOption = shippingOptions.queryElementAt(1, Ci.nsIPaymentShippingOption);
       if (!shippingOption.selected) {
         emitTestFail(shippingOption.label + " should be selected.");
       }
-      const paymentData = "{\"cardholderName\":\"Bill A. Pacheco\",\"cardNumber\":\"4024007191304152\",\"expiryMonth\":\"05\",\"expiryYear\":\"2019\",\"cardSecurityCode\":\"024\"}";
+
+      const showResponseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
+                                  createInstance(Ci.nsIGeneralResponseData);
+
+      try {
+        showResponseData.initData({ paymentToken: "6880281f-0df3-4b8e-916f-66575e2457c1",});
+      } catch (e) {
+        emitTestFail("Fail to initialize response data with { paymentToken: \"6880281f-0df3-4b8e-916f-66575e2457c1\",}");
+      }
+
       showResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"].
                      createInstance(Ci.nsIPaymentShowActionResponse);
       showResponse.init(requestId,
                         Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED,
-                        "basic-card",               // payment method
-                        paymentData,                // payment method data
+                        "testing-payment-method",   // payment method
+                        showResponseData,           // payment method data
                         "Bill A. Pacheco",          // payer name
                         "",                         // payer email
                         "");                        // payer phone
     }
     return showResponse;
   },
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
 };
 
 const RejectUIService = {
   canMakePayment: function(requestId) {
     return null;
   },
   showPayment: function(requestId) {
+    const responseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
+                            createInstance(Ci.nsIGeneralResponseData);
+
+    try {
+      responseData.initData({});
+    } catch (e) {
+      emitTestFail("Fail to initialize response data with empty object.");
+    }
     const showResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"].
-                         createInstance(Ci.nsIPaymentShowActionResponse);
+                            createInstance(Ci.nsIPaymentShowActionResponse);
     showResponse.init(requestId,
                       Ci.nsIPaymentActionResponse.PAYMENT_REJECTED,
-                      "",       // payment method
-                      "",       // payment method data
-                      "",       // payer name
-                      "",       // payer email
-                      "");      // payer phone
+                      "",                 // payment method
+                      responseData,       // payment method data
+                      "",                 // payer name
+                      "",                 // payer email
+                      "");                // payer phone
 
     return showResponse;
   },
   abortPayment: function(requestId) {
     return null;
   },
   completePayment: function(requestId) {
     return null;
@@ -129,40 +147,78 @@ const ErrorUIService = {
   updatePayment: function(requestId) {
     let payRequest = paymentSrv.getPaymentRequestById(requestId);
     if (!payRequest) {
       emitTestFail("Fail to get existing payment request.");
     }
     if (payRequest.paymentDetails.error != "Update with Error") {
       emitTestFail("details.error should be 'Update with Error', but got " + payRequest.paymentDetails.error + ".");
     }
+    const responseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
+                            createInstance(Ci.nsIGeneralResponseData);
+    try {
+      responseData.initData({});
+    } catch (e) {
+      emitTestFail("Fail to initialize response data with empty object.");
+    }
     const showResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"].
-                         createInstance(Ci.nsIPaymentShowActionResponse);
+                            createInstance(Ci.nsIPaymentShowActionResponse);
     showResponse.init(requestId,
                       Ci.nsIPaymentActionResponse.PAYMENT_REJECTED,
-                      "",       // payment method
-                      "",       // payment method data
-                      "",       // payer name
-                      "",       // payer email
-                      "");      // payer phone
+                      "",                 // payment method
+                      responseData,       // payment method data
+                      "",                 // payer name
+                      "",                 // payer email
+                      "");                // payer phone
+
     return showResponse;
   },
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
 
 };
 
+function testNullDetailsResponseHandler() {
+  const showResponseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
+                              createInstance(Ci.nsIGeneralResponseData);
+  try {
+    showResponseData.initData(null);
+    emitTestFail("nsIGeneralResponseData can not be initialized with null object.");
+  } catch (e) {
+    if (e.name != "NS_ERROR_FAILURE") {
+      emitTestFail("Expected 'NS_ERROR_FAILURE' when initializing nsIGeneralResponseData with null object, but got " + e.name + ".");
+    }
+  }
+  const showResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"].
+                          createInstance(Ci.nsIPaymentShowActionResponse);
+  try {
+    showResponse.init("test request id",
+                      Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED,
+                      "testing-payment-method",   // payment method
+                      showResponseData,           // payment method data
+                      "Bill A. Pacheco",          // payer name
+                      "",                         // payer email
+                      "");                        // payer phone
+  } catch (e) {
+    emitTestFail("Unexpected error " + e.name + " when initializing nsIPaymentShowActionResponse.");
+  }
+  sendAsyncMessage("test-null-details-response-complete");
+}
+
 addMessageListener("set-normal-ui-service", function() {
   paymentSrv.setTestingUIService(NormalUIService.QueryInterface(Ci.nsIPaymentUIService));
 });
 
 addMessageListener("set-reject-ui-service", function() {
   paymentSrv.setTestingUIService(RejectUIService.QueryInterface(Ci.nsIPaymentUIService));
 });
 
 addMessageListener("set-update-with-error-ui-service", function() {
   paymentSrv.setTestingUIService(ErrorUIService.QueryInterface(Ci.nsIPaymentUIService));
 })
 
+addMessageListener("test-null-details-response", testNullDetailsResponseHandler);
+
+
 addMessageListener("teardown", function() {
   paymentSrv.cleanup();
   paymentSrv.setTestingUIService(null);
   sendAsyncMessage('teardown-complete');
 });
--- a/dom/payments/test/head.js
+++ b/dom/payments/test/head.js
@@ -3,17 +3,17 @@ const kTestRoot = getRootDirectory(gTest
 
 function checkSimplePayment(aSimplePayment) {
   // checking the passed PaymentMethods parameter
   is(aSimplePayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
 
   const methodData = aSimplePayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
   ok(methodData, "Fail to get payment methodData.");
   is(methodData.supportedMethods, "MyPay", "supported method should be 'MyPay'.");
-  is(methodData.data, "", "method data should be empty");
+  ok(!methodData.data, "methodData.data should not exist.");
 
   // checking the passed PaymentDetails parameter
   const details = aSimplePayment.paymentDetails;
   is(details.id, "simple details", "details.id should be 'simple details'.");
   is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
   is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
   is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
 
@@ -32,17 +32,17 @@ function checkSimplePayment(aSimplePayme
 
 function checkComplexPayment(aPayment) {
   // checking the passed PaymentMethods parameter
   is(aPayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
 
   const methodData = aPayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
   ok(methodData, "Fail to get payment methodData.");
   is(methodData.supportedMethods, "MyPay", "supported method should be 'MyPay'.");
-  is(methodData.data, "", "method data should be empty");
+  ok(!methodData.data, "methodData.data should not exist.");
 
   // checking the passed PaymentDetails parameter
   const details = aPayment.paymentDetails;
   is(details.id, "complex details", "details.id should be 'complex details'.");
   is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
   is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
   is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
 
@@ -67,18 +67,19 @@ function checkComplexPayment(aPayment) {
   is(modifier.total.amount.value, "45.00", "modifier's total value should be '45.00'.");
 
   const additionalItems = modifier.additionalDisplayItems;
   is(additionalItems.length, "1", "additionalDisplayItems' length should be 1.");
   const additionalItem = additionalItems.queryElementAt(0, Ci.nsIPaymentItem);
   is(additionalItem.label, "MyPay discount", "additional item's label should be 'MyPay discount'.");
   is(additionalItem.amount.currency, "USD", "additional item's currency should be 'USD'.");
   is(additionalItem.amount.value, "-10.00", "additional item's value should be '-10.00'.");
-  is(modifier.data, "{\"discountProgramParticipantId\":\"86328764873265\"}",
-     "modifier's data should be '{\"discountProgramParticipantId\":\"86328764873265\"}'.");
+  ok(modifier.data, "moidifer.data should exist.");
+  is(modifier.data.discountProgramParticipantId, "86328764873265",
+     "modifier.data.discountProgramParticipantId should be '86328764873265'.");
 
   const shippingOptions = details.shippingOptions;
   is(shippingOptions.length, 2, "shippingOptions' length should be 2.");
 
   let shippingOption = shippingOptions.queryElementAt(0, Ci.nsIPaymentShippingOption);
   is(shippingOption.id, "NormalShipping", "1st shippingOption's id should be 'NoramlShpping'.");
   is(shippingOption.label, "NormalShipping", "1st shippingOption's lable should be 'NormalShipping'.");
   is(shippingOption.amount.currency, "USD", "1st shippingOption's amount currency should be 'USD'.");
@@ -102,18 +103,18 @@ function checkComplexPayment(aPayment) {
 }
 
 function checkDupShippingOptionsPayment(aPayment) {
   // checking the passed PaymentMethods parameter
   is(aPayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
 
   const methodData = aPayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
   ok(methodData, "Fail to get payment methodData.");
-  is(methodData.supportedMethods, "MyPay", "modifier's supported method name should be 'MyPay'.");
-  is(methodData.data, "", "method data should be empty");
+  is(methodData.supportedMethods, "MyPay", "methodData.supportedMethod name should be 'MyPay'.");
+  ok(!methodData.data, "methodData.data should not exist.");
 
   // checking the passed PaymentDetails parameter
   const details = aPayment.paymentDetails;
   is(details.id, "duplicate shipping options details", "details.id should be 'duplicate shipping options details'.");
   is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
   is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
   is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
 
--- a/dom/payments/test/mochitest.ini
+++ b/dom/payments/test/mochitest.ini
@@ -1,16 +1,18 @@
 [DEFAULT]
 # skip-if !e10s will be removed once non-e10s is supported
 skip-if = !e10s
 scheme = https
 support-files =
   simple_payment_request.html
+  BasiccardChromeScript.js
   CanMakePaymentChromeScript.js
   ConstructorChromeScript.js
   ShowPaymentChromeScript.js
 
 [test_abortPayment.html]
+[test_basiccard.html]
 [test_canMakePayment.html]
 [test_constructor.html]
 [test_showPayment.html]
 [test_validate_decimal_value.html]
 [test_payment-request-in-iframe.html]
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/test_basiccard.html
@@ -0,0 +1,298 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1375345
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1375345</title>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript">
+
+  "use strict";
+  SimpleTest.waitForExplicitFinish();
+
+  var gUrl = SimpleTest.getTestFileURL('BasiccardChromeScript.js');
+  var gScript = SpecialPowers.loadChromeScript(gUrl);
+
+  function testFailHandler(message) {
+    ok(false, message);
+  }
+  gScript.addMessageListener("test-fail", testFailHandler);
+
+  const errorTypesMethods = [{
+    supportedMethods: "basic-card",
+    data: {
+      supportedTypes: ["myType"],
+    },
+  }];
+
+  const errorNetworksMethods = [{
+    supportedMethods: "basic-card",
+    data: {
+      supportedNetworks: ["myNetwork"],
+    },
+  }];
+
+  const nullDataMethods = [{
+    supportedMethods: "basic-card",
+  }];
+
+  const emptyDataMethods = [{
+    supportedMethods: "basic-card",
+    data: {},
+  }];
+
+  const unconvertableDataMethods = [{
+    supportedMethods: "basic-card",
+    data: "unconvertable data",
+  }];
+
+  const defaultMethods = [{
+    supportedMethods: "basic-card",
+    data: {
+      supportedNetworks: ["unionpay", "visa", "mastercard", "amex", "discover",
+                          "diners", "jcb", "mir",
+      ],
+      supportedTypes: ["prepaid", "debit", "credit"],
+    },
+  }];
+  const defaultDetails = {
+    id: "test payment",
+    total: {
+      label: "Total",
+      amount: {
+        currency: "USD",
+        value: "1.00"
+      }
+    },
+    shippingOptions: [
+      {
+        id: "NormalShipping",
+        label: "NormalShipping",
+        amount: {
+          currency: "USD",
+          value: "10.00"
+        },
+        selected: true,
+      },
+      {
+        id: "FastShipping",
+        label: "FastShipping",
+        amount: {
+          currency: "USD",
+          value: "30.00"
+        },
+        selected: false,
+      },
+    ],
+  };
+
+  const defaultOptions = {
+    requestPayerName: true,
+    requestPayerEmail: false,
+    reqeustPayerPhone: false,
+    requestShipping: true,
+    shippingType: "shipping"
+  };
+
+  function testBasicCardRequestWithErrorTypes() {
+    return new Promise((resolve, reject) => {
+      try {
+        const payRequest = new PaymentRequest(errorTypesMethods, defaultDetails, defaultOptions);
+        ok(false, "Expected 'TypeError', but got success construction.");
+        resolve();
+      } catch (e) {
+        is(e.name, "TypeError", "Expected TypeError, but got " + e.name);
+        resolve();
+      }
+    });
+  }
+
+  function testBasicCardRequestWithErrorNetworks() {
+    return new Promise((resolve, reject) => {
+      try {
+        const payRequest = new PaymentRequest(errorNetworksMethods, defaultDetails, defaultOptions);
+        ok(false, "Expected 'TypeError', but got success construction.");
+        resolve();
+      } catch (e) {
+        is(e.name, "TypeError", "Expected TypeError, but got " + e.name);
+        resolve();
+      }
+    });
+  }
+
+  function testBasicCardRequestWithUnconvertableData() {
+    return new Promise((resolve, reject) => {
+      try {
+        const payRequest = new PaymentRequest(unconvertableDataMethods, defaultDetails, defaultOptions);
+        ok(false, "Expected 'TypeError', but got success construction.");
+        resolve();
+      } catch (e) {
+        is(e.name, "TypeError", "Expected TypeError, but got " + e.name);
+        resolve();
+      }
+    });
+  }
+
+  function testBasicCardRequestWithNullData() {
+    return new Promise((resolve, reject) => {
+      try {
+        const payRequest = new PaymentRequest(nullDataMethods, defaultDetails, defaultOptions);
+        ok(payRequest, "PaymentRequest should be constructed with null data BasicCardRequest.");
+        resolve();
+      } catch (e) {
+        ok(false, "Unexpected error: " + e.name);
+        resolve();
+      }
+    });
+  }
+
+  function testBasicCardRequestWithEmptyData() {
+    return new Promise((resolve, reject) => {
+      try {
+        const payRequest = new PaymentRequest(emptyDataMethods, defaultDetails, defaultOptions);
+        ok(payRequest, "PaymentRequest should be constructed with empty data BasicCardRequest.");
+        resolve();
+      } catch (e) {
+        ok(false, "Unexpected error: " + e.name);
+        resolve();
+      }
+    });
+  }
+
+  function testCanMakePaymentWithBasicCardRequest() {
+    return new Promise((resolve, reject) => {
+      const payRequest = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
+      payRequest.canMakePayment().then( result => {
+        ok(result, "Should be resolved with true, but got false.");
+        resolve();
+      }).catch (e => {
+        ok(false, "Unexpected error: " + e.name);
+        resolve();
+      });
+    });
+  }
+
+  function testBasicCardSimpleResponse() {
+    gScript.sendAsyncMessage("set-simple-ui-service");
+    return new Promise((resolve, reject) => {
+      const payRequest = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
+      payRequest.show().then(response => {
+        ok(response.details, "basiccard response should exists.");
+        ok(!response.details.cardholderName, "response.details.cardholderName should not exist.");
+        is(response.details.cardNumber, "4916855166538720", "response.details.cardNumber should be '4916855166538720'.");
+        ok(!response.details.expiryMonth, "response.details.expiryMonth should not exist.");
+        ok(!response.details.expiryYear, "response.details.expiryYear should be '2024'.");
+        ok(!response.details.cardSecurityCode, "response.details.cardSecurityCode should not exist.");
+        ok(!response.details.billingAddress, "response.details.billingAddress should not exist.");
+        response.complete("success").then(() =>{
+          resolve();
+        }).catch(e => {
+          ok(false, "Unexpected error: " + e.name);
+          resolve();
+        });
+      }).catch( e => {
+        ok(false, "Unexpected error: " + e.name);
+        resolve();
+      });
+    });
+  }
+
+  function testBasicCardDetailedResponse() {
+    gScript.sendAsyncMessage("set-detailed-ui-service");
+    return new Promise((resolve, reject) => {
+      const payRequest = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
+      payRequest.show().then(response => {
+        ok(response.details, "basiccard response should exists.");
+        is(response.details.cardholderName, "Bill A. Pacheco", "response.details.cardholderName should be 'Bill A. Pacheco'.");
+        is(response.details.cardNumber, "4916855166538720", "response.details.cardNumber should be '4916855166538720'.");
+        is(response.details.expiryMonth, "01", "response.details.expiryMonth should be '01'.");
+        is(response.details.expiryYear, "2024", "response.details.expiryYear should be '2024'.");
+        is(response.details.cardSecurityCode, "180", "response.details.cardSecurityCode should be '180'.");
+        const billingAddress = response.details.billingAddress;
+        is(billingAddress.country, "USA", "country should be 'USA'.");
+        is(billingAddress.addressLine.length, 1, "addressLine.length should be 1.");
+        is(billingAddress.addressLine[0], "Easton Ave", "addressLine[0] should be 'Easton Ave'.");
+        is(billingAddress.region, "CA", "region should be 'CA'.");
+        is(billingAddress.city, "San Bruno", "city should be 'San Bruno'.");
+        is(billingAddress.dependentLocality, "", "dependentLocality should be empty.");
+        is(billingAddress.postalCode, "94066", "postalCode should be '94066'.");
+        is(billingAddress.sortingCode, "123456", "sortingCode should be '123456'.");
+        is(billingAddress.languageCode, "en", "languageCode should be 'en'.");
+        is(billingAddress.organization, "", "organization should be empty." );
+        is(billingAddress.recipient, "Bill A. Pacheco", "recipient should be 'Bill A. Pacheco'.");
+        is(billingAddress.phone, "+14344413879", "phone should be '+14344413879'.");
+        response.complete("success").then(() =>{
+          resolve();
+        }).catch(e => {
+          ok(false, "Unexpected error: " + e.name);
+          resolve();
+        });
+      }).catch( e => {
+        ok(false, "Unexpected error: " + e.name);
+        resolve();
+      });
+    });
+  }
+
+  function testBasicCardErrorResponse() {
+    return new Promise((resolve, reject) => {
+      gScript.addMessageListener("error-response-complete",
+                                 function errorResponseCompleteHandler() {
+        gScript.removeMessageListener("error-response-complete",
+                                      errorResponseCompleteHandler);
+        resolve();
+      });
+      gScript.sendAsyncMessage("error-response-test");
+    });
+  }
+
+  function teardown() {
+    gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() {
+      gScript.removeMessageListener("teardown-complete", teardownCompleteHandler);
+      gScript.removeMessageListener("test-fail", testFailHandler)
+      gScript.destroy();
+      SimpleTest.finish();
+    });
+    gScript.sendAsyncMessage("teardown");
+  }
+
+  function runTests() {
+    testBasicCardRequestWithErrorTypes()
+    .then(testBasicCardRequestWithErrorNetworks)
+    .then(testBasicCardRequestWithUnconvertableData)
+    .then(testBasicCardRequestWithNullData)
+    .then(testBasicCardRequestWithEmptyData)
+    .then(testCanMakePaymentWithBasicCardRequest)
+    .then(testBasicCardSimpleResponse)
+    .then(testBasicCardDetailedResponse)
+    .then(testBasicCardErrorResponse)
+    .then(teardown)
+    .catch( e => {
+      ok(false, "Unexpected error: " + e.name);
+      SimpleTest.finish();
+    });
+  }
+
+  window.addEventListener('load', function() {
+    SpecialPowers.pushPrefEnv({
+      'set': [
+        ['dom.payments.request.enabled', true],
+      ]
+    }, runTests);
+  });
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1375345">Mozilla Bug 1375345</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/dom/payments/test/test_constructor.html
+++ b/dom/payments/test/test_constructor.html
@@ -39,16 +39,24 @@ https://bugzilla.mozilla.org/show_bug.cg
     data: {
       supportedNetworks: ['unionpay', 'visa', 'mastercard', 'amex', 'discover',
                           'diners', 'jcb', 'mir',
       ],
       supportedTypes: ['prepaid', 'debit', 'credit'],
     },
   }];
 
+  const nonBasicCardMethods = [{
+    supportedMethods: "testing-payment-method",
+    data: {
+      paymentId: "P3892940",
+      paymentType: "prepaid",
+    },
+  }];
+
   const complexDetails = {
     id: "payment details",
     total: {
       label: "Total",
       amount: {
         currency: "USD",
         value: "100.00"
       }
@@ -172,16 +180,28 @@ https://bugzilla.mozilla.org/show_bug.cg
       gScript.addMessageListener("check-complete", function checkCompleteHandler() {
         gScript.removeMessageListener("check-complete", checkCompleteHandler);
         resolve();
       });
       gScript.sendAsyncMessage("check-complex-request");
     });
   }
 
+  function testWithNonBasicCardMethods() {
+    return new Promise((resolve, reject) => {
+      const payRequest = new PaymentRequest(nonBasicCardMethods, simplestDetails);
+      ok(payRequest, "PaymentRequest should be created");
+      gScript.addMessageListener("check-complete", function checkCompleteHandler() {
+        gScript.removeMessageListener("check-complete", checkCompleteHandler);
+        resolve();
+      });
+      gScript.sendAsyncMessage("check-nonbasiccard-request");
+    });
+  }
+
   function testWithDuplicateShippingOptionsParameters() {
     return new Promise((resolve, reject) => {
       const payRequest = new PaymentRequest(simplestMethods, duplicateShippingOptionsDetails);
       ok(payRequest, "PaymentRequest should be created");
       gScript.addMessageListener("check-complete", function checkCompleteHandler() {
         gScript.removeMessageListener("check-complete", checkCompleteHandler);
         resolve();
       });
@@ -213,16 +233,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       SimpleTest.finish();
     });
     gScript.sendAsyncMessage("teardown");
   }
 
   function runTests() {
     testWithSimplestParameters()
     .then(testWithComplexParameters)
+    .then(testWithNonBasicCardMethods)
     .then(testWithDuplicateShippingOptionsParameters)
     .then(testMultipleRequests)
     .then(teardown)
     .catch( e => {
       ok(false, "Unexpected error: " + e.name);
       SimpleTest.finish();
     });
   }
--- a/dom/payments/test/test_showPayment.html
+++ b/dom/payments/test/test_showPayment.html
@@ -24,16 +24,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   const defaultMethods = [{
     supportedMethods: "basic-card",
     data: { 
       supportedNetworks: ['unionpay', 'visa', 'mastercard', 'amex', 'discover',
                           'diners', 'jcb', 'mir',
       ],
       supportedTypes: ['prepaid', 'debit', 'credit'],
     },
+  }, {
+    supportedMethods: "testing-payment-method",
   }];
   const defaultDetails = {
     id: "test payment",
     total: {
       label: "Total",
       amount: {
         currency: "USD",
         value: "1.00"
@@ -155,22 +157,18 @@ https://bugzilla.mozilla.org/show_bug.cg
       payRequest.addEventListener("shippingaddresschange", event => {
         event.updateWith(updateWithShippingAddress());
       });
       payRequest.addEventListener("shippingoptionchange", event => {
         event.updateWith(updateWithShippingOption());
       });
       payRequest.show().then(response => {
         is(response.requestId, "test payment", "response.requestId should be 'test payment'.");
-        is(response.methodName, "basic-card", "response.methodName should be 'basic-card'.");
-        is(response.details.cardholderName, "Bill A. Pacheco", "response.details.cardholderName should be 'Bill A. Pacheco'.");
-        is(response.details.cardNumber, "4024007191304152", "response.details.cardNumber should be '4024007191304152'.");
-        is(response.details.expiryMonth, "05", "response.details.expiryMonth should be '05'.");
-        is(response.details.expiryYear, "2019", "response.details.expiryYear should be '2019'.");
-        is(response.details.cardSecurityCode, "024", "response.details.cardSecurityCode should be '024'.");
+        is(response.methodName, "testing-payment-method", "response.methodName should be 'testing-payment-method'.");
+        is(response.details.paymentToken, "6880281f-0df3-4b8e-916f-66575e2457c1", "response.details.paymentToken should be '6880281f-0df3-4b8e-916f-66575e2457c1'.");
         is(response.shippingAddress.country, "USA", "response.shippingAddress.country should be 'USA'.");
         is(response.shippingAddress.addressLine.length, 1, "response.shippingAddress.addressLine.length should be 1.");
         is(response.shippingAddress.addressLine[0], "Easton Ave", "response.shippingAddress.addressLine[0] should be 'Easton Ave'.");
         is(response.shippingAddress.region, "CA", "response.shippingAddress.region should be 'CA'.");
         is(response.shippingAddress.city, "San Bruno", "response.shippingAddress.city should be 'San Bruno'.");
         is(response.shippingAddress.dependentLocality, "", "response.shippingAddress.dependentLocality should be empty.");
         is(response.shippingAddress.postalCode, "94066", "response.shippingAddress.postalCode should be '94066'.");
         is(response.shippingAddress.sortingCode, "123456", "response.shippingAddress.sortingCode should be '123456'.");
@@ -229,30 +227,43 @@ https://bugzilla.mozilla.org/show_bug.cg
         resolve();
       }).catch(e => {
         ok(false, "Unexpected error: " + e.name);
         resolve();
       });
     });
   }
 
+  function testNullDetailsResponse() {
+    return new Promise((resolve, reject) => {
+      gScript.addMessageListener("test-null-details-response-complete",
+                                 function nullDetailsResponseCompleteHandler() {
+        gScript.removeMessageListener("test-null-details-response-complete",
+                                      nullDetailsResponseCompleteHandler);
+        resolve();
+      });
+      gScript.sendAsyncMessage("test-null-details-response");
+    });
+  }
+
   function teardown() {
     gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() {
       gScript.removeMessageListener("teardown-complete", teardownCompleteHandler);
       gScript.removeMessageListener("test-fail", testFailHandler)
       gScript.destroy();
       SimpleTest.finish();
     });
     gScript.sendAsyncMessage("teardown");
   }
 
   function runTests() {
     testRejectShow()
     .then(testShow)
     .then(testUpdateWithError)
+    .then(testNullDetailsResponse)
     .then(teardown)
     .catch( e => {
       ok(false, "Unexpected error: " + e.name);
       SimpleTest.finish();
     });
   }
 
   window.addEventListener('load', function() {
--- a/dom/payments/test/test_validate_decimal_value.html
+++ b/dom/payments/test/test_validate_decimal_value.html
@@ -50,17 +50,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   function testInvalidTotalAmounts() {
     return new Promise((resolve, reject) => {
       for (const amount of invalidTotalAmounts) {
         try {
           new PaymentRequest(
             [
               {
-                supportedMethods: ["basic-card"],
+                supportedMethods: "basic-card",
               },
             ],
             {
               total: {
                 label: "",
                 amount: {
                   currency: "USD",
                   value: amount,
@@ -83,17 +83,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   function testInvalidAmounts() {
      return new Promise((resolve, reject) => {
       for (const amount of invalidAmounts) {
         try {
           new PaymentRequest(
             [
               {
-                supportedMethods: ["basic-card"],
+                supportedMethods: "basic-card",
               },
             ],
             {
               total: {
                 label: "",
                 amount: {
                   currency: "USD",
                   value: "1.00",