diff --git a/src/modules/authentication/authentication.module.ts b/src/modules/authentication/authentication.module.ts index 8a9401d..dc0c776 100644 --- a/src/modules/authentication/authentication.module.ts +++ b/src/modules/authentication/authentication.module.ts @@ -16,7 +16,7 @@ import { MessageBrokerPublisher } from '@mobicoop/message-broker-module'; import { UsernameRepository } from './infrastructure/username.repository'; import { UsernameMapper } from './username.mapper'; import { AddUsernameGrpcController } from './interface/grpc-controllers/add-username.grpc.controller'; -import { AddUsernameService } from './core/application/commands/add-usernames/add-username.service'; +import { AddUsernameService } from './core/application/commands/add-username/add-username.service'; const grpcControllers = [ CreateAuthenticationGrpcController, diff --git a/src/modules/authentication/core/application/commands/add-usernames/add-username.command.ts b/src/modules/authentication/core/application/commands/add-username/add-username.command.ts similarity index 100% rename from src/modules/authentication/core/application/commands/add-usernames/add-username.command.ts rename to src/modules/authentication/core/application/commands/add-username/add-username.command.ts diff --git a/src/modules/authentication/core/application/commands/add-usernames/add-username.service.ts b/src/modules/authentication/core/application/commands/add-username/add-username.service.ts similarity index 100% rename from src/modules/authentication/core/application/commands/add-usernames/add-username.service.ts rename to src/modules/authentication/core/application/commands/add-username/add-username.service.ts diff --git a/src/modules/authentication/interface/grpc-controllers/add-username.grpc.controller.ts b/src/modules/authentication/interface/grpc-controllers/add-username.grpc.controller.ts index a3d51c6..bc41a4e 100644 --- a/src/modules/authentication/interface/grpc-controllers/add-username.grpc.controller.ts +++ b/src/modules/authentication/interface/grpc-controllers/add-username.grpc.controller.ts @@ -9,7 +9,7 @@ import { CommandBus } from '@nestjs/cqrs'; import { GrpcMethod, RpcException } from '@nestjs/microservices'; import { UsernameAlreadyExistsException } from '@modules/authentication/core/domain/authentication.errors'; import { AddUsernameRequestDto } from './dtos/add-username.request.dto'; -import { AddUsernameCommand } from '@modules/authentication/core/application/commands/add-usernames/add-username.command'; +import { AddUsernameCommand } from '@modules/authentication/core/application/commands/add-username/add-username.command'; @UsePipes( new RpcValidationPipe({ diff --git a/src/modules/authentication/tests/unit/core/add-username.service.spec.ts b/src/modules/authentication/tests/unit/core/add-username.service.spec.ts new file mode 100644 index 0000000..8e9411a --- /dev/null +++ b/src/modules/authentication/tests/unit/core/add-username.service.spec.ts @@ -0,0 +1,106 @@ +import { + AggregateID, + ConflictException, + UniqueConstraintException, +} from '@mobicoop/ddd-library'; +import { + AUTHENTICATION_REPOSITORY, + USERNAME_REPOSITORY, +} from '@modules/authentication/authentication.di-tokens'; +import { AddUsernameCommand } from '@modules/authentication/core/application/commands/add-username/add-username.command'; +import { AddUsernameService } from '@modules/authentication/core/application/commands/add-username/add-username.service'; +import { UsernameAlreadyExistsException } from '@modules/authentication/core/domain/authentication.errors'; +import { UsernameEntity } from '@modules/authentication/core/domain/username.entity'; +import { Type } from '@modules/authentication/core/domain/username.types'; +import { AddUsernameRequestDto } from '@modules/authentication/interface/grpc-controllers/dtos/add-username.request.dto'; +import { Test, TestingModule } from '@nestjs/testing'; + +const addUsernameRequest: AddUsernameRequestDto = { + userId: '165192d4-398a-4469-a16b-98c02cc6f531', + name: 'john.doe@email.com', + type: Type.EMAIL, +}; + +const mockAuthenticationRepository = { + findOneById: jest.fn().mockImplementationOnce(() => ({})), +}; + +const mockUsernameRepository = { + insert: jest + .fn() + .mockImplementationOnce(() => ({})) + .mockImplementationOnce(() => { + throw new ConflictException('already exists'); + }) + .mockImplementationOnce(() => { + throw new UniqueConstraintException('username'); + }) + .mockImplementationOnce(() => { + throw new Error(); + }), +}; + +describe('Add Username Service', () => { + let addUsernameService: AddUsernameService; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: AUTHENTICATION_REPOSITORY, + useValue: mockAuthenticationRepository, + }, + { + provide: USERNAME_REPOSITORY, + useValue: mockUsernameRepository, + }, + AddUsernameService, + ], + }).compile(); + + addUsernameService = module.get(AddUsernameService); + }); + + it('should be defined', () => { + expect(addUsernameService).toBeDefined(); + }); + + describe('execution', () => { + const addUsernameCommand = new AddUsernameCommand({ + userId: addUsernameRequest.userId, + username: { + name: addUsernameRequest.name, + type: addUsernameRequest.type, + }, + }); + UsernameEntity.create = jest.fn().mockReturnValue({ + id: 'john.doe@email.com', + getProps: jest.fn().mockImplementation(() => ({ + userId: '165192d4-398a-4469-a16b-98c02cc6f531', + name: 'john.doe@email.com', + type: Type.EMAIL, + })), + }); + it('should add a new username', async () => { + const result: AggregateID = await addUsernameService.execute( + addUsernameCommand, + ); + expect(result).toBe('john.doe@email.com'); + }); + it('should throw a dedicated exception if username already exists for this type', async () => { + await expect( + addUsernameService.execute(addUsernameCommand), + ).rejects.toBeInstanceOf(UsernameAlreadyExistsException); + }); + it('should throw a dedicated exception if username already exists for this name', async () => { + await expect( + addUsernameService.execute(addUsernameCommand), + ).rejects.toBeInstanceOf(UsernameAlreadyExistsException); + }); + it('should throw an error if something bad happens', async () => { + await expect( + addUsernameService.execute(addUsernameCommand), + ).rejects.toBeInstanceOf(Error); + }); + }); +}); diff --git a/src/modules/authentication/tests/unit/core/create-authentication.service.spec.ts b/src/modules/authentication/tests/unit/core/create-authentication.service.spec.ts index b4b1d25..b4df3d5 100644 --- a/src/modules/authentication/tests/unit/core/create-authentication.service.spec.ts +++ b/src/modules/authentication/tests/unit/core/create-authentication.service.spec.ts @@ -44,7 +44,7 @@ const mockAuthenticationRepository = { }), }; -describe('create-authentication.service', () => { +describe('Create Authentication Service', () => { let createAuthenticationService: CreateAuthenticationService; beforeAll(async () => { @@ -68,63 +68,39 @@ describe('create-authentication.service', () => { }); describe('execution', () => { - const createAdCommand = new CreateAuthenticationCommand( + const createAuthenticationCommand = new CreateAuthenticationCommand( createAuthenticationRequest, ); + AuthenticationEntity.create = jest.fn().mockReturnValue({ + id: '165192d4-398a-4469-a16b-98c02cc6f531', + getProps: jest.fn().mockImplementation(() => ({ + userId: '165192d4-398a-4469-a16b-98c02cc6f531', + })), + }); it('should create a new authentication', async () => { - AuthenticationEntity.create = jest.fn().mockReturnValue({ - id: '165192d4-398a-4469-a16b-98c02cc6f531', - getProps: jest.fn().mockImplementation(() => ({ - userId: '165192d4-398a-4469-a16b-98c02cc6f531', - })), - }); const result: AggregateID = await createAuthenticationService.execute( - createAdCommand, + createAuthenticationCommand, ); expect(result).toBe('165192d4-398a-4469-a16b-98c02cc6f531'); }); it('should throw a dedicated exception if Authentication already exists', async () => { - AuthenticationEntity.create = jest.fn().mockReturnValue({ - id: '165192d4-398a-4469-a16b-98c02cc6f531', - getProps: jest.fn().mockImplementation(() => ({ - userId: '165192d4-398a-4469-a16b-98c02cc6f531', - })), - }); await expect( - createAuthenticationService.execute(createAdCommand), + createAuthenticationService.execute(createAuthenticationCommand), ).rejects.toBeInstanceOf(AuthenticationAlreadyExistsException); }); it('should throw a dedicated exception if uuid already exists', async () => { - AuthenticationEntity.create = jest.fn().mockReturnValue({ - id: '165192d4-398a-4469-a16b-98c02cc6f531', - getProps: jest.fn().mockImplementation(() => ({ - userId: '165192d4-398a-4469-a16b-98c02cc6f531', - })), - }); await expect( - createAuthenticationService.execute(createAdCommand), + createAuthenticationService.execute(createAuthenticationCommand), ).rejects.toBeInstanceOf(AuthenticationAlreadyExistsException); }); it('should throw a dedicated exception if username already exists', async () => { - AuthenticationEntity.create = jest.fn().mockReturnValue({ - id: '165192d4-398a-4469-a16b-98c02cc6f531', - getProps: jest.fn().mockImplementation(() => ({ - userId: '165192d4-398a-4469-a16b-98c02cc6f531', - })), - }); await expect( - createAuthenticationService.execute(createAdCommand), + createAuthenticationService.execute(createAuthenticationCommand), ).rejects.toBeInstanceOf(UsernameAlreadyExistsException); }); it('should throw an error if something bad happens', async () => { - AuthenticationEntity.create = jest.fn().mockReturnValue({ - id: '165192d4-398a-4469-a16b-98c02cc6f531', - getProps: jest.fn().mockImplementation(() => ({ - userId: '165192d4-398a-4469-a16b-98c02cc6f531', - })), - }); await expect( - createAuthenticationService.execute(createAdCommand), + createAuthenticationService.execute(createAuthenticationCommand), ).rejects.toBeInstanceOf(Error); }); });