diff options
Diffstat (limited to 'packages/browser/src')
-rw-r--r-- | packages/browser/src/helpers/__jest__/generateCustomError.ts | 17 | ||||
-rw-r--r-- | packages/browser/src/methods/startAuthentication.test.ts | 21 | ||||
-rw-r--r-- | packages/browser/src/methods/startRegistration.test.ts | 34 | ||||
-rw-r--r-- | packages/browser/src/setupTests.ts | 61 |
4 files changed, 56 insertions, 77 deletions
diff --git a/packages/browser/src/helpers/__jest__/generateCustomError.ts b/packages/browser/src/helpers/__jest__/generateCustomError.ts new file mode 100644 index 0000000..f4b3250 --- /dev/null +++ b/packages/browser/src/helpers/__jest__/generateCustomError.ts @@ -0,0 +1,17 @@ +/** + * Create "custom errors" to help emulate WebAuthn API errors +*/ +type WebAuthnErrorName = + 'AbortError' + | 'ConstraintError' + | 'InvalidStateError' + | 'NotAllowedError' + | 'NotSupportedError' + | 'SecurityError' + | 'UnknownError'; + +export function generateCustomError(name: WebAuthnErrorName): Error { + const customError = new Error(); + customError.name = name; + return customError; +} diff --git a/packages/browser/src/methods/startAuthentication.test.ts b/packages/browser/src/methods/startAuthentication.test.ts index 4be0ad6..848e9db 100644 --- a/packages/browser/src/methods/startAuthentication.test.ts +++ b/packages/browser/src/methods/startAuthentication.test.ts @@ -9,6 +9,7 @@ import { browserSupportsWebauthn } from '../helpers/browserSupportsWebauthn'; import utf8StringToBuffer from '../helpers/utf8StringToBuffer'; import bufferToBase64URLString from '../helpers/bufferToBase64URLString'; import { WebAuthnError } from '../helpers/structs'; +import { generateCustomError } from '../helpers/__jest__/generateCustomError'; import startAuthentication from './startAuthentication'; @@ -203,6 +204,8 @@ test('should include extension results when no extensions specified', async () = describe('WebAuthnError', () => { describe('AbortError', () => { + const AbortError = generateCustomError('AbortError'); + /** * We can't actually test this because nothing in startAuthentication() propagates the abort * signal. But if you invoked WebAuthn via this and then manually sent an abort signal I guess @@ -211,7 +214,7 @@ describe('WebAuthnError', () => { * As a matter of fact I couldn't actually get any browser to respect the abort signal... */ test.skip('should identify abort signal', async () => { - mockNavigatorGet.mockRejectedValueOnce(new AbortError()); + mockNavigatorGet.mockRejectedValueOnce(AbortError); const rejected = await expect(startAuthentication(goodOpts1)).rejects; rejected.toThrow(WebAuthnError); @@ -221,8 +224,10 @@ describe('WebAuthnError', () => { }); describe('NotAllowedError', () => { + const NotAllowedError = generateCustomError('NotAllowedError'); + test('should identify unrecognized allowed credentials', async () => { - mockNavigatorGet.mockRejectedValueOnce(new NotAllowedError()); + mockNavigatorGet.mockRejectedValueOnce(NotAllowedError); const rejected = await expect(startAuthentication(goodOpts1)).rejects; rejected.toThrow(WebAuthnError); @@ -231,7 +236,7 @@ describe('WebAuthnError', () => { }); test('should identify cancellation or timeout', async () => { - mockNavigatorGet.mockRejectedValueOnce(new NotAllowedError()); + mockNavigatorGet.mockRejectedValueOnce(NotAllowedError); const opts = { ...goodOpts1, @@ -247,6 +252,8 @@ describe('WebAuthnError', () => { }); describe('SecurityError', () => { + const SecurityError = generateCustomError('SecurityError'); + let _originalHostName: string; beforeEach(() => { @@ -260,7 +267,7 @@ describe('WebAuthnError', () => { test('should identify invalid domain', async () => { window.location.hostname = '1.2.3.4'; - mockNavigatorGet.mockRejectedValueOnce(new SecurityError()); + mockNavigatorGet.mockRejectedValueOnce(SecurityError); const rejected = await expect(startAuthentication(goodOpts1)).rejects; rejected.toThrowError(WebAuthnError); @@ -272,7 +279,7 @@ describe('WebAuthnError', () => { test('should identify invalid RP ID', async () => { window.location.hostname = 'simplewebauthn.com'; - mockNavigatorGet.mockRejectedValueOnce(new SecurityError()); + mockNavigatorGet.mockRejectedValueOnce(SecurityError); const rejected = await expect(startAuthentication(goodOpts1)).rejects; rejected.toThrowError(WebAuthnError); @@ -283,8 +290,10 @@ describe('WebAuthnError', () => { }); describe('UnknownError', () => { + const UnknownError = generateCustomError('UnknownError'); + test('should identify potential authenticator issues', async () => { - mockNavigatorGet.mockRejectedValueOnce(new UnknownError()); + mockNavigatorGet.mockRejectedValueOnce(UnknownError); const rejected = await expect(startAuthentication(goodOpts1)).rejects; rejected.toThrow(WebAuthnError); diff --git a/packages/browser/src/methods/startRegistration.test.ts b/packages/browser/src/methods/startRegistration.test.ts index 78b0157..8322642 100644 --- a/packages/browser/src/methods/startRegistration.test.ts +++ b/packages/browser/src/methods/startRegistration.test.ts @@ -9,6 +9,7 @@ import utf8StringToBuffer from '../helpers/utf8StringToBuffer'; import { browserSupportsWebauthn } from '../helpers/browserSupportsWebauthn'; import bufferToBase64URLString from '../helpers/bufferToBase64URLString'; import { WebAuthnError } from '../helpers/structs'; +import { generateCustomError } from '../helpers/__jest__/generateCustomError'; import startRegistration from './startRegistration'; @@ -177,6 +178,7 @@ test('should include extension results when no extensions specified', async () = describe('WebAuthnError', () => { describe('AbortError', () => { + const AbortError = generateCustomError('AbortError'); /** * We can't actually test this because nothing in startRegistration() propagates the abort * signal. But if you invoked WebAuthn via this and then manually sent an abort signal I guess @@ -185,7 +187,7 @@ describe('WebAuthnError', () => { * As a matter of fact I couldn't actually get any browser to respect the abort signal... */ test.skip('should identify abort signal', async () => { - mockNavigatorCreate.mockRejectedValueOnce(new AbortError()); + mockNavigatorCreate.mockRejectedValueOnce(AbortError); const rejected = await expect(startRegistration(goodOpts1)).rejects; rejected.toThrow(WebAuthnError); @@ -195,8 +197,10 @@ describe('WebAuthnError', () => { }); describe('ConstraintError', () => { + const ConstraintError = generateCustomError('ConstraintError'); + test('should identify unsupported discoverable credentials', async () => { - mockNavigatorCreate.mockRejectedValueOnce(new ConstraintError()); + mockNavigatorCreate.mockRejectedValueOnce(ConstraintError); const opts: PublicKeyCredentialCreationOptionsJSON = { ...goodOpts1, @@ -214,7 +218,7 @@ describe('WebAuthnError', () => { }); test('should identify unsupported user verification', async () => { - mockNavigatorCreate.mockRejectedValueOnce(new ConstraintError()); + mockNavigatorCreate.mockRejectedValueOnce(ConstraintError); const opts: PublicKeyCredentialCreationOptionsJSON = { ...goodOpts1, @@ -232,8 +236,10 @@ describe('WebAuthnError', () => { }); describe('InvalidStateError', () => { + const InvalidStateError = generateCustomError('InvalidStateError'); + test('should identify re-registration attempt', async () => { - mockNavigatorCreate.mockRejectedValueOnce(new InvalidStateError()); + mockNavigatorCreate.mockRejectedValueOnce(InvalidStateError); const rejected = await expect(startRegistration(goodOpts1)).rejects; rejected.toThrow(WebAuthnError); @@ -244,8 +250,10 @@ describe('WebAuthnError', () => { }); describe('NotAllowedError', () => { + const NotAllowedError = generateCustomError('NotAllowedError'); + test('should identify cancellation or timeout', async () => { - mockNavigatorCreate.mockRejectedValueOnce(new NotAllowedError()); + mockNavigatorCreate.mockRejectedValueOnce(NotAllowedError); const rejected = await expect(startRegistration(goodOpts1)).rejects; rejected.toThrow(WebAuthnError); @@ -256,8 +264,10 @@ describe('WebAuthnError', () => { }); describe('NotSupportedError', () => { + const NotSupportedError = generateCustomError('NotSupportedError'); + test('should identify missing "public-key" entries in pubKeyCredParams', async () => { - mockNavigatorCreate.mockRejectedValueOnce(new NotSupportedError()); + mockNavigatorCreate.mockRejectedValueOnce(NotSupportedError); const opts = { ...goodOpts1, @@ -272,7 +282,7 @@ describe('WebAuthnError', () => { }); test('should identify no authenticator supports algs in pubKeyCredParams', async () => { - mockNavigatorCreate.mockRejectedValueOnce(new NotSupportedError()); + mockNavigatorCreate.mockRejectedValueOnce(NotSupportedError); const opts: PublicKeyCredentialCreationOptionsJSON = { ...goodOpts1, @@ -288,6 +298,8 @@ describe('WebAuthnError', () => { }); describe('SecurityError', () => { + const SecurityError = generateCustomError('SecurityError'); + let _originalHostName: string; beforeEach(() => { @@ -301,7 +313,7 @@ describe('WebAuthnError', () => { test('should identify invalid domain', async () => { window.location.hostname = '1.2.3.4'; - mockNavigatorCreate.mockRejectedValueOnce(new SecurityError()); + mockNavigatorCreate.mockRejectedValueOnce(SecurityError); const rejected = await expect(startRegistration(goodOpts1)).rejects; rejected.toThrowError(WebAuthnError); @@ -313,7 +325,7 @@ describe('WebAuthnError', () => { test('should identify invalid RP ID', async () => { window.location.hostname = 'simplewebauthn.com'; - mockNavigatorCreate.mockRejectedValueOnce(new SecurityError()); + mockNavigatorCreate.mockRejectedValueOnce(SecurityError); const rejected = await expect(startRegistration(goodOpts1)).rejects; rejected.toThrowError(WebAuthnError); @@ -344,8 +356,10 @@ describe('WebAuthnError', () => { }); describe('UnknownError', () => { + const UnknownError = generateCustomError('UnknownError'); + test('should identify potential authenticator issues', async () => { - mockNavigatorCreate.mockRejectedValueOnce(new UnknownError()); + mockNavigatorCreate.mockRejectedValueOnce(UnknownError); const rejected = await expect(startRegistration(goodOpts1)).rejects; rejected.toThrow(WebAuthnError); diff --git a/packages/browser/src/setupTests.ts b/packages/browser/src/setupTests.ts index fda8840..5b6efcf 100644 --- a/packages/browser/src/setupTests.ts +++ b/packages/browser/src/setupTests.ts @@ -24,64 +24,3 @@ Object.defineProperty(window, 'location', { hostname: '', }, }); - -/** - * Define WebAuthn's custom API errors - */ - -class AbortError extends Error { - constructor() { - super(); - this.name = 'AbortError'; - } -} - -class ConstraintError extends Error { - constructor() { - super(); - this.name = 'ConstraintError'; - } -} - -class InvalidStateError extends Error { - constructor() { - super(); - this.name = 'InvalidStateError'; - } -} - -class NotAllowedError extends Error { - constructor() { - super(); - this.name = 'NotAllowedError'; - } -} - -class NotSupportedError extends Error { - constructor() { - super(); - this.name = 'NotSupportedError'; - } -} - -class SecurityError extends Error { - constructor() { - super(); - this.name = 'SecurityError'; - } -} - -class UnknownError extends Error { - constructor() { - super(); - this.name = 'UnknownError'; - } -} - -Object.defineProperty(global, 'AbortError', { value: AbortError }); -Object.defineProperty(global, 'ConstraintError', { value: ConstraintError }); -Object.defineProperty(global, 'InvalidStateError', { value: InvalidStateError }); -Object.defineProperty(global, 'NotAllowedError', { value: NotAllowedError }); -Object.defineProperty(global, 'NotSupportedError', { value: NotSupportedError }); -Object.defineProperty(global, 'SecurityError', { value: SecurityError }); -Object.defineProperty(global, 'UnknownError', { value: UnknownError }); |