import { TestingModule, Test } from '@nestjs/testing'; import { v4 } from 'uuid'; import * as bcrypt from 'bcrypt'; import { PrismaService } from '@modules/authentication/infrastructure/prisma.service'; import { AuthenticationRepository } from '@modules/authentication/infrastructure/authentication.repository'; import { AuthenticationMapper } from '@modules/authentication/authentication.mapper'; import { EventEmitterModule } from '@nestjs/event-emitter'; import { DatabaseErrorException, NotFoundException, UniqueConstraintException, } from '@mobicoop/ddd-library'; import { AuthenticationEntity } from '@modules/authentication/core/domain/authentication.entity'; import { Type } from '@modules/authentication/core/domain/username.types'; import { CreateAuthenticationProps } from '@modules/authentication/core/domain/authentication.types'; import { AUTH_MESSAGE_PUBLISHER } from '@modules/authentication/authentication.di-tokens'; const uuid = '165192d4-398a-4469-a16b-98c02cc6f531'; const createAuthenticationProps: CreateAuthenticationProps = { userId: uuid, password: 'somePassword', usernames: [ { type: Type.EMAIL, name: 'john.doe@email.com', }, ], }; const mockMessagePublisher = { publish: jest.fn().mockImplementation(), }; const mockLogger = { log: jest.fn(), warn: jest.fn(), error: jest.fn(), }; describe('AuthenticationRepository', () => { let prismaService: PrismaService; let authenticationRepository: AuthenticationRepository; beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ imports: [EventEmitterModule.forRoot()], providers: [ AuthenticationRepository, PrismaService, AuthenticationMapper, { provide: AUTH_MESSAGE_PUBLISHER, useValue: mockMessagePublisher, }, ], }) // disable logging .setLogger(mockLogger) .compile(); prismaService = module.get(PrismaService); authenticationRepository = module.get( AuthenticationRepository, ); }); afterAll(async () => { await prismaService.$disconnect(); }); beforeEach(async () => { await prismaService.auth.deleteMany(); }); describe('findOneById', () => { it('should return an authentication', async () => { const authToFind = await prismaService.auth.create({ data: { uuid: v4(), password: bcrypt.hashSync(`password`, 10), }, }); const auth = await authenticationRepository.findOneById(authToFind.uuid); expect(auth.id).toBe(authToFind.uuid); }); it('should throw an exception if record is not found', async () => { await expect( authenticationRepository.findOneById( '544572be-11fb-4244-8235-587221fc9104', ), ).rejects.toBeInstanceOf(NotFoundException); }); }); describe('create', () => { it('should create an authentication', async () => { const beforeCount = await prismaService.auth.count(); const authenticationToCreate: AuthenticationEntity = await AuthenticationEntity.create(createAuthenticationProps); await authenticationRepository.insert(authenticationToCreate); const afterCount = await prismaService.auth.count(); expect(afterCount - beforeCount).toBe(1); }); it('should throw a UniqueConstraintException if authentication already exists', async () => { await prismaService.auth.create({ data: { uuid: uuid, password: bcrypt.hashSync(`password`, 10), }, }); const authenticationToCreate: AuthenticationEntity = await AuthenticationEntity.create(createAuthenticationProps); await expect( authenticationRepository.insert(authenticationToCreate), ).rejects.toBeInstanceOf(UniqueConstraintException); }); }); describe('update', () => { it('should update an authentication', async () => { const authenticationToUpdate = await prismaService.auth.create({ data: { uuid: v4(), password: bcrypt.hashSync(`password`, 10), }, }); const toUpdate: AuthenticationEntity = await AuthenticationEntity.create( createAuthenticationProps, ); await authenticationRepository.update( authenticationToUpdate.uuid, toUpdate, ); const updatedAuthentication = await prismaService.auth.findUnique({ where: { uuid: toUpdate.id, }, }); expect((updatedAuthentication as any).uuid).toBe(uuid); expect(authenticationToUpdate.updatedAt.getTime()).toBeLessThan( (updatedAuthentication as any).updatedAt.getTime(), ); }); it('should throw a DatabaseException if id is unknown', async () => { const toUpdate: AuthenticationEntity = await AuthenticationEntity.create( createAuthenticationProps, ); await expect( authenticationRepository.update( '544572be-11fb-4244-8235-587221fc9104', toUpdate, ), ).rejects.toBeInstanceOf(DatabaseErrorException); }); }); describe('delete', () => { it('should delete an authentication', async () => { await prismaService.auth.create({ data: { uuid, password: bcrypt.hashSync(`password`, 10), }, }); const toDelete: AuthenticationEntity = await AuthenticationEntity.create( createAuthenticationProps, ); await authenticationRepository.delete(toDelete); const count = await prismaService.auth.count(); expect(count).toBe(0); }); it('should throw a DatabaseException if authentication does not exist', async () => { const toDelete: AuthenticationEntity = await AuthenticationEntity.create( createAuthenticationProps, ); await expect( authenticationRepository.delete(toDelete), ).rejects.toBeInstanceOf(DatabaseErrorException); }); }); });