From 019190e91cff53d78f48c6c70e2ea8da23846a94 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Thu, 21 May 2020 11:55:06 -0700 Subject: Add remaining unit tests for browser --- .../browser/src/helpers/supportsWebauthn.test.ts | 15 +++ packages/browser/src/index.test.ts | 13 +++ .../browser/src/methods/startAssertion.test.ts | 111 +++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 packages/browser/src/helpers/supportsWebauthn.test.ts create mode 100644 packages/browser/src/index.test.ts create mode 100644 packages/browser/src/methods/startAssertion.test.ts (limited to 'packages/browser/src') diff --git a/packages/browser/src/helpers/supportsWebauthn.test.ts b/packages/browser/src/helpers/supportsWebauthn.test.ts new file mode 100644 index 0000000..078c27d --- /dev/null +++ b/packages/browser/src/helpers/supportsWebauthn.test.ts @@ -0,0 +1,15 @@ +import supportsWebauthn from './supportsWebauthn'; + +beforeEach(() => { + // @ts-ignore 2741 + window.PublicKeyCredential = jest.fn().mockReturnValue(() => {}); +}); + +test('should return true when browser supports WebAuthn', () => { + expect(supportsWebauthn()).toBe(true); +}); + +test('should return false when browser does not support WebAuthn', () => { + delete window.PublicKeyCredential; + expect(supportsWebauthn()).toBe(false); +}); diff --git a/packages/browser/src/index.test.ts b/packages/browser/src/index.test.ts new file mode 100644 index 0000000..0d132ba --- /dev/null +++ b/packages/browser/src/index.test.ts @@ -0,0 +1,13 @@ +import * as index from './index'; + +test('should export method `startAttestation`', () => { + expect(index.startAttestation).toBeDefined(); +}); + +test('should export method `startAssertion`', () => { + expect(index.startAssertion).toBeDefined(); +}); + +test('should export method `supportsWebauthn`', () => { + expect(index.supportsWebauthn).toBeDefined(); +}); diff --git a/packages/browser/src/methods/startAssertion.test.ts b/packages/browser/src/methods/startAssertion.test.ts new file mode 100644 index 0000000..b069f60 --- /dev/null +++ b/packages/browser/src/methods/startAssertion.test.ts @@ -0,0 +1,111 @@ +import base64js from 'base64-js'; + +import { AssertionCredential, PublicKeyCredentialRequestOptionsJSON } from '@webauthntine/typescript-types'; + +import toUint8Array from '../helpers/toUint8Array'; +import supportsWebauthn from '../helpers/supportsWebauthn'; + +import startAssertion from './startAssertion'; + +jest.mock('../helpers/supportsWebauthn'); + +const mockNavigatorGet = (window.navigator.credentials.get as jest.Mock); +const mockSupportsWebauthn = (supportsWebauthn as jest.Mock); + +const mockAttestationObject = 'mockAsse'; +const mockClientDataJSON = 'mockClie'; +const mockSignature = 'mockSign'; +const mockUserHandle = 'mockUser'; + +const goodOpts1: PublicKeyCredentialRequestOptionsJSON = { + publicKey: { + challenge: 'fizz', + allowCredentials: [{ + id: 'credId', + type: 'public-key', + transports: ['nfc'], + }], + timeout: 1, + }, +}; + +beforeEach(() => { + mockNavigatorGet.mockReset(); + mockSupportsWebauthn.mockReset(); +}); + +test('should convert options before passing to navigator.credentials.get(...)', async (done) => { + mockSupportsWebauthn.mockReturnValue(true); + + // Stub out a response so the method won't throw + mockNavigatorGet.mockImplementation((): Promise => { + return new Promise((resolve) => { + resolve({ response: {} }); + }); + }); + + await startAssertion(goodOpts1); + + const argsPublicKey = mockNavigatorGet.mock.calls[0][0].publicKey; + + expect(argsPublicKey.challenge).toEqual(toUint8Array(goodOpts1.publicKey.challenge)); + expect(argsPublicKey.allowCredentials[0].id).toEqual( + toUint8Array(goodOpts1.publicKey.allowCredentials[0].id), + ); + + done(); +}); + +test('should return base64-encoded response values', async (done) => { + mockSupportsWebauthn.mockReturnValue(true); + + mockNavigatorGet.mockImplementation((): Promise => { + return new Promise((resolve) => { + resolve({ + id: 'foobar', + rawId: toUint8Array('foobar'), + response: { + clientDataJSON: base64js.toByteArray(mockClientDataJSON), + authenticatorData: base64js.toByteArray(mockClientDataJSON), + signature: base64js.toByteArray(mockSignature), + userHandle: base64js.toByteArray(mockUserHandle), + }, + getClientExtensionResults: () => ({}), + type: 'webauthn.get', + }); + }); + }); + + const response = await startAssertion(goodOpts1); + + expect(response).toEqual({ + base64AuthenticatorData: mockClientDataJSON, + base64ClientDataJSON: mockClientDataJSON, + base64Signature: mockSignature, + base64UserHandle: mockUserHandle, + }); + + done(); +}) + +test('should throw error if WebAuthn isn\'t supported', async (done) => { + mockSupportsWebauthn.mockReturnValue(false); + + await expect(startAssertion(goodOpts1)).rejects.toThrow('WebAuthn is not supported in this browser'); + + done(); +}); + +test('should throw error if assertion is cancelled for some reason', async (done) => { + mockSupportsWebauthn.mockReturnValue(true); + + mockNavigatorGet.mockImplementation((): Promise => { + return new Promise((resolve) => { + resolve(null); + }); + }); + + await expect(startAssertion(goodOpts1)).rejects.toThrow('Assertion was not completed'); + + done(); +}); -- cgit v1.2.3