Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<title>Digital Credential API tests for create.</title>
<link rel="help" href="https://wicg.github.io/digital-credentials/" />
<script src="/common/get-host-info.sub.js"></script>
<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>
<iframe id="same-origin"></iframe>
<iframe id="cross-origin"></iframe>
</body>
<script type="module">
import { makeCreateOptions, sendMessage, loadIframe } from "./support/helper.js";
const iframeSameOrigin = document.querySelector("iframe#same-origin");
const iframeCrossOrigin = document.querySelector("iframe#cross-origin");
const mediations = ["silent", "optional", "conditional", "required"];
promise_setup(async () => {
const hostInfo = get_host_info();
await Promise.all([
loadIframe(
iframeCrossOrigin,
`${hostInfo.HTTPS_REMOTE_ORIGIN}/digital-credentials/support/iframe.html`
),
loadIframe(iframeSameOrigin, "/digital-credentials/support/iframe.html"),
]);
});
promise_test(async (t) => {
iframeSameOrigin.focus();
for (const global of [window, iframeSameOrigin.contentWindow]) {
await promise_rejects_dom(
t,
"NotSupportedError",
global.DOMException,
global.navigator.credentials.create()
);
await promise_rejects_dom(
t,
"NotSupportedError",
global.DOMException,
global.navigator.credentials.create({})
);
await promise_rejects_dom(
t,
"NotSupportedError",
global.DOMException,
global.navigator.credentials.create({ x: "y" })
);
await promise_rejects_dom(
t,
"NotSupportedError",
global.DOMException,
global.navigator.credentials.create({ x: "y", y: "z" })
);
await promise_rejects_dom(
t,
"NotSupportedError",
global.DOMException,
global.navigator.credentials.create({ mediation: "required" })
);
const abortController = new AbortController();
const { signal } = abortController;
await promise_rejects_dom(
t,
"NotSupportedError",
global.DOMException,
global.navigator.credentials.create({ signal })
);
await promise_rejects_dom(
t,
"NotSupportedError",
global.DOMException,
global.navigator.credentials.create({ signal, mediation: "required" })
);
}
}, "Calling navigator.credentials.create() without a digital member same origin.");
promise_test(async (t) => {
for (const request of [undefined, []]) {
const options = makeCreateOptions(request);
await test_driver.bless("user activation");
await promise_rejects_js(t, TypeError, navigator.credentials.create(options));
}
}, "navigator.credentials.create() API rejects if there are no credential request.");
promise_test(async (t) => {
iframeSameOrigin.focus();
const { contentWindow: iframeWindow } = iframeSameOrigin;
for (const request of [undefined, []]) {
const options = makeCreateOptions(request);
await test_driver.bless("user activation");
await promise_rejects_js(
t,
iframeWindow.TypeError,
iframeWindow.navigator.credentials.create(options)
);
}
}, "navigator.credentials.create() API rejects if there are no credential request for same-origin iframe.");
promise_test(async (t) => {
iframeCrossOrigin.focus();
for (const request of [undefined, []]) {
const options = makeCreateOptions(request);
const result = await sendMessage(iframeCrossOrigin, {
action: "create",
options,
});
assert_equals(result.constructor, "TypeError");
}
}, "navigator.credentials.create() API rejects if there are no credential request in cross-origin iframe.");
promise_test(async (t) => {
const abortController = new AbortController();
const { signal } = abortController;
abortController.abort();
for (const options of [{ signal }, { signal, ...makeCreateOptions([]) }]) {
await promise_rejects_dom(
t,
"AbortError",
navigator.credentials.create(options)
);
}
}, "navigator.credentials.create() promise is rejected if called with an aborted controller.");
promise_test(async (t) => {
iframeSameOrigin.focus();
const { contentWindow: iframeWindow } = iframeSameOrigin;
const abortController = new iframeWindow.AbortController();
const { signal } = abortController;
abortController.abort();
for (const options of [{ signal }, { signal, ...makeCreateOptions([]) }]) {
await test_driver.bless("user activation");
await promise_rejects_dom(
t,
"AbortError",
iframeWindow.DOMException,
iframeWindow.navigator.credentials.create(options)
);
assert_true(
navigator.userActivation.isActive,
"User activation is still active."
);
}
}, "navigator.credentials.create() promise is rejected if called with an aborted controller in same-origin iframe.");
promise_test(async (t) => {
iframeCrossOrigin.focus();
for (const options of [undefined, {}, makeCreateOptions([])]) {
const result = await sendMessage(iframeCrossOrigin, {
abort: "before",
action: "create",
options,
});
assert_equals(result.constructor, "DOMException");
assert_equals(result.name, "AbortError");
}
}, "navigator.credentials.create() promise is rejected if called with an aborted signal in cross-origin iframe.");
promise_test(async (t) => {
const abortController = new AbortController();
const { signal } = abortController;
const options = makeCreateOptions("openid4vci");
options.signal = signal;
await test_driver.bless("user activation");
const promise = promise_rejects_dom(
t,
"AbortError",
DOMException,
navigator.credentials.create(options)
);
abortController.abort();
await promise;
}, "navigator.credentials.create() promise is rejected if abort controller is aborted after call to create().");
promise_test(async (t) => {
iframeCrossOrigin.focus();
const result = await sendMessage(iframeCrossOrigin, {
abort: "after",
action: "create",
needsActivation: true,
options: makeCreateOptions("openid4vci"),
});
assert_equals(result.constructor, "DOMException");
assert_equals(result.name, "AbortError");
}, "navigator.credentials.create() promise is rejected if abort controller is aborted after call to create() in cross-origin iframe.");
promise_test(async (t) => {
const abortController = new AbortController();
const { signal } = abortController;
abortController.abort();
for (const mediation of mediations) {
const requestPromise = navigator.credentials.create({
mediation,
signal,
});
await promise_rejects_dom(t, "AbortError", requestPromise);
}
}, "Adding mediations together with abort signal respects the abort signal.");
promise_test(async (t) => {
/** @type sequence<CredentialMediationRequirement> */
const disallowedMediations = [ "conditional", "optional", "silent"];
for (const mediation of disallowedMediations) {
const options = makeCreateOptions("default", mediation);
await promise_rejects_js(t, TypeError, navigator.credentials.create(options));
}
}, "Mediation is required to create a DigitalCredential.");
</script>