tests for infractructure, domain entities and create authentication service
This commit is contained in:
parent
470a93879e
commit
b23f8f9ade
|
@ -1,11 +1,13 @@
|
|||
import { AggregateID, AggregateRoot } from '@mobicoop/ddd-library';
|
||||
import { UsernameProps } from './username.types';
|
||||
import { CreateUsernameProps, UsernameProps } from './username.types';
|
||||
import { UsernameAddedDomainEvent } from './events/username-added.domain-event';
|
||||
|
||||
export class UsernameEntity extends AggregateRoot<UsernameProps> {
|
||||
protected readonly _id: AggregateID;
|
||||
|
||||
static create = async (create: UsernameProps): Promise<UsernameEntity> => {
|
||||
static create = async (
|
||||
create: CreateUsernameProps,
|
||||
): Promise<UsernameEntity> => {
|
||||
const props: UsernameProps = { ...create };
|
||||
const username = new UsernameEntity({
|
||||
id: props.name,
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
// All properties that a Username has
|
||||
export interface UsernameProps {
|
||||
name: string;
|
||||
userId?: string;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export interface CreateUsernameProps {
|
||||
name: string;
|
||||
userId: string;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export enum Type {
|
||||
EMAIL = 'EMAIL',
|
||||
PHONE = 'PHONE',
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
import { AuthenticationEntity } from '@modules/authentication/core/domain/authentication.entity';
|
||||
import { CreateAuthenticationProps } from '@modules/authentication/core/domain/authentication.types';
|
||||
import { AuthenticationDeletedDomainEvent } from '@modules/authentication/core/domain/events/authentication-deleted.domain-event';
|
||||
import { Type } from '@modules/authentication/core/domain/username.types';
|
||||
|
||||
const createAuthenticationProps: CreateAuthenticationProps = {
|
||||
userId: '165192d4-398a-4469-a16b-98c02cc6f531',
|
||||
password: 'somePassword',
|
||||
usernames: [
|
||||
{
|
||||
type: Type.EMAIL,
|
||||
name: 'john.doe@email.com',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const createAuthenticationPropsWith2Usernames: CreateAuthenticationProps = {
|
||||
userId: '165192d4-398a-4469-a16b-98c02cc6f531',
|
||||
password: 'somePassword',
|
||||
usernames: [
|
||||
{
|
||||
type: Type.EMAIL,
|
||||
name: 'john.doe@email.com',
|
||||
},
|
||||
{
|
||||
type: Type.PHONE,
|
||||
name: '+33611223344',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe('Authentication entity create', () => {
|
||||
it('should create a new authentication entity', async () => {
|
||||
const authenticationEntity: AuthenticationEntity =
|
||||
await AuthenticationEntity.create(createAuthenticationProps);
|
||||
expect(authenticationEntity.id).toBe(
|
||||
'165192d4-398a-4469-a16b-98c02cc6f531',
|
||||
);
|
||||
expect(authenticationEntity.domainEvents.length).toBe(1);
|
||||
});
|
||||
it('should create a new authentication entity with 2 usernames', async () => {
|
||||
const authenticationEntity: AuthenticationEntity =
|
||||
await AuthenticationEntity.create(
|
||||
createAuthenticationPropsWith2Usernames,
|
||||
);
|
||||
expect(authenticationEntity.id).toBe(
|
||||
'165192d4-398a-4469-a16b-98c02cc6f531',
|
||||
);
|
||||
expect(authenticationEntity.getProps().usernames.length).toBe(2);
|
||||
expect(authenticationEntity.domainEvents.length).toBe(1);
|
||||
});
|
||||
it('should delete an authentication entity', async () => {
|
||||
const authenticationEntity: AuthenticationEntity =
|
||||
await AuthenticationEntity.create(createAuthenticationProps);
|
||||
authenticationEntity.delete();
|
||||
expect(authenticationEntity.domainEvents.length).toBe(2);
|
||||
expect(authenticationEntity.domainEvents[1]).toBeInstanceOf(
|
||||
AuthenticationDeletedDomainEvent,
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,131 @@
|
|||
import {
|
||||
AggregateID,
|
||||
ConflictException,
|
||||
UniqueConstraintException,
|
||||
} from '@mobicoop/ddd-library';
|
||||
import { AUTHENTICATION_REPOSITORY } from '@modules/authentication/authentication.di-tokens';
|
||||
import { CreateAuthenticationCommand } from '@modules/authentication/core/application/commands/create-authentication/create-authentication.command';
|
||||
import { CreateAuthenticationService } from '@modules/authentication/core/application/commands/create-authentication/create-authentication.service';
|
||||
import { AuthenticationEntity } from '@modules/authentication/core/domain/authentication.entity';
|
||||
import {
|
||||
AuthenticationAlreadyExistsException,
|
||||
UsernameAlreadyExistsException,
|
||||
} from '@modules/authentication/core/domain/authentication.errors';
|
||||
import { Type } from '@modules/authentication/core/domain/username.types';
|
||||
import { CreateAuthenticationRequestDto } from '@modules/authentication/interface/grpc-controllers/dtos/create-authentication.request.dto';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
const createAuthenticationRequest: CreateAuthenticationRequestDto = {
|
||||
userId: '165192d4-398a-4469-a16b-98c02cc6f531',
|
||||
password: 'somePassword',
|
||||
usernames: [
|
||||
{
|
||||
name: 'john.doe@email.com',
|
||||
type: Type.EMAIL,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mockAuthenticationRepository = {
|
||||
insert: jest
|
||||
.fn()
|
||||
.mockImplementationOnce(() => ({}))
|
||||
.mockImplementationOnce(() => {
|
||||
throw new ConflictException('already exists');
|
||||
})
|
||||
.mockImplementationOnce(() => {
|
||||
throw new UniqueConstraintException('uuid');
|
||||
})
|
||||
.mockImplementationOnce(() => {
|
||||
throw new UniqueConstraintException('username');
|
||||
})
|
||||
.mockImplementationOnce(() => {
|
||||
throw new Error();
|
||||
}),
|
||||
};
|
||||
|
||||
describe('create-authentication.service', () => {
|
||||
let createAuthenticationService: CreateAuthenticationService;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
{
|
||||
provide: AUTHENTICATION_REPOSITORY,
|
||||
useValue: mockAuthenticationRepository,
|
||||
},
|
||||
CreateAuthenticationService,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
createAuthenticationService = module.get<CreateAuthenticationService>(
|
||||
CreateAuthenticationService,
|
||||
);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(createAuthenticationService).toBeDefined();
|
||||
});
|
||||
|
||||
describe('execution', () => {
|
||||
const createAdCommand = new CreateAuthenticationCommand(
|
||||
createAuthenticationRequest,
|
||||
);
|
||||
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,
|
||||
);
|
||||
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),
|
||||
).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),
|
||||
).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),
|
||||
).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),
|
||||
).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
import { UsernameEntity } from '@modules/authentication/core/domain/username.entity';
|
||||
import {
|
||||
CreateUsernameProps,
|
||||
Type,
|
||||
} from '@modules/authentication/core/domain/username.types';
|
||||
|
||||
const createUsernameProps: CreateUsernameProps = {
|
||||
userId: '165192d4-398a-4469-a16b-98c02cc6f531',
|
||||
type: Type.EMAIL,
|
||||
name: 'john.doe@email.com',
|
||||
};
|
||||
|
||||
describe('Username entity create', () => {
|
||||
it('should create a new username entity', async () => {
|
||||
const usernameEntity: UsernameEntity = await UsernameEntity.create(
|
||||
createUsernameProps,
|
||||
);
|
||||
expect(usernameEntity.id).toBe('john.doe@email.com');
|
||||
expect(usernameEntity.domainEvents.length).toBe(1);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
import { AuthenticationMapper } from '@modules/authentication/authentication.mapper';
|
||||
import { AuthenticationRepository } from '@modules/authentication/infrastructure/authentication.repository';
|
||||
import { PrismaService } from '@modules/authentication/infrastructure/prisma.service';
|
||||
import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
const mockMessagePublisher = {
|
||||
publish: jest.fn().mockImplementation(),
|
||||
};
|
||||
|
||||
describe('Authentication repository', () => {
|
||||
let prismaService: PrismaService;
|
||||
let authenticationMapper: AuthenticationMapper;
|
||||
let eventEmitter: EventEmitter2;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [EventEmitterModule.forRoot()],
|
||||
providers: [PrismaService, AuthenticationMapper],
|
||||
}).compile();
|
||||
|
||||
prismaService = module.get<PrismaService>(PrismaService);
|
||||
authenticationMapper =
|
||||
module.get<AuthenticationMapper>(AuthenticationMapper);
|
||||
eventEmitter = module.get<EventEmitter2>(EventEmitter2);
|
||||
});
|
||||
it('should be defined', () => {
|
||||
expect(
|
||||
new AuthenticationRepository(
|
||||
prismaService,
|
||||
authenticationMapper,
|
||||
eventEmitter,
|
||||
mockMessagePublisher,
|
||||
),
|
||||
).toBeDefined();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
import { UsernameMapper } from '@modules/authentication/username.mapper';
|
||||
import { PrismaService } from '@modules/authentication/infrastructure/prisma.service';
|
||||
import { EventEmitter2, EventEmitterModule } from '@nestjs/event-emitter';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { UsernameRepository } from '@modules/authentication/infrastructure/username.repository';
|
||||
|
||||
const mockMessagePublisher = {
|
||||
publish: jest.fn().mockImplementation(),
|
||||
};
|
||||
|
||||
describe('Username repository', () => {
|
||||
let prismaService: PrismaService;
|
||||
let usernameMapper: UsernameMapper;
|
||||
let eventEmitter: EventEmitter2;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [EventEmitterModule.forRoot()],
|
||||
providers: [PrismaService, UsernameMapper],
|
||||
}).compile();
|
||||
|
||||
prismaService = module.get<PrismaService>(PrismaService);
|
||||
usernameMapper = module.get<UsernameMapper>(UsernameMapper);
|
||||
eventEmitter = module.get<EventEmitter2>(EventEmitter2);
|
||||
});
|
||||
it('should be defined', () => {
|
||||
expect(
|
||||
new UsernameRepository(
|
||||
prismaService,
|
||||
usernameMapper,
|
||||
eventEmitter,
|
||||
mockMessagePublisher,
|
||||
),
|
||||
).toBeDefined();
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue