summaryrefslogtreecommitdiffhomepage
path: root/packages/browser/src/methods/startAuthentication.test.ts
diff options
context:
space:
mode:
authorMatthew Miller <matthew@millerti.me>2022-06-20 12:44:39 -0700
committerMatthew Miller <matthew@millerti.me>2022-06-20 12:44:39 -0700
commitaa5b2e8f97e8948dff05c6444bf2262dcb43cbcf (patch)
tree57ed6c31279b850ce9cf2cca556cee26a79e86c6 /packages/browser/src/methods/startAuthentication.test.ts
parent803f96ca81fa113a23aa8243dfa438f2f778daa9 (diff)
Add tests for conditional UI support
Diffstat (limited to 'packages/browser/src/methods/startAuthentication.test.ts')
-rw-r--r--packages/browser/src/methods/startAuthentication.test.ts56
1 files changed, 56 insertions, 0 deletions
diff --git a/packages/browser/src/methods/startAuthentication.test.ts b/packages/browser/src/methods/startAuthentication.test.ts
index 89a0938..6f1b87b 100644
--- a/packages/browser/src/methods/startAuthentication.test.ts
+++ b/packages/browser/src/methods/startAuthentication.test.ts
@@ -6,6 +6,7 @@ import {
} from '@simplewebauthn/typescript-types';
import { browserSupportsWebauthn } from '../helpers/browserSupportsWebauthn';
+import { browserSupportsWebAuthnAutofill } from '../helpers/browserSupportsWebAuthnAutofill';
import utf8StringToBuffer from '../helpers/utf8StringToBuffer';
import bufferToBase64URLString from '../helpers/bufferToBase64URLString';
import { WebAuthnError } from '../helpers/structs';
@@ -15,9 +16,11 @@ import { webauthnAbortService } from '../helpers/webAuthnAbortService';
import { startAuthentication } from './startAuthentication';
jest.mock('../helpers/browserSupportsWebauthn');
+jest.mock('../helpers/browserSupportsWebAuthnAutofill');
const mockNavigatorGet = window.navigator.credentials.get as jest.Mock;
const mockSupportsWebauthn = browserSupportsWebauthn as jest.Mock;
+const mockSupportsAutofill = browserSupportsWebAuthnAutofill as jest.Mock;
const mockAuthenticatorData = 'mockAuthenticatorData';
const mockClientDataJSON = 'mockClientDataJSON';
@@ -56,11 +59,13 @@ beforeEach(() => {
});
mockSupportsWebauthn.mockReturnValue(true);
+ mockSupportsAutofill.mockResolvedValue(true);
});
afterEach(() => {
mockNavigatorGet.mockReset();
mockSupportsWebauthn.mockReset();
+ mockSupportsAutofill.mockReset();
});
test('should convert options before passing to navigator.credentials.get(...)', async () => {
@@ -231,6 +236,57 @@ test('should cancel an existing call when executed again', async () => {
expect(abortSpy).toHaveBeenCalledTimes(1);
});
+test('should set up autofill a.k.a. Conditional UI', async () => {
+ const opts: PublicKeyCredentialRequestOptionsJSON = {
+ ...goodOpts1,
+ allowCredentials: [
+ {
+ ...goodOpts1.allowCredentials![0],
+ transports: ["cable"],
+ },
+ ]
+ };
+ document.body.innerHTML = `
+ <form>
+ <label for="username">Username</label>
+ <input type="text" name="username" autocomplete="username webauthn" />
+ <button type="submit">Submit</button>
+ </form>
+ `;
+
+ await startAuthentication(opts, true);
+
+ // The most important bit
+ expect(mockNavigatorGet.mock.calls[0][0].mediation).toEqual('conditional');
+ // The latest version of https://github.com/w3c/webauthn/pull/1576 says allowCredentials should
+ // be an "empty list", as opposed to being undefined
+ expect(mockNavigatorGet.mock.calls[0][0].publicKey.allowCredentials).toBeDefined();
+ expect(mockNavigatorGet.mock.calls[0][0].publicKey.allowCredentials.length).toEqual(0);
+});
+
+test('should throw error if autofill not supported', async () => {
+ mockSupportsAutofill.mockResolvedValue(false);
+
+ const rejected = await expect(startAuthentication(goodOpts1, true)).rejects;
+ rejected.toThrow(Error);
+ rejected.toThrow(/does not support webauthn autofill/i);
+});
+
+test('should throw error if no acceptable <input> is found', async () => {
+ // <input> is missing "webauthn" from the autocomplete attribute
+ document.body.innerHTML = `
+ <form>
+ <label for="username">Username</label>
+ <input type="text" name="username" autocomplete="username" />
+ <button type="submit">Submit</button>
+ </form>
+ `;
+
+ const rejected = await expect(startAuthentication(goodOpts1, true)).rejects;
+ rejected.toThrow(Error);
+ rejected.toThrow(/no <input>/i);
+});
+
describe('WebAuthnError', () => {
describe('AbortError', () => {
const AbortError = generateCustomError('AbortError');