| <!doctype html> |
| <meta charset="utf8"> |
| <link rel="help" href="https://w3c.github.io/payment-request/#dfn-abort-the-update"> |
| <title> |
| updateWith() method - "abort the update" |
| </title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script> |
| setup({ explicit_done: true, explicit_timeout: true }); |
| |
| // PaymentMethod |
| const validMethod = Object.freeze({ |
| supportedMethods: "valid-but-wont-ever-match", |
| }); |
| |
| const validMethodBasicCard = Object.freeze({ |
| supportedMethods: "basic-card", |
| }); |
| |
| // Methods |
| const validMethods = Object.freeze([validMethodBasicCard, validMethod]); |
| |
| // Amounts |
| const validAmount = Object.freeze({ |
| currency: "USD", |
| value: "1.00", |
| }); |
| |
| const invalidAmount = Object.freeze({ |
| currency: "¡INVALID!", |
| value: "A1.0", |
| }); |
| |
| const negativeAmount = Object.freeze({ |
| currency: "USD", |
| value: "-1.00", |
| }); |
| |
| // Totals |
| const validTotal = Object.freeze({ |
| label: "Valid Total", |
| amount: validAmount, |
| }); |
| |
| const invalidTotal = Object.freeze({ |
| label: "Invalid Total", |
| amount: invalidAmount, |
| }); |
| |
| const invalidNegativeTotal = Object.freeze({ |
| label: "Invalid negative total", |
| amount: negativeAmount, |
| }); |
| |
| // PaymentDetailsInit |
| const validDetails = Object.freeze({ |
| total: validTotal, |
| }); |
| |
| const invalidDetailsNegativeTotal = Object.freeze({ |
| total: invalidNegativeTotal, |
| }); |
| |
| // PaymentOptions |
| const validOptions = Object.freeze({ |
| requestShipping: true, |
| }); |
| |
| // PaymentItem |
| const validPaymentItem = Object.freeze({ |
| amount: validAmount, |
| label: "Valid payment item", |
| }); |
| |
| const invalidPaymentItem = Object.freeze({ |
| amount: invalidAmount, |
| label: "Invalid payment item", |
| }); |
| |
| // PaymentItem |
| const validPaymentItems = Object.freeze([validPaymentItem]); |
| const invalidPaymentItems = Object.freeze([invalidPaymentItem]); |
| |
| // PaymentShippingOption |
| const invalidShippingOption = Object.freeze({ |
| id: "abc", |
| label: "Invalid shipping option", |
| amount: invalidAmount, |
| selected: true, |
| }); |
| |
| // PaymentShippingOptions |
| const validShippingOption = Object.freeze({ |
| id: "abc", |
| label: "valid shipping option", |
| amount: validAmount, |
| }); |
| |
| const validShippingOptions = Object.freeze([validShippingOption]); |
| const invalidShippingOptions = Object.freeze([invalidShippingOption]); |
| |
| // PaymentDetailsModifier |
| const validModifier = Object.freeze({ |
| additionalDisplayItems: validPaymentItems, |
| supportedMethods: "valid-but-wont-ever-match", |
| total: validTotal, |
| }); |
| |
| const modifierWithInvalidDisplayItems = Object.freeze({ |
| additionalDisplayItems: invalidPaymentItems, |
| supportedMethods: "basic-card", |
| total: validTotal, |
| }); |
| |
| const modifierWithValidDisplayItems = Object.freeze({ |
| additionalDisplayItems: validPaymentItems, |
| supportedMethods: "basic-card", |
| total: validTotal, |
| }); |
| |
| const modifierWithInvalidTotal = Object.freeze({ |
| additionalDisplayItems: validPaymentItems, |
| supportedMethods: "basic-card", |
| total: invalidTotal, |
| }); |
| |
| const recursiveData = {}; |
| recursiveData.foo = recursiveData; |
| Object.freeze(recursiveData); |
| |
| const modifierWithRecursiveData = Object.freeze({ |
| supportedMethods: validMethodBasicCard, |
| total: validTotal, |
| data: recursiveData, |
| }); |
| |
| function testBadUpdate(button, badDetails, expectedError, errorCode) { |
| button.disabled = true; |
| promise_test(async t => { |
| const request = new PaymentRequest( |
| validMethods, |
| validDetails, |
| validOptions |
| ); |
| request.onshippingaddresschange = event => { |
| event.updateWith(badDetails); |
| }; |
| // First we check the bad update. |
| const acceptPromise = request.show(); |
| await promise_rejects( |
| t, |
| expectedError, |
| acceptPromise, |
| "badDetails must cause acceptPromise to reject with expectedError" |
| ); |
| // The request [[state]] is now "closed", so let's check for InvalidStateError |
| await promise_rejects( |
| t, |
| "InvalidStateError", |
| request.show(), |
| "show() must reject with InvalidStateError" |
| ); |
| }, button.innerText.trim()); |
| } |
| </script> |
| <h2>updateWith() method - "abort the update"</h2> |
| <p> |
| Click on each button in sequence from top to bottom without refreshing the page. |
| Each button will bring up the Payment Request UI window. |
| </p> |
| <p> |
| When the payment sheet is shown, change the shipping address. |
| </p> |
| <ol> |
| <li> |
| <button onclick=" |
| const rejectedPromise = Promise.reject(new SyntaxError('test')).catch(err => err); |
| testBadUpdate(this, rejectedPromise, 'AbortError'); |
| "> |
| Rejection of detailsPromise must abort the update with an "AbortError" DOMException. |
| </button> |
| </li> |
| <li> |
| <button onclick=" |
| const invalidDetails = { total: `this will cause a TypeError!` }; |
| testBadUpdate(this, invalidDetails, new TypeError()); |
| "> |
| Total in the update is a string, so converting to IDL must abort the update with a TypeError. |
| </button> |
| </li> |
| <li> |
| <button onclick=" |
| const invalidDetails = { total: recursiveData }; |
| testBadUpdate(this, invalidDetails, new TypeError()); |
| "> |
| Total is recursive, so converting to IDL must abort the update with a TypeError. |
| </button> |
| </li> |
| <li> |
| <button onclick=" |
| testBadUpdate(this, invalidDetailsNegativeTotal, new TypeError()); |
| "> |
| Updating with a negative total results in a TypeError. |
| </button> |
| </li> |
| <li> |
| <button onclick=" |
| const badDetails = Object.assign({}, validDetails, { displayItems: invalidPaymentItems }); |
| testBadUpdate(this, badDetails, new RangeError()); |
| "> |
| Updating with a displayItem with an invalid currency results in TypeError. |
| </button> |
| </li> |
| <li> |
| <button onclick=" |
| const duplicateShippingOptions = [validShippingOption, validShippingOption]; |
| const badDetails = Object.assign({}, validDetails, { shippingOptions: duplicateShippingOptions }); |
| testBadUpdate(this, badDetails, new TypeError()); |
| "> |
| Updating with duplicate shippingOptions (same IDs) results in a TypeError. |
| </button> |
| </li> |
| <li> |
| <button onclick=" |
| const badDetails = Object.assign({}, validDetails, { shippingOptions: invalidShippingOptions }); |
| testBadUpdate(this, badDetails, new RangeError()); |
| "> |
| Updating with a shippingOption with an invalid currency value results in a RangError. |
| </button> |
| </li> |
| <li> |
| <button onclick=" |
| // validModifier is there as to avoid false positives - it should just get ignored |
| const badModifiers = { modifiers: [ modifierWithInvalidTotal, validModifier ] }; |
| const badDetails = Object.assign({}, validDetails, badModifiers); |
| testBadUpdate(this, badDetails, new RangeError()); |
| "> |
| Must throw a RangeError when a modifier's total item has an invalid currency. |
| </button> |
| </li> |
| <li> |
| <button onclick=" |
| // validModifier is there as to avoid false positives - it should just get ignored |
| const badModifiers = { modifiers: [ modifierWithInvalidDisplayItems, validModifier ] }; |
| const badDetails = Object.assign({}, validDetails, badModifiers); |
| testBadUpdate(this, badDetails, new RangeError()); |
| "> |
| Must throw a RangeError when a modifier display item has an invalid currency. |
| </button> |
| </li> |
| <li> |
| <button onclick=" |
| // validModifier is there as to avoid false positives - it should just get ignored |
| const badModifiers = { modifiers: [ modifierWithRecursiveData, validModifier ] }; |
| const badDetails = Object.assign({}, validDetails, badModifiers); |
| testBadUpdate(this, badDetails, new TypeError()); |
| "> |
| Must throw as Modifier has a recursive dictionary. |
| </button> |
| </li> |
| <li> |
| <button onclick="done();">Done!</button> |
| </li> |
| </ol> |
| <small> |
| If you find a buggy test, please <a href="https://github.com/web-platform-tests/wpt/issues">file a bug</a> |
| and tag one of the <a href="https://github.com/web-platform-tests/wpt/blob/master/payment-request/META.yml">suggested reviewers</a>. |
| </small> |