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 { 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';
|
import { UsernameAddedDomainEvent } from './events/username-added.domain-event';
|
||||||
|
|
||||||
export class UsernameEntity extends AggregateRoot<UsernameProps> {
|
export class UsernameEntity extends AggregateRoot<UsernameProps> {
|
||||||
protected readonly _id: AggregateID;
|
protected readonly _id: AggregateID;
|
||||||
|
|
||||||
static create = async (create: UsernameProps): Promise<UsernameEntity> => {
|
static create = async (
|
||||||
|
create: CreateUsernameProps,
|
||||||
|
): Promise<UsernameEntity> => {
|
||||||
const props: UsernameProps = { ...create };
|
const props: UsernameProps = { ...create };
|
||||||
const username = new UsernameEntity({
|
const username = new UsernameEntity({
|
||||||
id: props.name,
|
id: props.name,
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
// All properties that a Username has
|
|
||||||
export interface UsernameProps {
|
export interface UsernameProps {
|
||||||
name: string;
|
name: string;
|
||||||
userId?: string;
|
userId?: string;
|
||||||
type: Type;
|
type: Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CreateUsernameProps {
|
||||||
|
name: string;
|
||||||
|
userId: string;
|
||||||
|
type: Type;
|
||||||
|
}
|
||||||
|
|
||||||
export enum Type {
|
export enum Type {
|
||||||
EMAIL = 'EMAIL',
|
EMAIL = 'EMAIL',
|
||||||
PHONE = 'PHONE',
|
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