show-method-optional-promise-rejects.https.html (6728B)
1 <!DOCTYPE html> 2 <meta charset="utf-8" /> 3 <title>Test for PaymentRequest.show(optional detailsPromise) method</title> 4 <link 5 rel="help" 6 href="https://w3c.github.io/browser-payment-api/#show-method" 7 /> 8 <script src="/resources/testharness.js"></script> 9 <script src="/resources/testharnessreport.js"></script> 10 <script src="/resources/testdriver.js"></script> 11 <script src="/resources/testdriver-vendor.js"></script> 12 <script> 13 // See function testBadUpdate() for test details! 14 setup({ 15 allow_uncaught_exception: true, 16 }); 17 18 // == TEST DATA === 19 // PaymentMethod 20 const validMethod = Object.freeze({ 21 supportedMethods: "valid-but-wont-ever-match", 22 }); 23 24 const validMethodBasicCard = Object.freeze({ 25 supportedMethods: "basic-card", 26 }); 27 28 const validMethodApplePay = Object.freeze({ 29 supportedMethods: "https://apple.com/apple-pay", 30 data: { 31 version: 3, 32 merchantIdentifier: "merchant.com.example", 33 countryCode: "US", 34 merchantCapabilities: ["supports3DS"], 35 supportedNetworks: ["visa"], 36 }, 37 }); 38 39 // Methods 40 const validMethods = Object.freeze([ 41 validMethodBasicCard, 42 validMethod, 43 validMethodApplePay, 44 ]); 45 46 // Amounts 47 const validAmount = Object.freeze({ 48 currency: "USD", 49 value: "1.00", 50 }); 51 52 const invalidAmount = Object.freeze({ 53 currency: "¡INVALID!", 54 value: "A1.0", 55 }); 56 57 const negativeAmount = Object.freeze({ 58 currency: "USD", 59 value: "-1.00", 60 }); 61 62 // Totals 63 const validTotal = Object.freeze({ 64 label: "Valid Total", 65 amount: validAmount, 66 }); 67 68 const invalidTotal = Object.freeze({ 69 label: "Invalid Total", 70 amount: invalidAmount, 71 }); 72 73 const invalidNegativeTotal = Object.freeze({ 74 label: "Invalid negative total", 75 amount: negativeAmount, 76 }); 77 78 // PaymentDetailsInit 79 const validDetails = Object.freeze({ 80 total: validTotal, 81 }); 82 83 const invalidDetailsNegativeTotal = Object.freeze({ 84 total: invalidNegativeTotal, 85 }); 86 87 // PaymentOptions 88 const validOptions = Object.freeze({ 89 requestShipping: true, 90 }); 91 92 // PaymentItem 93 const validPaymentItem = Object.freeze({ 94 amount: validAmount, 95 label: "Valid payment item", 96 }); 97 98 const invalidPaymentItem = Object.freeze({ 99 amount: invalidAmount, 100 label: "Invalid payment item", 101 }); 102 103 // PaymentItem 104 const validPaymentItems = Object.freeze([validPaymentItem]); 105 const invalidPaymentItems = Object.freeze([invalidPaymentItem]); 106 107 // PaymentShippingOption 108 const invalidShippingOption = Object.freeze({ 109 id: "abc", 110 label: "Invalid shipping option", 111 amount: invalidAmount, 112 selected: true, 113 }); 114 115 // PaymentShippingOptions 116 const validShippingOption = Object.freeze({ 117 id: "abc", 118 label: "valid shipping option", 119 amount: validAmount, 120 }); 121 122 const validShippingOptions = Object.freeze([validShippingOption]); 123 const invalidShippingOptions = Object.freeze([invalidShippingOption]); 124 125 // PaymentDetailsModifier 126 const validModifier = Object.freeze({ 127 additionalDisplayItems: validPaymentItems, 128 supportedMethods: "valid-but-wont-ever-match", 129 total: validTotal, 130 }); 131 132 const modifierWithInvalidDisplayItems = Object.freeze({ 133 additionalDisplayItems: invalidPaymentItems, 134 supportedMethods: "basic-card", 135 total: validTotal, 136 }); 137 138 const modifierWithValidDisplayItems = Object.freeze({ 139 additionalDisplayItems: validPaymentItems, 140 supportedMethods: "basic-card", 141 total: validTotal, 142 }); 143 144 const modifierWithInvalidTotal = Object.freeze({ 145 additionalDisplayItems: validPaymentItems, 146 supportedMethods: "basic-card", 147 total: invalidTotal, 148 }); 149 150 const recursiveData = {}; 151 recursiveData.foo = recursiveData; 152 Object.freeze(recursiveData); 153 154 const modifierWithRecursiveData = Object.freeze({ 155 supportedMethods: "basic-card", 156 total: validTotal, 157 data: recursiveData, 158 }); 159 // == END OF TEST DATA === 160 /* 161 These test work by creating a "valid" payment request and then 162 performing a bad update via `show(detailsPromise)`. 163 The `badDetails` cause detailsPromise to reject with `expectedError`. 164 */ 165 function testBadUpdate(testAssertion, badDetails, expectedError) { 166 promise_test(async (t) => { 167 const request = new PaymentRequest( 168 validMethods, 169 validDetails, 170 validOptions 171 ); 172 await test_driver.bless("Payment request"); 173 const detailsPromise = Promise.resolve(badDetails); 174 const acceptPromise = request.show(detailsPromise); 175 const test_func = 176 typeof expectedError == "function" 177 ? promise_rejects_js 178 : promise_rejects_dom; 179 await test_func( 180 t, 181 expectedError, 182 acceptPromise, 183 "badDetails must cause acceptPromise to reject with expectedError" 184 ); 185 }, testAssertion); 186 } 187 188 const rejectedPromise = Promise.reject(new SyntaxError("test")); 189 testBadUpdate( 190 "Rejection of detailsPromise must abort the update with an 'AbortError' DOMException.", 191 rejectedPromise, 192 "AbortError" 193 ); 194 195 testBadUpdate( 196 "Total in the update is a string, so converting to IDL must abort the update with a TypeError.", 197 { total: `this will cause a TypeError!` }, 198 TypeError 199 ); 200 201 testBadUpdate( 202 "Total is recursive, so converting to IDL must abort the update with a TypeError.", 203 { total: recursiveData }, 204 TypeError 205 ); 206 207 testBadUpdate( 208 "Updating with a negative total results in a TypeError.", 209 invalidDetailsNegativeTotal, 210 TypeError 211 ); 212 213 testBadUpdate( 214 "Updating with a displayItem with an invalid currency results in RangeError.", 215 { ...validDetails, displayItems: invalidPaymentItems }, 216 RangeError 217 ); 218 219 testBadUpdate( 220 "Updating with duplicate shippingOptions (same IDs) results in a TypeError.", 221 { 222 ...validDetails, 223 shippingOptions: [validShippingOption, validShippingOption], 224 }, 225 TypeError 226 ); 227 228 testBadUpdate( 229 "Updating with a shippingOption with an invalid currency value results in a RangError.", 230 { ...validDetails, shippingOptions: invalidShippingOptions }, 231 RangeError 232 ); 233 234 testBadUpdate( 235 "Must throw a RangeError when a modifier's total item has an invalid currency.", 236 { ...validDetails, modifiers: [modifierWithInvalidTotal, validModifier] }, 237 RangeError 238 ); 239 240 testBadUpdate( 241 "Must throw a RangeError when a modifier display item has an invalid currency.", 242 { 243 ...validDetails, 244 modifiers: [modifierWithInvalidDisplayItems, validModifier], 245 }, 246 RangeError 247 ); 248 testBadUpdate( 249 "Must throw as Modifier has a recursive dictionary.", 250 { ...validDetails, modifiers: [modifierWithRecursiveData, validModifier] }, 251 TypeError 252 ); 253 </script>