tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_showPayment.html (17093B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <!--
      4 https://bugzilla.mozilla.org/show_bug.cgi?id=1345366
      5 -->
      6 <head>
      7  <meta charset="utf-8">
      8  <title>Test for Bug 1345366</title>
      9  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
     10  <script src="/tests/SimpleTest/SimpleTest.js"></script>
     11  <script type="application/javascript">
     12 
     13  "use strict";
     14  SimpleTest.waitForExplicitFinish();
     15 
     16  var gUrl = SimpleTest.getTestFileURL('ShowPaymentChromeScript.js');
     17  var gScript = SpecialPowers.loadChromeScript(gUrl);
     18 
     19  function testFailHandler(message) {
     20    ok(false, message);
     21  }
     22  function testPassHandler(message) {
     23    ok(true, message);
     24  }
     25  gScript.addMessageListener("test-fail", testFailHandler);
     26  gScript.addMessageListener("test-pass", testPassHandler);
     27 
     28  async function requestChromeAction(action, params) {
     29    await new Promise(resolve => {
     30      gScript.addMessageListener(`${action}-complete`, function completeListener() {
     31        gScript.removeMessageListener(`${action}-complete`, completeListener);
     32        resolve();
     33      });
     34      gScript.sendAsyncMessage(action, params);
     35    });
     36  }
     37 
     38  // testing data declaration
     39  // default parameters for PaymentRequest construction
     40  const defaultMethods = [{
     41    supportedMethods: "basic-card",
     42    data: {
     43      supportedNetworks: ['unionpay', 'visa', 'mastercard', 'amex', 'discover',
     44                          'diners', 'jcb', 'mir',
     45      ],
     46    },
     47  }, {
     48    supportedMethods: "testing-payment-method",
     49  }];
     50 
     51  const defaultTotal = {
     52    label: "Total",
     53    amount: {
     54      currency: "USD",
     55      value: "1.00",
     56    },
     57  }
     58 
     59  const defaultDetails = {
     60    id: "test payment",
     61    total: defaultTotal,
     62    shippingOptions: [
     63      {
     64        id: "NormalShipping",
     65        label: "NormalShipping",
     66        amount: {
     67          currency: "USD",
     68          value: "10.00"
     69        },
     70        selected: false,
     71      },
     72      {
     73        id: "FastShipping",
     74        label: "FastShipping",
     75        amount: {
     76          currency: "USD",
     77          value: "30.00"
     78        },
     79        selected: false,
     80      },
     81    ],
     82  };
     83 
     84  const defaultOptions = {
     85    requestPayerName: true,
     86    requestPayerEmail: false,
     87    requestPayerPhone: false,
     88    requestShipping: true,
     89    shippingType: "shipping"
     90  };
     91 
     92  // testing data for PaymentRequestUpdateEvent.updateWith()
     93  const updatedShippingOptionsDetails = {
     94    total: defaultTotal,
     95    shippingOptions: [
     96      {
     97        id: "NormalShipping",
     98        label: "NormalShipping",
     99        amount: {
    100          currency: "USD",
    101          value: "10.00"
    102        },
    103        selected: false,
    104      },
    105      {
    106        id: "FastShipping",
    107        label: "FastShipping",
    108        amount: {
    109          currency: "USD",
    110          value: "30.00"
    111        },
    112        selected: true,
    113      },
    114    ],
    115  };
    116 
    117  const updatedErrorDetails = {
    118    total: defaultTotal,
    119    error: "Update with Error",
    120  };
    121 
    122  // Promise function for PaymentRequestUpdateEvent.updateWith()
    123  function updateWithPromise(detailsUpdate) {
    124    return new Promise((resolve, reject) => {
    125      if (detailsUpdate) {
    126        resolve(detailsUpdate);
    127      } else {
    128        reject();
    129      }
    130    });
    131  }
    132 
    133  // testing data for PaymentRequest.show() with Non-supported methods
    134  const nonSupportedMethods = [{
    135    supportedMethods: "nonsupported-method",
    136  }];
    137 
    138 
    139  // checking functions
    140  function checkAddress(testName, address, fromEvent) {
    141    is(address.country,
    142       "USA",
    143       `${testName}: address.country should be 'USA'.`);
    144    is(address.region,
    145       "CA",
    146       `${testName}: address.region should be 'CA'.`);
    147    is(address.city,
    148       "San Bruno",
    149       `${testName}: address.city should be 'San Bruno'.`);
    150    is(address.dependentLocality,
    151       "Test locality",
    152       `${testName}: address.dependentLocality should be 'Test locality'.`);
    153    is(address.postalCode,
    154       "94066",
    155       `${testName}: address.postalCode should be '94066'.`);
    156    is(address.sortingCode,
    157       "123456",
    158       `${testName}: address.sortingCode should be '123456'.`);
    159    if (fromEvent) {
    160      is(address.addressLine.length,
    161         0,
    162         `${testName}: address.addressLine.length should be 0 from event.`);
    163      is(address.organization,
    164         "",
    165         `${testName}: address.organization should be empty from event.`);
    166      is(address.recipient,
    167         "",
    168         `${testName}: address.recipient should be empty from event.`);
    169      is(address.phone,
    170         "",
    171         `${testName}: address.phone should be empty from event.`);
    172    } else {
    173      is(address.addressLine.length,
    174         1,
    175         `${testName}: address.addressLine.length should be 1 from promise.`);
    176      is(address.addressLine[0],
    177         "Easton Ave",
    178         `${testName}: address.addressLine[0] should be 'Easton Ave' from promise.`);
    179      is(address.organization,
    180         "Testing Org",
    181         `${testName}: address.organization should be 'Testing Org' from promise.`);
    182      is(address.recipient,
    183         "Bill A. Pacheco",
    184         `${testName}: address.recipient should be 'Bill A. Pacheco' from promise.`);
    185      is(address.phone,
    186         "+1-434-441-3879",
    187         `${testName}: address.phone should be '+1-434-441-3879' from promise.`);
    188    }
    189  }
    190 
    191  function checkResponse(testName, response) {
    192    is(response.requestId,
    193       "test payment",
    194       `${testName}: response.requestId should be 'test payment'.`);
    195    is(response.methodName,
    196       "testing-payment-method",
    197       `${testName}: response.methodName should be 'testing-payment-method'.`);
    198    is(response.details.paymentToken,
    199       "6880281f-0df3-4b8e-916f-66575e2457c1",
    200       `${testName}: response.details.paymentToken should be '6880281f-0df3-4b8e-916f-66575e2457c1'.`);
    201    checkAddress(testName, response.shippingAddress, false/*fromEvent*/);
    202    is(response.shippingOption,
    203       "FastShipping",
    204       `${testName}: response.shippingOption should be 'FastShipping'.`);
    205    is(response.payerName,
    206       "Bill A. Pacheco",
    207       `${testName}: response.payerName should be 'Bill A. Pacheco'.`);
    208    ok(!response.payerEmail,
    209       `${testName}: response.payerEmail should be empty`);
    210    ok(!response.payerPhone,
    211       `${testName}: response.payerPhone should be empty`);
    212  }
    213 
    214  // testing functions
    215  async function testShowNormalFlow() {
    216    const testName = "testShowNormalFlow";
    217    await requestChromeAction("set-normal-ui-service", testName);
    218 
    219    const request = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
    220    request.addEventListener("shippingaddresschange", event => {
    221      checkAddress(testName, request.shippingAddress, true/*fromEvent*/);
    222      event.updateWith(updateWithPromise(defaultDetails));
    223    });
    224    request.addEventListener("shippingoptionchange", event => {
    225      event.updateWith(updateWithPromise(updatedShippingOptionsDetails));
    226    });
    227    const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
    228    try {
    229      let response = await request.show();
    230      checkResponse(testName, response, false);
    231      await response.complete();
    232    } catch (error) {
    233      ok(false, `${testName} Unexpected error: ${e.name}`);
    234    }
    235    await handler.destruct();
    236  }
    237 
    238  // testing show with nonsupported methods
    239  async function testCannotMakePaymentShow() {
    240    const testName = "testCannotMakePaymentShow";
    241    await requestChromeAction("set-simple-ui-service", testName);
    242 
    243    const request = new PaymentRequest(nonSupportedMethods, defaultDetails);
    244    const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
    245    let result = await request.canMakePayment();
    246    ok(!result, `${testName}: canMakePayment() should return false.`);
    247    try {
    248      await request.show();
    249      ok(false, `${testName}: should be rejected with 'NotSupportedError' but got resolved.`);
    250    } catch (error) {
    251      is(error.name, "NotSupportedError", `${testName}: should be rejected with 'NotSupportedError'.`);
    252    }
    253    await handler.destruct();
    254  }
    255 
    256  // testing show rejected by user
    257  async function testRejectShow() {
    258    const testName = "testRejectShow";
    259    await requestChromeAction("set-reject-ui-service", testName);
    260 
    261    const request = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
    262    const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
    263    try {
    264      await request.show();
    265      ok(false, `${testName}: Should be rejected with 'AbortError' but got resolved.`);
    266    } catch(error) {
    267      is(error.name, "AbortError", `${testName}: Should be rejected with 'AbortError'.`);
    268    }
    269    await handler.destruct();
    270  }
    271 
    272  // testing PaymentResponse.complete() with specified result
    273  async function testCompleteStatus(testName, result) {
    274    await requestChromeAction("set-simple-ui-service", testName);
    275    if (result) {
    276      await requestChromeAction(`set-complete-status-${result}`);
    277    } else {
    278      await requestChromeAction(`set-complete-status-unknown`);
    279    }
    280 
    281    const request = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
    282    const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
    283    try {
    284      let response = await request.show();
    285      await response.complete(result);
    286    } catch (error) {
    287      ok(false, `${testName}: Unexpected error ${error.name}.`);
    288    }
    289    await handler.destruct();
    290  }
    291 
    292  async function testCompleteFail() {
    293    const testName = "testCompleteFail";
    294    return testCompleteStatus(testName, "fail");
    295  }
    296 
    297  async function testCompleteSuccess() {
    298    const testName = "testCompleteSuccess";
    299    return testCompleteStatus(testName, "success");
    300  }
    301 
    302  async function testCompleteUnknown() {
    303    const testName = "testCompleteUnknown"
    304    return testCompleteStatus(testName, "unknown");
    305  }
    306 
    307  async function testCompleteEmpty() {
    308    const testName = "testCompleteEmpty";
    309    return testCompleteStatus(testName);
    310  }
    311 
    312  // testing PaymentRequestUpdateEvent.updateWith with specified details and error
    313  async function testUpdateWith(testName, detailsUpdate, expectedError) {
    314    if (expectedError) {
    315      await requestChromeAction("set-update-with-error-ui-service", testName);
    316    } else {
    317      await requestChromeAction("set-update-with-ui-service", testName);
    318    }
    319 
    320    const request = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
    321    request.addEventListener("shippingaddresschange", event => {
    322      event.updateWith(updateWithPromise(detailsUpdate));
    323    });
    324    request.addEventListener("shippingoptionchange", event => {
    325      event.updateWith(updateWithPromise(detailsUpdate));
    326    });
    327    const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
    328    try {
    329      const response = await request.show();
    330      if (expectedError) {
    331        ok(false, `${testName}: Should be rejected with ${expectedError} but got resolved.`);
    332      } else {
    333        await response.complete("success");
    334      }
    335    } catch(error) {
    336      if (expectedError) {
    337        is(error.name, expectedError, `${testName}: Should be rejected with ${expectedError}.`);
    338      } else {
    339        ok(false, `${testName}: Unexpected error ${error.name}.`);
    340      }
    341    }
    342    await handler.destruct();
    343  }
    344 
    345  async function testUpdateWithReject() {
    346    const testName = "testUpdateWithReject";
    347    return testUpdateWith(testName, null, "AbortError");
    348  }
    349 
    350  async function testUpdateWithValidDetails() {
    351    const testName = "testUpdateWithValidDetails";
    352    return testUpdateWith(testName, updatedShippingOptionsDetails, null);
    353  }
    354 
    355  async function testUpdateWithInvalidDetails() {
    356    const testName = "testUpdateWithInvalidDetails";
    357    return testUpdateWith(testName, {total: "invalid details"}, "TypeError");
    358  }
    359 
    360  async function testUpdateWithError() {
    361    const testName = "testUpdateWithError";
    362    return testUpdateWith(testName, updatedErrorDetails, "AbortError");
    363  }
    364 
    365  // testing show with detailsUpdate promise
    366  async function testShowWithDetailsPromise(testName, detailsUpdate, expectedError) {
    367    if (expectedError) {
    368      await requestChromeAction("set-reject-ui-service", testName);
    369    } else {
    370      await requestChromeAction("set-simple-ui-service", testName);
    371    }
    372 
    373    const request = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
    374    ok(!request.shippingOption, `${testName}: request.shippingOption should be null.`);
    375    const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
    376    try {
    377      let response = await request.show(updateWithPromise(detailsUpdate));
    378      if (expectedError) {
    379        ok(false, `${testName}: Should be rejected with ${expectedError} but got resolved.`);
    380      } else {
    381        ok(response.shippingOption,
    382           `${testName}: response.shippingOption should not be null.`);
    383      }
    384      await response.complete();
    385    } catch(error) {
    386      if (expectedError) {
    387        is(error.name, expectedError, `${testName}: Should be rejected with ${expectedError}.`);
    388      } else {
    389        ok(false, `${testName}: Unexpected error ${error.name}.`);
    390      }
    391    }
    392    await handler.destruct();
    393  }
    394  async function testShowWithValidPromise() {
    395    const testName = "testShowWithValidPromise";
    396    return testShowWithDetailsPromise(testName, updatedShippingOptionsDetails, null);
    397  }
    398 
    399  async function testShowWithRejectedPromise() {
    400    const testName = "testShowWithRejectedPromise";
    401    return testShowWithDetailsPromise(testName, null, "AbortError");
    402  }
    403 
    404  async function testShowWithInvalidPromise() {
    405    const testName = "testShowWithInvalidPromise";
    406    return testShowWithDetailsPromise(testName, {total: "invalid details"}, "TypeError");
    407  }
    408 
    409  async function testShowWithErrorPromise() {
    410    const testName = "testShowWithErrorPromise";
    411    return testShowWithDetailsPromise(testName, updatedErrorDetails, "AbortError");
    412  }
    413 
    414  async function testShowWithPromiseResolvedByRejectedPromise() {
    415    const testName = "testShowWithPromiseResolvedByRejectedPromise";
    416    await requestChromeAction("set-reject-ui-service", testName);
    417 
    418    const request = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions);
    419    const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
    420    let rejectPromise = Promise.reject(new TypeError());
    421    let detailsUpdatePromise = Promise.resolve(rejectPromise);
    422    try {
    423      await request.show(detailsUpdatePromise);
    424      ok(false, `${testName}: should be rejected with AbortError but got resolved.`);
    425    } catch(error) {
    426      is(error.name, "AbortError", `${testName}: should be rejected with AbortError.`);
    427    }
    428    await handler.destruct();
    429  }
    430 
    431  // testing show response initialization in chrome process
    432  async function testShowResponseInit() {
    433    const testName = "testShowResponseInit";
    434    await requestChromeAction("test-show-response-init", testName);
    435  }
    436 
    437  // testing show that is not triggered by user.
    438  async function testShowNotTriggeredByUser() {
    439    const testName = "testShowNotTriggeredByUser";
    440    await requestChromeAction("set-simple-ui-service", testName);
    441 
    442    const request = new PaymentRequest(defaultMethods, defaultDetails);
    443    try {
    444      await request.show();
    445      ok(false, `${testName}: should be rejected with SecurityError, but got resolved.`);
    446    } catch (error) {
    447      is(error.name, "SecurityError", `${testName}: should be rejected with SecurityError.`);
    448    }
    449  }
    450 
    451  // teardown function
    452  async function teardown() {
    453    gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() {
    454      gScript.removeMessageListener("teardown-complete", teardownCompleteHandler);
    455      gScript.removeMessageListener("test-fail", testFailHandler);
    456      gScript.removeMessageListener("test-pass", testPassHandler);
    457      gScript.destroy();
    458      SimpleTest.finish();
    459    });
    460    gScript.sendAsyncMessage("teardown");
    461  }
    462 
    463  // test main body
    464  async function runTests() {
    465    try {
    466      await testCannotMakePaymentShow();
    467      await testRejectShow();
    468      await testShowNormalFlow();
    469      await testCompleteSuccess();
    470      await testCompleteFail();
    471      await testCompleteUnknown();
    472      await testCompleteEmpty();
    473      await testUpdateWithReject();
    474      await testUpdateWithValidDetails();
    475      await testUpdateWithInvalidDetails();
    476      await testUpdateWithError();
    477      await testShowWithValidPromise();
    478      await testShowWithInvalidPromise();
    479      await testShowWithRejectedPromise();
    480      await testShowWithErrorPromise();
    481      await testShowWithPromiseResolvedByRejectedPromise();
    482      await testShowResponseInit();
    483      await testShowNotTriggeredByUser();
    484      await teardown();
    485    } catch (error) {
    486      ok(false, `test_showPayment: Unexpected error: ${error.name}`);
    487      SimpleTest.finish();
    488    }
    489  }
    490 
    491  window.addEventListener('load', function() {
    492    SpecialPowers.pushPrefEnv({
    493      'set': [
    494        ['dom.payments.request.enabled', true],
    495      ]
    496    }, runTests);
    497  });
    498 
    499  </script>
    500 </head>
    501 <body>
    502 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1345366">Mozilla Bug 1345366</a>
    503 </body>
    504 </html>