Added: trunk/LayoutTests/http/tests/paymentrequest/payment-is-showing.https.html (0 => 246863)
--- trunk/LayoutTests/http/tests/paymentrequest/payment-is-showing.https.html (rev 0)
+++ trunk/LayoutTests/http/tests/paymentrequest/payment-is-showing.https.html 2019-06-27 00:39:29 UTC (rev 246863)
@@ -0,0 +1,290 @@
+<!DOCTYPE html> <meta charset="utf-8" />
+<title>Test for PaymentRequest.show(optional promise) method</title>
+<link
+ rel="help"
+ href=""
+/>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<body>
+ <script>
+ 'use strict';
+ const applePayMethod = {
+ supportedMethods: 'https://apple.com/apple-pay',
+ data: {
+ version: 3,
+ merchantIdentifier: 'merchant.com.example',
+ countryCode: 'US',
+ merchantCapabilities: ['supports3DS'],
+ supportedNetworks: ['visa'],
+ },
+ };
+ const methods = [{supportedMethods: 'basic-card'}, applePayMethod];
+ const details = {
+ total: {
+ label: 'Total',
+ amount: {
+ currency: 'USD',
+ value: '1.00',
+ },
+ },
+ };
+
+ /**
+ * Attaches an iframe to window.document.
+ *
+ * @param {String} src Optional resource URL to load.
+ * @returns {Promise} Resolves when the src loads.
+ */
+ async function attachIframe(src = '') {
+ const iframe = document.createElement('iframe');
+ iframe.allowPaymentRequest = true;
+ iframe.src = ""
+ document.body.appendChild(iframe);
+ await new Promise(resolve => {
+ iframe.addEventListener('load', resolve, {once: true});
+ });
+ return iframe;
+ }
+
+ /**
+ * Creates a popup window. The caller must be triggered with a user gesture.
+ *
+ * @param {String} src Optional resource URL to load.
+ * @returns {Promise} Resolves when the src loads.
+ */
+ async function loadPopupInsideUserGesture(src = '') {
+ const popupWindow = window.open(src, '', 'width=400,height=400');
+ await new Promise(resolve => {
+ popupWindow.addEventListener('load', resolve, {once: true});
+ });
+ popupWindow.focus();
+ return popupWindow;
+ }
+
+ promise_test(async t => {
+ const request1 = new PaymentRequest(methods, details);
+ const request2 = new PaymentRequest(methods, details);
+
+ // Sets the "payment-relevant browsing context's payment request is
+ // showing boolean" to true and then try to show a second payment sheet in
+ // the same window. The second show() should reject.
+ const [showPromise1, showPromise2] = await activateThen(
+ async () => {
+ return [request1.show(), request2.show()];
+ }
+ );
+ await promise_rejects(
+ t,
+ 'AbortError',
+ showPromise2,
+ 'Attempting to show a second payment request must reject.',
+ );
+
+ await request1.abort();
+ await promise_rejects(
+ t,
+ 'AbortError',
+ showPromise1,
+ 'request1 was aborted via .abort()',
+ );
+
+ // Finally, request2 should have been "closed", so trying to show
+ // it will again result in promise rejected with an InvalidStateError.
+ // See: https://github.com/w3c/payment-request/pull/821
+ const [rejectedPromise] = await activateThen(async () => { return [request2.show()] });
+ await promise_rejects(
+ t,
+ 'InvalidStateError',
+ rejectedPromise,
+ 'Attempting to show a second payment request must reject.',
+ );
+ // Finally, we confirm that request2's returned promises are unique.
+ assert_not_equals(
+ showPromise2,
+ rejectedPromise,
+ 'Returned Promises be unique',
+ );
+ }, 'The top browsing context can only show one payment sheet at a time.');
+
+ promise_test(async t => {
+ const iframe = await attachIframe();
+ const iframeWindow = iframe.contentWindow;
+
+ // Payment requests
+ const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
+ const windowRequest = new window.PaymentRequest(methods, details);
+
+ // Let's get some blessed showPromises
+ const [iframeShowPromise, windowShowPromise] = await activateThen(
+ async () => {
+ // iframe sets "is showing boolean", ignore the returned promise.
+ // The top level window now tries to show() the payment request.
+ return [iframeRequest.show(), windowRequest.show()];
+ }
+ );
+
+ await promise_rejects(
+ t,
+ 'AbortError',
+ windowShowPromise,
+ 'iframe is already showing a payment request.',
+ );
+
+ // Cleanup
+ await iframeRequest.abort();
+ await promise_rejects(
+ t,
+ 'AbortError',
+ iframeShowPromise,
+ 'abort() was called');
+ iframe.remove();
+ }, "If an iframe shows a payment request, the top-level browsing context can't also show one.");
+
+ promise_test(async t => {
+ const iframe = await attachIframe();
+ const iframeWindow = iframe.contentWindow;
+
+ // Payment requests
+ const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
+ const windowRequest = new window.PaymentRequest(methods, details);
+
+ // We first show a payment request via the the top level browsing context,
+ // windowRequest.show() sets "is showing boolean" to true. Then we try to
+ // show a payment request in the iframe, which should reject.
+ const [windowShowPromise, iframeShowPromise] = await activateThen(
+ async () => {
+ return [windowRequest.show(), iframeRequest.show()];
+ }
+ );
+
+ await promise_rejects(
+ t,
+ 'AbortError',
+ iframeShowPromise,
+ 'The top window is already showing a payment request.',
+ );
+
+ // Cleanup
+ await windowRequest.abort();
+ await promise_rejects(
+ t,
+ 'AbortError',
+ windowShowPromise,
+ 'abort() was called');
+ iframe.remove();
+ }, 'An iframe cannot show a payment request if the top-level window is already showing one.');
+
+ promise_test(async t => {
+ const iframe = await attachIframe();
+ const iframeWindow = iframe.contentWindow;
+
+ // Create requests
+ const windowRequest = new window.PaymentRequest(methods, details);
+ const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
+
+ // Get the showPromise for each browsing context. Doing this in a separate
+ // test_driver.bless() is important because the user gesture brings
+ // |window| to the foreground, so that the payment sheet can show.
+ const [
+ windowShowPromise,
+ iframeShowPromise,
+ ] = await activateThen(
+ async () => {
+ return [
+ windowRequest.show(),
+ iframeRequest.show(),
+ ];
+ }
+ );
+
+ await promise_rejects(
+ t,
+ 'AbortError',
+ iframeShowPromise,
+ 'Expected iframeShowPromise to reject, request is already showing.',
+ );
+
+ await windowRequest.abort();
+ await promise_rejects(
+ t,
+ 'AbortError',
+ windowShowPromise,
+ 'abort() was called');
+ iframe.remove();
+ }, "Given multiple nested browsing contexts, and window calls show() first, other nested browsing contexts can't show a request.");
+
+ promise_test(async t => {
+ const iframe = await attachIframe();
+ const iframeWindow = iframe.contentWindow;
+
+ // Create requests
+ const windowRequest = new window.PaymentRequest(methods, details);
+ const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
+
+ // Get the showPromise for each browsing context. Doing this in a separate
+ // test_driver.bless() is important because the user gesture brings
+ // |window| to the foreground, so that the payment sheet can show.
+ const [
+ iframeShowPromise,
+ windowShowPromise,
+ ] = await activateThen(
+ async () => {
+ return [
+ iframeRequest.show(),
+ windowRequest.show(),
+ ];
+ }
+ );
+
+ // windowShowPromise and iframeRequest will both reject
+ await promise_rejects(
+ t,
+ 'AbortError',
+ windowShowPromise,
+ 'Expected windowShowPromise to reject, the popup is showing a payment request.',
+ );
+
+ await iframeRequest.abort();
+ await promise_rejects(
+ t,
+ 'AbortError',
+ iframeShowPromise,
+ 'abort() was called');
+ iframe.remove();
+ }, "Given multiple nested browsing contexts, and an iframe calls show() first, other nested browsing contexts can't show a request.");
+
+ promise_test(async t => {
+ const iframe = await attachIframe();
+ const iframeWindow = iframe.contentWindow;
+ const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
+ const [iframeShowPromise] = await activateThen(
+ async () => { return [iframeRequest.show()] }
+ );
+
+ // We navigate away, causing the payment sheet to close
+ // and the request is showing boolean to become false.
+ iframe.src = '';
+ await new Promise(resolve => (iframe._onload_ = resolve));
+ await promise_rejects(
+ t,
+ 'AbortError',
+ iframeShowPromise,
+ 'Navigating iframe away must cause the iframeShowPromise to reject.',
+ );
+ iframe.remove();
+
+ // Now we should be ok to spin up a new payment request
+ const request = new window.PaymentRequest(methods, details);
+ const [showPromise] = await activateThen(async () => { return [request.show()] });
+ await request.abort();
+ await promise_rejects(
+ t,
+ 'AbortError',
+ showPromise,
+ 'abort() was called');
+ }, "Navigating an iframe as a nested browsing context sets 'payment request is showing boolean' to false.");
+ </script>
+</body>