get.tentative.https.html (8466B)
1 <!DOCTYPE html> 2 <title>Digital Credential tests.</title> 3 <link rel="help" href="https://wicg.github.io/digital-credentials/" /> 4 <script src="/common/get-host-info.sub.js"></script> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/resources/testdriver.js"></script> 8 <script src="/resources/testdriver-vendor.js"></script> 9 10 <body> 11 <iframe id="cross-origin" allow="digital-credentials-get"></iframe> 12 <iframe id="same-origin"></iframe> 13 </body> 14 <script type="module"> 15 import { makeGetOptions, sendMessage, loadIframe } from "./support/helper.js"; 16 17 const iframeSameOrigin = document.querySelector("iframe#same-origin"); 18 const iframeCrossOrigin = document.querySelector("iframe#cross-origin"); 19 20 promise_setup(async () => { 21 const hostInfo = get_host_info(); 22 await Promise.all([ 23 loadIframe( 24 iframeCrossOrigin, 25 `${hostInfo.HTTPS_REMOTE_ORIGIN}/digital-credentials/support/iframe.html` 26 ), 27 loadIframe(iframeSameOrigin, "/digital-credentials/support/iframe.html"), 28 ]); 29 }); 30 31 promise_test(async (t) => { 32 const invalidData = [null, "", 123, true, false]; 33 for (const data of invalidData) { 34 const options = makeGetOptions({ data }); 35 await test_driver.bless("user activation"); 36 await promise_rejects_js( 37 t, 38 TypeError, 39 navigator.credentials.get(options) 40 ); 41 } 42 }, "Type conversion happens on the data member of the DigitalCredentialGetRequest object."); 43 44 promise_test(async (t) => { 45 iframeSameOrigin.focus(); 46 for (const global of [window, iframeSameOrigin.contentWindow]) { 47 await promise_rejects_dom( 48 t, 49 "NotSupportedError", 50 global.DOMException, 51 global.navigator.credentials.get() 52 ); 53 54 await promise_rejects_dom( 55 t, 56 "NotSupportedError", 57 global.DOMException, 58 global.navigator.credentials.get({}) 59 ); 60 61 await promise_rejects_dom( 62 t, 63 "NotSupportedError", 64 global.DOMException, 65 global.navigator.credentials.get({ x: "y" }) 66 ); 67 68 await promise_rejects_dom( 69 t, 70 "NotSupportedError", 71 global.DOMException, 72 global.navigator.credentials.get({ x: "y", y: "z" }) 73 ); 74 75 await promise_rejects_dom( 76 t, 77 "NotSupportedError", 78 global.DOMException, 79 global.navigator.credentials.get({ mediation: "required" }) 80 ); 81 82 const abortController = new AbortController(); 83 const { signal } = abortController; 84 85 await promise_rejects_dom( 86 t, 87 "NotSupportedError", 88 global.DOMException, 89 global.navigator.credentials.get({ signal }) 90 ); 91 92 await promise_rejects_dom( 93 t, 94 "NotSupportedError", 95 global.DOMException, 96 global.navigator.credentials.get({ signal, mediation: "required" }) 97 ); 98 } 99 }, "Calling navigator.credentials.get() without a digital member same origin."); 100 101 promise_test(async (t) => { 102 for (const r of [undefined, []]) { 103 const options = { 104 digital: { 105 requests: r 106 }, 107 }; 108 await test_driver.bless("user activation"); 109 await promise_rejects_js( 110 t, 111 TypeError, 112 navigator.credentials.get(options) 113 ); 114 } 115 }, "navigator.credentials.get() API rejects if there are no credential request."); 116 117 promise_test(async (t) => { 118 iframeSameOrigin.focus(); 119 const { contentWindow: iframeWindow } = iframeSameOrigin; 120 for (const r of [undefined, []]) { 121 const options = { 122 digital: { 123 requests: r 124 }, 125 }; 126 await test_driver.bless("user activation"); 127 await promise_rejects_js( 128 t, 129 iframeWindow.TypeError, 130 iframeWindow.navigator.credentials.get(options) 131 ); 132 } 133 }, "navigator.credentials.get() API rejects if there are no credential request for same-origin iframe."); 134 135 promise_test(async (t) => { 136 iframeCrossOrigin.focus(); 137 for (const r of [undefined, []]) { 138 const options = { 139 digital: { 140 requests: r 141 }, 142 }; 143 const result = await sendMessage(iframeCrossOrigin, { 144 action: "get", 145 options, 146 }); 147 assert_equals(result.constructor, "TypeError"); 148 } 149 }, "navigator.credentials.get() API rejects if there are no credential request in cross-origin iframe."); 150 151 promise_test(async (t) => { 152 const abortController = new AbortController(); 153 const { signal } = abortController; 154 abortController.abort(); 155 for (const options of [{ signal }, makeGetOptions({protocol: [], signal})]) { 156 await promise_rejects_dom( 157 t, 158 "AbortError", 159 navigator.credentials.get(options) 160 ); 161 } 162 }, "navigator.credentials.get() promise is rejected if called with an aborted controller."); 163 164 promise_test(async (t) => { 165 iframeSameOrigin.focus(); 166 const { contentWindow: iframeWindow } = iframeSameOrigin; 167 const abortController = new iframeWindow.AbortController(); 168 const { signal } = abortController; 169 abortController.abort(); 170 for (const options of [{ signal }, makeGetOptions({protocol: [], signal})]) { 171 await test_driver.bless("user activation"); 172 await promise_rejects_dom( 173 t, 174 "AbortError", 175 iframeWindow.DOMException, 176 iframeWindow.navigator.credentials.get(options) 177 ); 178 assert_true( 179 navigator.userActivation.isActive, 180 "User activation is still active." 181 ); 182 } 183 }, "navigator.credentials.get() promise is rejected if called with an aborted controller in same-origin iframe."); 184 185 promise_test(async (t) => { 186 iframeCrossOrigin.focus(); 187 for (const options of [undefined, {}, makeGetOptions({protocol: []})]) { 188 const result = await sendMessage(iframeCrossOrigin, { 189 abort: "before", 190 action: "get", 191 options, 192 }); 193 assert_equals(result.constructor, "DOMException"); 194 assert_equals(result.name, "AbortError"); 195 } 196 }, "navigator.credentials.get() promise is rejected if called with an aborted signal in cross-origin iframe."); 197 198 promise_test(async (t) => { 199 const abortController = new AbortController(); 200 const { signal } = abortController; 201 const options = makeGetOptions({signal}); 202 await test_driver.bless("user activation"); 203 const promise = promise_rejects_dom( 204 t, 205 "AbortError", 206 DOMException, 207 navigator.credentials.get(options) 208 ); 209 abortController.abort(); 210 await promise; 211 }, "navigator.credentials.get() promise is rejected if abort controller is aborted after call to get()."); 212 213 promise_test(async (t) => { 214 iframeCrossOrigin.focus(); 215 const result = await sendMessage(iframeCrossOrigin, { 216 abort: "after", 217 action: "get", 218 needsActivation: true, 219 options: makeGetOptions(), 220 }); 221 assert_equals(result.constructor, "DOMException"); 222 assert_equals(result.name, "AbortError"); 223 }, "navigator.credentials.get() promise is rejected if abort controller is aborted after call to get() in cross-origin iframe."); 224 225 promise_test(async (t) => { 226 for (const mediation of ["silent", "optional", "conditional", "required"]) { 227 const abortController = new AbortController(); 228 const { signal } = abortController; 229 await test_driver.bless("user activation"); 230 const requestPromise = navigator.credentials.get(makeGetOptions({ 231 mediation, 232 signal, 233 })); 234 abortController.abort(new Error(`Aborted for testing mediation "${mediation}"`)); 235 await promise_rejects_js(t, Error, requestPromise); 236 } 237 }, "Mediation is implicitly required and hence ignored. Request is aborted regardless."); 238 239 promise_test(async t => { 240 const throwingValues = [ 241 BigInt(123), 242 (() => { const o = {}; o.self = o; return o; })(), 243 Symbol("foo") 244 ]; 245 246 for (const badValue of throwingValues) { 247 const options = makeGetOptions({ data: badValue }); 248 249 await promise_rejects_js( 250 t, 251 TypeError, 252 navigator.credentials.get(options), 253 `Should throw for: ${String(badValue)}` 254 ); 255 } 256 }, "Throws TypeError when request data is not JSON stringifiable."); 257 258 promise_test(async (t) => { 259 await promise_rejects_js( 260 t, 261 TypeError, 262 navigator.credentials.get({digital: {}})); 263 }, "`requests` field is required in the options object."); 264 </script>