test: add coverage on helper function

This commit is contained in:
Nicolas Meienberger 2023-04-12 20:40:42 +02:00 committed by Nicolas Meienberger
parent 69386778a7
commit 3c108e8d44
5 changed files with 188 additions and 1 deletions

View file

@ -0,0 +1,81 @@
import { renderHook } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { useDisclosure } from '../useDisclosure';
describe('useDisclosure', () => {
test('should set isOpen to false by default', () => {
// arrange
const { result } = renderHook(() => useDisclosure());
// assert
expect(result.current.isOpen).toBe(false);
});
test('should set isOpen to true when calling open', () => {
// arrange
const { result } = renderHook(() => useDisclosure());
// act
act(() => {
result.current.open();
});
// assert
expect(result.current.isOpen).toBe(true);
});
test('should set isOpen to false when calling close', () => {
// arrangarrange
const { result } = renderHook(() => useDisclosure(true));
// act
act(() => {
result.current.close();
});
// assert
expect(result.current.isOpen).toBe(false);
});
test('should set isOpen to the opposite of the current value when calling toggle', () => {
// arrange
const { result } = renderHook(() => useDisclosure(false));
// act
act(() => {
result.current.toggle();
});
// assert
expect(result.current.isOpen).toBe(true);
// act
act(() => {
result.current.toggle();
});
// assert
expect(result.current.isOpen).toBe(false);
});
test('should set isOpen to the passed value when calling toggle with a boolean argument', () => {
// arrange
const { result } = renderHook(() => useDisclosure(false));
// act
act(() => {
result.current.toggle(true);
});
// assert
expect(result.current.isOpen).toBe(true);
// act
act(() => {
result.current.toggle(false);
});
// assert
expect(result.current.isOpen).toBe(false);
});
});

View file

@ -5,7 +5,7 @@ export const useDisclosure = (isOpenDefault = false) => {
const open = useCallback(() => setIsOpen(true), []);
const close = useCallback(() => setIsOpen(false), []);
const toggle = useCallback((toSet: boolean) => {
const toggle = useCallback((toSet?: boolean) => {
if (typeof toSet === 'undefined') {
setIsOpen((state) => !state);
} else {

View file

@ -0,0 +1,62 @@
import { nonNullable, objectKeys } from '../typescript';
describe('objectKeys and nonNullable', () => {
describe('objectKeys', () => {
test('should return an array of keys from an object', () => {
// arrange
const input = { foo: 1, bar: 'baz' };
// act
const result = objectKeys(input);
// assert
expect(result).toStrictEqual(['foo', 'bar']);
});
test('should return an empty array for an empty object', () => {
// arrange
const input = {};
// act
const result = objectKeys(input);
// assert
expect(result).toStrictEqual([]);
});
});
describe('nonNullable', () => {
test('should return true for a non-null, non-undefined value', () => {
// arrange
const input = 'foo';
// act
const result = nonNullable(input);
// assert
expect(result).toBe(true);
});
test('should return false for a null value', () => {
// arrange
const input = null;
// act
const result = nonNullable(input);
// assert
expect(result).toBe(false);
});
test('should return false for an undefined value', () => {
// arrange
const input = undefined;
// act
const result = nonNullable(input);
// assert
expect(result).toBe(false);
});
});
});

View file

@ -25,6 +25,7 @@ beforeAll(async () => {
beforeEach(async () => {
jest.mock('fs-extra');
jest.mock('redis');
await setConfig('demoMode', false);
await db.user.deleteMany();
});
@ -238,6 +239,16 @@ describe('Test: getTotpUri', () => {
// act & assert
await expect(AuthService.getTotpUri({ userId, password: 'password' })).rejects.toThrowError('User not found');
});
it('should throw an error if app is in demo mode', async () => {
// arrange
await setConfig('demoMode', true);
const email = faker.internet.email();
const user = await createUser({ email }, db);
// act & assert
await expect(AuthService.getTotpUri({ userId: user.id, password: 'password' })).rejects.toThrowError('2FA is not available in demo mode');
});
});
describe('Test: setupTotp', () => {
@ -291,6 +302,16 @@ describe('Test: setupTotp', () => {
// act & assert
await expect(AuthService.setupTotp({ userId: user.id, totpCode: '1234' })).rejects.toThrowError('Invalid TOTP code');
});
it('should throw an error if app is in demo mode', async () => {
// arrange
await setConfig('demoMode', true);
const email = faker.internet.email();
const user = await createUser({ email }, db);
// act & assert
await expect(AuthService.setupTotp({ userId: user.id, totpCode: '1234' })).rejects.toThrowError('2FA is not available in demo mode');
});
});
describe('Test: disableTotp', () => {
@ -683,4 +704,15 @@ describe('Test: changePassword', () => {
// act & assert
await expect(AuthService.changePassword({ userId: user.id, newPassword, currentPassword: 'password' })).rejects.toThrowError('Password must be at least 8 characters');
});
it('should throw if instance is in demo mode', async () => {
// arrange
await setConfig('demoMode', true);
const email = faker.internet.email();
const user = await createUser({ email }, db);
const newPassword = faker.internet.password();
// act & assert
await expect(AuthService.changePassword({ userId: user.id, newPassword, currentPassword: 'password' })).rejects.toThrowError('Changing password is not allowed in demo mode');
});
});

View file

@ -111,6 +111,10 @@ export class AuthServiceClass {
* @returns {Promise<{uri: string, key: string}>} - A promise that resolves to an object containing the TOTP URI and the secret key
*/
public getTotpUri = async (params: { userId: number; password: string }) => {
if (getConfig().demoMode) {
throw new Error('2FA is not available in demo mode');
}
const { userId, password } = params;
const user = await this.prisma.user.findUnique({ where: { id: userId } });
@ -150,6 +154,10 @@ export class AuthServiceClass {
};
public setupTotp = async (params: { userId: number; totpCode: string }) => {
if (getConfig().demoMode) {
throw new Error('2FA is not available in demo mode');
}
const { userId, totpCode } = params;
const user = await this.prisma.user.findUnique({ where: { id: userId } });
@ -370,6 +378,10 @@ export class AuthServiceClass {
};
public changePassword = async (params: { currentPassword: string; newPassword: string; userId: number }) => {
if (getConfig().demoMode) {
throw new Error('Changing password is not allowed in demo mode');
}
const { currentPassword, newPassword, userId } = params;
const user = await this.prisma.user.findUnique({ where: { id: userId } });