show-method-optional-promise-resolves-manual.https.html (9237B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>Test for PaymentRequest.show(optional promise) method</title> 4 <link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script> 8 "use strict"; 9 setup({ 10 allow_uncaught_exception: true, 11 explicit_done: true, 12 explicit_timeout: true, 13 }); 14 15 // DATA USED BY TESTS 16 // PaymentMethods 17 const validMethods = Object.freeze([ 18 { 19 supportedMethods: "valid-but-wont-ever-match", 20 }, 21 { 22 supportedMethods: "basic-card", 23 }, 24 { 25 supportedMethods: "https://apple.com/apple-pay", 26 data: { 27 version: 3, 28 merchantIdentifier: "merchant.com.example", 29 countryCode: "US", 30 merchantCapabilities: ["supports3DS"], 31 supportedNetworks: ["visa"], 32 } 33 }, 34 ]); 35 36 // Amounts 37 const failAmount = Object.freeze({ 38 currency: "USD", 39 value: "1.00", 40 }); 41 const passAmount = Object.freeze({ 42 currency: "CAD", 43 value: "50.00", 44 }); 45 const neutralAmount = Object.freeze({ 46 currency: "AUD", 47 value: "0.00", 48 }); 49 50 // Labels 51 const failLabel = "💥 TEST HAS FAILED 💥"; 52 const passLabel = "✅ TEST HAS PASSED ✅"; 53 const neutralLabel = "Ignore this label"; 54 // Totals 55 const failTotal = Object.freeze({ 56 label: failLabel, 57 amount: failAmount, 58 }); 59 const passTotal = Object.freeze({ 60 label: passLabel, 61 amount: passAmount, 62 }); 63 const neutralTotal = Object.freeze({ 64 label: neutralLabel, 65 amount: passAmount, 66 }); 67 68 // PaymentItem 69 const failPaymentItem = Object.freeze({ 70 amount: failAmount, 71 label: failLabel, 72 }); 73 const failPaymentItems = Object.freeze([failPaymentItem]); 74 75 const passPaymentItem = Object.freeze({ 76 amount: passAmount, 77 label: passLabel, 78 }); 79 const passPaymentItems = Object.freeze([passPaymentItem]); 80 81 // PaymentShippingOptions 82 const failShippingOption = Object.freeze({ 83 id: "fail", 84 label: failLabel, 85 amount: failAmount, 86 }); 87 const failShippingOptions = Object.freeze([failShippingOption]); 88 89 const neutralShippingOption = Object.freeze({ 90 id: "neutral", 91 label: neutralLabel, 92 amount: neutralAmount, 93 }); 94 95 const updatedShippingOption1 = Object.freeze({ 96 id: "updated-1", 97 label: `${passLabel} - option 1`, 98 amount: passAmount, 99 }); 100 const updatedShippingOption2 = Object.freeze({ 101 id: "updated-2", 102 label: `${passLabel} - option 2 (MUST BE SELECTED!)`, 103 amount: passAmount, 104 selected: true, 105 }); 106 const passShippingOptions = Object.freeze([ 107 updatedShippingOption1, 108 updatedShippingOption2, 109 ]); 110 111 // Modifiers 112 // create a modifier objects for each validMethods 113 // and single additional display item 114 const failModifiers = validMethods.map(modifier => { 115 const label = `${failLabel} - (${modifier.supportedMethods})`; 116 return { 117 ...modifier, 118 total: { 119 ...failTotal, 120 label, 121 }, 122 additionalDisplayItems: [ 123 { 124 ...failPaymentItem, 125 label, 126 }, 127 ], 128 }; 129 }); 130 // Updates the total for each, and changes the additionalDisplayItems 131 const passModifiers = failModifiers.map(modifier => { 132 const label = `${passLabel} - (${modifier.supportedMethods})`; 133 return { 134 ...modifier, 135 total: { 136 ...passTotal, 137 label, 138 }, 139 additionalDisplayItems: [ 140 { 141 ...passPaymentItem, 142 label, 143 }, 144 ], 145 }; 146 }); 147 148 // PaymentDetailsInit 149 const failDetails = Object.freeze({ 150 displayItems: failPaymentItems, 151 id: "this cannot be changed", 152 modifiers: failModifiers, 153 shippingOptions: failShippingOptions, 154 total: failTotal, 155 }); 156 157 const neutralDetails = Object.freeze({ 158 displayItems: [], 159 modifiers: [], 160 shippingOptions: [neutralShippingOption], 161 total: neutralTotal, 162 }); 163 164 function smokeTest() { 165 promise_test(async t => { 166 const request = new PaymentRequest(validMethods, failDetails); 167 await promise_rejects_js( 168 t, 169 TypeError, 170 request.show({ 171 total: "This throws a TypeError", 172 }), 173 "expected TypeError" 174 ); 175 }, "smoke test - checks if the optional details are supported on show() method"); 176 } 177 178 function runUpdateDetailsAlgorithm( 179 buttonElement, 180 details, 181 options = { 182 requestShipping: true, 183 }, 184 initialDetails = failDetails, 185 ) { 186 const testAssertion = buttonElement.textContent.trim(); 187 buttonElement.disabled = true; 188 promise_test(async t => { 189 const request = new PaymentRequest(validMethods, initialDetails, options); 190 const detailsPromise = Promise.resolve(details); 191 const acceptPromise = request.show(detailsPromise); 192 assert_equals(request.id, "this cannot be changed", "id must never change."); 193 await promise_rejects_dom( 194 t, 195 "AbortError", 196 acceptPromise, 197 "expected AbortError" 198 ); 199 }, testAssertion); 200 } 201 </script> 202 <h2> 203 PaymentRequest <code>.show(optional detailsPromise)</code> tests 204 </h2> 205 <p> 206 These test cause <code>detailsPromise</code> to resolve successfully with some updated value. As such, that will cause 207 something in the payment sheet to change. Each test describes what is expected to change - if anything. 208 </p> 209 <p> 210 <strong>Instructions:</strong> Click on each button in sequence from top to bottom without refreshing the page. The payment 211 sheet will be shown. If required, confirm that the expected value appears in the payment sheet. Finally, manually abort/cancel 212 the payment request by closing the payment sheet. 213 </p> 214 <ol> 215 <li><button onclick="smokeTest()">If the payment sheet is shown, the test has failed.</button></li> 216 <li><button onclick=" 217 const details = { 218 ...neutralDetails, 219 id: 'fail', 220 }; 221 runUpdateDetailsAlgorithm(this, details); 222 "> 223 When the payment sheet is shown, the provided `id` must have no effect on the payment request. 224 </button></li> 225 <li><button onclick=" 226 const details = { 227 ...neutralDetails, 228 total: passTotal 229 }; 230 runUpdateDetailsAlgorithm(this, details); 231 "> 232 When the payment sheet is shown, the total must be CAD$50 with the label "✅ TEST HAS PASSED ✅". 233 </button></li> 234 <li><button onclick=" 235 const details = { 236 ...neutralDetails, 237 displayItems: passPaymentItems, 238 }; 239 runUpdateDetailsAlgorithm(this, details); 240 "> 241 When the payment sheet is shown, there must be a one display item with a value of CAD$50 with the label "✅ TEST HAS PASSED ✅". 242 </button> 243 </li> 244 <li><button onclick=" 245 const auItem = { 246 ...passPaymentItem, 247 amount: { value: '40', currency: 'AUD'}, 248 pending: true 249 } 250 const details = { 251 ...neutralDetails, 252 displayItems: passPaymentItems.concat(auItem), 253 }; 254 runUpdateDetailsAlgorithm(this, details); 255 "> 256 When the payment sheet is shown, there must be 257 two display items: One with a value of CAD$50, another with 258 value AUD$40 that is pending. 259 </button> 260 </li> 261 <li><button onclick=" 262 const details = { 263 ...neutralDetails, 264 shippingOptions: [updatedShippingOption1], 265 }; 266 runUpdateDetailsAlgorithm(this, details); 267 "> 268 When the payment sheet is shown, there must be a one shipping option 269 with a value of CAD$50. 270 </button> 271 </li> 272 <li><button onclick=" 273 const details = { 274 ...neutralDetails, 275 shippingOptions: passShippingOptions, 276 }; 277 runUpdateDetailsAlgorithm(this, details); 278 "> 279 When the payment sheet is shown, there must be 280 two shipping options: One with a value of CAD$50, another with 281 value AUD$40 that is selected. 282 </button> 283 </li> 284 <li><button onclick=" 285 const details = { 286 ...neutralDetails, 287 modifiers: passModifiers, 288 }; 289 runUpdateDetailsAlgorithm(this, details); 290 "> 291 When the payment sheet is shown, the total should be CAD$50. 292 </button> 293 </li> 294 <li> 295 <button onclick=" 296 const details = { 297 ...neutralDetails, 298 shippingOptions: [], 299 error: passLabel, 300 }; 301 runUpdateDetailsAlgorithm(this, details); 302 "> 303 When the payment sheet is shown, the string "✅ TEST HAS PASSED ✅" should be shown 304 somewhere in the user interface. Alternatively, the payment sheet must indicate to the 305 end user that it's not possible to ship their order. 306 </button> 307 </li> 308 <li> 309 <button onclick=" 310 const details = { 311 ...neutralDetails, 312 error: failLabel, 313 }; 314 runUpdateDetailsAlgorithm(this, details, {requestShipping: false}); 315 "> 316 When the payment sheet is shown, there should not be any errors shown. 317 </button> 318 </li> 319 <li> 320 <button onclick=" 321 const initialDetails = {total: passTotal, id: 'this cannot be changed'}; 322 const updatedDetails = {}; 323 runUpdateDetailsAlgorithm( 324 this, updatedDetails, {requestShipping: false}, initialDetails); 325 "> 326 Resolving the show promise with empty details will preserve the details from 327 the constructor. When the payment sheet is shown, the string 328 "✅ TEST HAS PASSED ✅" should be shown. 329 </button> 330 </li> 331 <li> 332 <button onclick="done();">Done!</button> 333 </li> 334 </ol> 335 336 <small> 337 If you find a buggy test, please <a href="https://github.com/web-platform-tests/wpt/issues">file a bug</a> 338 and tag one of the <a href="https://github.com/web-platform-tests/wpt/blob/master/payment-request/META.yml">suggested reviewers</a>. 339 </small>