payment-is-showing.https.html (5565B)
1 <!DOCTYPE html> <meta charset="utf-8" /> 2 <title>Test for PaymentRequest.show(optional promise) method</title> 3 <link 4 rel="help" 5 href="https://w3c.github.io/browser-payment-api/#dfn-payment-request-is-showing" 6 /> 7 <meta name="timeout" content="long" /> 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 <body> 13 <script> 14 "use strict"; 15 const applePayMethod = { 16 supportedMethods: "https://apple.com/apple-pay", 17 data: { 18 version: 3, 19 merchantIdentifier: "merchant.com.example", 20 countryCode: "US", 21 merchantCapabilities: ["supports3DS"], 22 supportedNetworks: ["visa"], 23 }, 24 }; 25 const methods = [{ supportedMethods: "basic-card" }, applePayMethod]; 26 const details = { 27 total: { 28 label: "Total", 29 amount: { 30 currency: "USD", 31 value: "1.00", 32 }, 33 }, 34 }; 35 36 /** 37 * Attaches an iframe to window.document. 38 * 39 * @param {String} src Optional resource URL to load. 40 * @returns {Promise} Resolves when the src loads. 41 */ 42 async function attachIframe(src = "./resources/blank.html") { 43 const iframe = document.createElement("iframe"); 44 iframe.allow = "payment"; 45 iframe.src = src; 46 document.body.appendChild(iframe); 47 await new Promise((resolve) => { 48 iframe.addEventListener("load", resolve, { once: true }); 49 }); 50 return iframe; 51 } 52 53 function getShowPromiseFromContext(paymentRequest, context = this) { 54 return test_driver.bless( 55 "payment request show()", 56 () => { 57 return [paymentRequest.show()]; 58 }, 59 context 60 ); 61 } 62 63 promise_test(async (t) => { 64 const request1 = new PaymentRequest(methods, details); 65 const request2 = new PaymentRequest(methods, details); 66 67 // Sets the "payment-relevant browsing context's payment request is 68 // showing boolean" to true and then try to show a second payment sheet in 69 // the same window. The second show() should reject. 70 await test_driver.bless("payment request show()"); 71 const showPromise1 = request1.show(); 72 73 await test_driver.bless("payment request show()"); 74 const showPromise2 = request2.show(); 75 76 await promise_rejects_dom( 77 t, 78 "AbortError", 79 showPromise2, 80 "Attempting to show a second payment request must reject." 81 ); 82 83 await request1.abort(); 84 await promise_rejects_dom( 85 t, 86 "AbortError", 87 showPromise1, 88 "request1 was aborted via .abort()" 89 ); 90 91 // Finally, request2 should have been "closed", so trying to show 92 // it will again result in promise rejected with an InvalidStateError. 93 // See: https://github.com/w3c/payment-request/pull/821 94 const rejectedPromise = request2.show(); 95 await promise_rejects_dom( 96 t, 97 "InvalidStateError", 98 rejectedPromise, 99 "Attempting to show a second payment request must reject." 100 ); 101 // Finally, we confirm that request2's returned promises are unique. 102 assert_not_equals( 103 showPromise2, 104 rejectedPromise, 105 "Returned Promises be unique" 106 ); 107 }, "The top browsing context can only show one payment sheet at a time."); 108 109 promise_test(async (t) => { 110 const iframe = await attachIframe(); 111 const iframeWindow = iframe.contentWindow; 112 113 // Payment requests 114 const windowRequest = new window.PaymentRequest(methods, details); 115 const iframeRequest = new iframeWindow.PaymentRequest(methods, details); 116 117 // Let's get some blessed showPromises 118 // iframe sets "is showing boolean", ignore the returned promise. 119 const [iframePromise] = await getShowPromiseFromContext( 120 iframeRequest, 121 iframeWindow 122 ); 123 124 // The top level window now tries to show() the payment request. 125 await test_driver.bless("payment request show()"); 126 const showPromise = windowRequest.show(); 127 128 await promise_rejects_dom( 129 t, 130 "AbortError", 131 showPromise, 132 "iframe is already showing a payment request." 133 ); 134 135 // Cleanup 136 await iframeRequest.abort(); 137 iframe.remove(); 138 }, "If an iframe shows a payment request, the top-level browsing context can't also show one."); 139 140 promise_test(async (t) => { 141 const iframe = await attachIframe(); 142 const iframeWindow = iframe.contentWindow; 143 const iframeRequest = new iframeWindow.PaymentRequest(methods, details); 144 const [iframeShowPromise] = await getShowPromiseFromContext( 145 iframeRequest, 146 iframeWindow 147 ); 148 149 // We navigate away, causing the payment sheet to close 150 // and the request is showing boolean to become false. 151 await new Promise((resolve) => { 152 iframe.onload = resolve; 153 iframe.src = "./resources/blank.html?test=123"; 154 }); 155 156 iframe.remove(); 157 158 // Now we should be ok to spin up a new payment request 159 const request = new window.PaymentRequest(methods, details); 160 const [showPromise] = await getShowPromiseFromContext(request); 161 await request.abort(); 162 await promise_rejects_dom( 163 t, 164 "AbortError", 165 showPromise, 166 "Normal abort." 167 ); 168 }, "Navigating an iframe as a nested browsing context sets 'payment request is showing boolean' to false."); 169 </script> 170 </body>