1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
<!DOCTYPE html> <meta charset="utf-8" />
<title>Test for PaymentRequest.show(optional promise) method</title>
<link
rel="help"
href="https://w3c.github.io/browser-payment-api/#dfn-payment-request-is-showing"
/>
<meta name="timeout" content="long" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<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 = "./resources/blank.html") {
const iframe = document.createElement("iframe");
iframe.allow = "payment";
iframe.src = src;
document.body.appendChild(iframe);
await new Promise((resolve) => {
iframe.addEventListener("load", resolve, { once: true });
});
return iframe;
}
function getShowPromiseFromContext(paymentRequest, context = this) {
return test_driver.bless(
"payment request show()",
() => {
return [paymentRequest.show()];
},
context
);
}
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.
await test_driver.bless("payment request show()");
const showPromise1 = request1.show();
await test_driver.bless("payment request show()");
const showPromise2 = request2.show();
await promise_rejects_dom(
t,
"AbortError",
showPromise2,
"Attempting to show a second payment request must reject."
);
await request1.abort();
await promise_rejects_dom(
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 = request2.show();
await promise_rejects_dom(
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 windowRequest = new window.PaymentRequest(methods, details);
const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
// Let's get some blessed showPromises
// iframe sets "is showing boolean", ignore the returned promise.
const [iframePromise] = await getShowPromiseFromContext(
iframeRequest,
iframeWindow
);
// The top level window now tries to show() the payment request.
await test_driver.bless("payment request show()");
const showPromise = windowRequest.show();
await promise_rejects_dom(
t,
"AbortError",
showPromise,
"iframe is already showing a payment request."
);
// Cleanup
await iframeRequest.abort();
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;
const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
const [iframeShowPromise] = await getShowPromiseFromContext(
iframeRequest,
iframeWindow
);
// We navigate away, causing the payment sheet to close
// and the request is showing boolean to become false.
await new Promise((resolve) => {
iframe.onload = resolve;
iframe.src = "./resources/blank.html?test=123";
});
iframe.remove();
// Now we should be ok to spin up a new payment request
const request = new window.PaymentRequest(methods, details);
const [showPromise] = await getShowPromiseFromContext(request);
await request.abort();
await promise_rejects_dom(
t,
"AbortError",
showPromise,
"Normal abort."
);
}, "Navigating an iframe as a nested browsing context sets 'payment request is showing boolean' to false.");
</script>
</body>
|