<!DOCTYPE html><!-- webkit-test-runner [ WebAuthenticationModernEnabled=true ] -->
<title>Web Authentication API: PublicKeyCredential's [[create]] success cases with a mock hid authenticator.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="./resources/util.js"></script>
<script src="./resources/cbor.js"></script>
<script>
    // Default mock configuration. Tests need to override if they need different configuration.
    if (window.internals)
        internals.setMockWebAuthenticationConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", payloadBase64: [testCreationMessageBase64] } });

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential, true, ["usb"]);
        });
    }, "PublicKeyCredential's [[create]] with minimum options in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: asciiToUint8Array("1"),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential, true, ["usb"]);
        });
    }, "PublicKeyCredential's [[create]] with user handle of length=1 in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: asciiToUint8Array("1234567812345678123456781234567812345678123456781234567812345678"),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential, true, ["usb"]);
        });
    }, "PublicKeyCredential's [[create]] with user handle of length=64 in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [],
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with empty pubKeyCredParams in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                authenticatorSelection: { authenticatorAttachment: "cross-platform" },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with authenticatorSelection { 'cross-platform' } in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                authenticatorSelection: { requireResidentKey: false },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with requireResidentKey { false } in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                authenticatorSelection: { residentKey: "discouraged" },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with residentKey { Discouraged } in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                authenticatorSelection: { residentKey: "preferred" },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with residentKey { Preferred } in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                authenticatorSelection: { residentKey: "required" },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with residentKey { Required } in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                authenticatorSelection: { userVerification: "preferred" },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with userVerification { 'preferred' } in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                authenticatorSelection: { userVerification: "discouraged" },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with userVerification { 'discouraged' } in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                authenticatorSelection: { authenticatorAttachment: "cross-platform", requireResidentKey: false, userVerification: "preferred" },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with mixed options in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                timeout: 100
            }
        };

        // Stall the first request to wait for cancellation.
        if (window.internals)
            internals.setMockWebAuthenticationConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", payloadBase64: [testCreationMessageBase64], expectCancel: true } });
        promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "This request has been cancelled by a new request.");
        if (window.internals)
            internals.setMockWebAuthenticationConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", payloadBase64: [testCreationMessageBase64] } });
        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with two consecutive requests.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                attestation: "none",
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with none attestation in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                attestation: "direct",
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential, false);
        });
    }, "PublicKeyCredential's [[create]] with direct attestation in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                attestation: "indirect",
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential, false);
        });
    }, "PublicKeyCredential's [[create]] with indirect attestation in a mock hid authenticator.");

    // When RP ID is not google.com, googleLegacyAppidSupport should not have any effects.
    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                extensions: { googleLegacyAppidSupport: true },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with googleLegacyAppidSupport extension in a mock hid authenticator.");

    promise_test(t => {
        const options = {
            publicKey: {
                rp: {
                    name: "localhost",
                },
                user: {
                    name: "John Appleseed",
                    id: Base64URL.parse(testUserhandleBase64),
                    displayName: "Appleseed",
                },
                challenge: Base64URL.parse("MTIzNDU2"),
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
                extensions: { googleLegacyAppidSupport: true, appid: "" },
                timeout: 100
            }
        };

        return navigator.credentials.create(options).then(credential => {
            checkCtapMakeCredentialResult(credential);
        });
    }, "PublicKeyCredential's [[create]] with googleLegacyAppidSupport and appid extensions in a mock hid authenticator.");
</script>
