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>