diff options
Diffstat (limited to 'packages/browser/src')
-rw-r--r-- | packages/browser/src/helpers/__mocks__/supportsWebauthn.ts | 2 | ||||
-rw-r--r-- | packages/browser/src/methods/startAttestation.test.ts | 112 | ||||
-rw-r--r-- | packages/browser/src/setupTests.ts | 12 |
3 files changed, 126 insertions, 0 deletions
diff --git a/packages/browser/src/helpers/__mocks__/supportsWebauthn.ts b/packages/browser/src/helpers/__mocks__/supportsWebauthn.ts new file mode 100644 index 0000000..b6b47d4 --- /dev/null +++ b/packages/browser/src/helpers/__mocks__/supportsWebauthn.ts @@ -0,0 +1,2 @@ +// We just need a simple mock so we can control whether this returns `true` or `false` +export default jest.fn(); diff --git a/packages/browser/src/methods/startAttestation.test.ts b/packages/browser/src/methods/startAttestation.test.ts new file mode 100644 index 0000000..0efec48 --- /dev/null +++ b/packages/browser/src/methods/startAttestation.test.ts @@ -0,0 +1,112 @@ +import base64js from 'base64-js'; + +import { AttestationCredential, PublicKeyCredentialCreationOptionsJSON } from '@webauthntine/typescript-types'; + +import toUint8Array from '../helpers/toUint8Array'; +import supportsWebauthn from '../helpers/supportsWebauthn'; + +import startAttestation from './startAttestation'; + +jest.mock('../helpers/supportsWebauthn'); + +const mockNavigatorCreate = (window.navigator.credentials.create as jest.Mock); +const mockSupportsWebauthn = (supportsWebauthn as jest.Mock); + +const mockAttestationObject = 'mockAtte'; +const mockClientDataJSON = 'mockClie'; + +const goodOpts1: PublicKeyCredentialCreationOptionsJSON = { + publicKey: { + challenge: 'fizz', + attestation: 'direct', + pubKeyCredParams: [{ + alg: -7, + type: "public-key", + }], + rp: { + id: '1234', + name: 'webauthntine', + }, + user: { + id: '5678', + displayName: 'username', + name: 'username', + }, + timeout: 1, + }, +}; + +beforeEach(() => { + mockNavigatorCreate.mockReset(); + mockSupportsWebauthn.mockReset(); +}); + +test('should convert options before passing to navigator.credentials.create(...)', async (done) => { + mockSupportsWebauthn.mockReturnValue(true); + + // Stub out a response so the method won't throw + mockNavigatorCreate.mockImplementation((): Promise<any> => { + return new Promise((resolve) => { + resolve({ response: {} }); + }); + }); + + await startAttestation(goodOpts1); + + const argsPublicKey = mockNavigatorCreate.mock.calls[0][0].publicKey; + + expect(argsPublicKey.challenge).toEqual(toUint8Array(goodOpts1.publicKey.challenge)); + expect(argsPublicKey.user.id).toEqual(toUint8Array(goodOpts1.publicKey.user.id)); + + done(); +}); + +test('should return base64-encoded response values', async (done) => { + mockSupportsWebauthn.mockReturnValue(true); + + mockNavigatorCreate.mockImplementation((): Promise<AttestationCredential> => { + return new Promise((resolve) => { + resolve({ + id: 'foobar', + rawId: toUint8Array('foobar'), + response: { + attestationObject: base64js.toByteArray(mockAttestationObject), + clientDataJSON: base64js.toByteArray(mockClientDataJSON), + }, + getClientExtensionResults: () => ({}), + type: 'webauthn.create', + }); + }); + }); + + const response = await startAttestation(goodOpts1); + + expect(response).toEqual({ + base64AttestationObject: mockAttestationObject, + base64ClientDataJSON: mockClientDataJSON, + }); + + done(); +}) + +test('should throw error if WebAuthn isn\'t supported', async (done) => { + mockSupportsWebauthn.mockReturnValue(false); + + await expect(startAttestation(goodOpts1)).rejects.toThrow('WebAuthn is not supported in this browser'); + + done(); +}); + +test('should throw error if attestation is cancelled for some reason', async (done) => { + mockSupportsWebauthn.mockReturnValue(true); + + mockNavigatorCreate.mockImplementation((): Promise<null> => { + return new Promise((resolve) => { + resolve(null); + }); + }); + + await expect(startAttestation(goodOpts1)).rejects.toThrow('Attestation was not completed'); + + done(); +}); diff --git a/packages/browser/src/setupTests.ts b/packages/browser/src/setupTests.ts index 4cf23af..dcb981e 100644 --- a/packages/browser/src/setupTests.ts +++ b/packages/browser/src/setupTests.ts @@ -1,3 +1,15 @@ // Silence some console output jest.spyOn(console, 'log').mockImplementation(); jest.spyOn(console, 'debug').mockImplementation(); + +/** + * JSDom doesn't seem to support `credentials`, so let's define them here so we can mock their + * implementations in specific tests. + */ +// @ts-ignore 2540 +window.navigator.credentials = { + // attestation + create: jest.fn(), + // assertion + get: jest.fn(), +}; |