Merge branch 'crud' into 'main'
Crud See merge request mobicoop/lab/v3/services/user!1
This commit is contained in:
commit
ff3ac73ecb
|
@ -1,10 +0,0 @@
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "user" (
|
|
||||||
"uuid" UUID NOT NULL,
|
|
||||||
"firstName" TEXT NOT NULL,
|
|
||||||
"lastName" TEXT NOT NULL,
|
|
||||||
"email" TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "user_uuid_key" ON "user"("uuid");
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "user" (
|
||||||
|
"uuid" UUID NOT NULL,
|
||||||
|
"firstName" TEXT NOT NULL,
|
||||||
|
"lastName" TEXT NOT NULL,
|
||||||
|
"email" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "user_pkey" PRIMARY KEY ("uuid")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "user_email_key" ON "user"("email");
|
|
@ -11,10 +11,12 @@ datasource db {
|
||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
uuid String @unique @default(uuid()) @db.Uuid
|
uuid String @id @default(uuid()) @db.Uuid
|
||||||
firstName String
|
firstName String
|
||||||
lastName String
|
lastName String
|
||||||
email String
|
email String @unique
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
@@map("user")
|
@@map("user")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
|
import { classes } from '@automapper/classes';
|
||||||
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { UsersModule } from './modules/users/users.module';
|
import { UsersModule } from './modules/users/users.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule.forRoot({ isGlobal: true }), UsersModule],
|
imports: [
|
||||||
|
ConfigModule.forRoot({ isGlobal: true }),
|
||||||
|
AutomapperModule.forRoot({ strategyInitializer: classes() }),
|
||||||
|
UsersModule,
|
||||||
|
],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
providers: [],
|
providers: [],
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,7 +9,6 @@ export class DatabaseException implements Error {
|
||||||
) {
|
) {
|
||||||
this.name = 'DatabaseException';
|
this.name = 'DatabaseException';
|
||||||
this.message = message ?? 'An error occured with the database.';
|
this.message = message ?? 'An error occured with the database.';
|
||||||
|
|
||||||
if (this.message.includes('Unique constraint failed')) {
|
if (this.message.includes('Unique constraint failed')) {
|
||||||
this.message = 'Already exists.';
|
this.message = 'Already exists.';
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ package user;
|
||||||
service UsersService {
|
service UsersService {
|
||||||
rpc FindOneByUuid(UserByUuid) returns (User);
|
rpc FindOneByUuid(UserByUuid) returns (User);
|
||||||
rpc FindAll(UserFilter) returns (Users);
|
rpc FindAll(UserFilter) returns (Users);
|
||||||
rpc Create(CreateUser) returns (User);
|
rpc Create(User) returns (User);
|
||||||
|
rpc Update(User) returns (User);
|
||||||
|
rpc Delete(UserByUuid) returns (Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
message UserByUuid {
|
message UserByUuid {
|
||||||
|
@ -19,15 +21,10 @@ message User {
|
||||||
string email = 4;
|
string email = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CreateUser {
|
|
||||||
string uuid = 1;
|
|
||||||
string firstName = 2;
|
|
||||||
string lastName = 3;
|
|
||||||
string email = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message UserFilter {}
|
message UserFilter {}
|
||||||
|
|
||||||
message Users {
|
message Users {
|
||||||
repeated User users = 1;
|
repeated User users = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message Empty {}
|
||||||
|
|
|
@ -1,25 +1,97 @@
|
||||||
|
import { Mapper } from '@automapper/core';
|
||||||
|
import { InjectMapper } from '@automapper/nestjs';
|
||||||
import { Controller } from '@nestjs/common';
|
import { Controller } from '@nestjs/common';
|
||||||
import { QueryBus } from '@nestjs/cqrs';
|
import { CommandBus, QueryBus } from '@nestjs/cqrs';
|
||||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||||
import { FindUserByUuidRequest } from '../../domain/dto/findUserByUuidRequest';
|
import { DatabaseException } from 'src/modules/database/src/exceptions/DatabaseException';
|
||||||
|
import { CreateUserCommand } from '../../commands/create-user.command';
|
||||||
|
import { DeleteUserCommand } from '../../commands/delete-user.command';
|
||||||
|
import { UpdateUserCommand } from '../../commands/update-user.command';
|
||||||
|
import { CreateUserRequest } from '../../domain/dto/create-user.request';
|
||||||
|
import { FindUserByUuidRequest } from '../../domain/dto/find-user-by-uuid.request';
|
||||||
|
import { UpdateUserRequest } from '../../domain/dto/update-user.request';
|
||||||
import { User } from '../../domain/entities/user';
|
import { User } from '../../domain/entities/user';
|
||||||
import { FindUserByUuidQuery } from '../../queries/find-user-by-uuid.query';
|
import { FindUserByUuidQuery } from '../../queries/find-user-by-uuid.query';
|
||||||
|
import { UserPresenter } from './user.presenter';
|
||||||
|
|
||||||
@Controller()
|
@Controller()
|
||||||
export class UsersController {
|
export class UsersController {
|
||||||
constructor(private readonly _queryBus: QueryBus) {}
|
constructor(
|
||||||
|
private readonly _commandBus: CommandBus,
|
||||||
|
private readonly _queryBus: QueryBus,
|
||||||
|
@InjectMapper() private readonly _mapper: Mapper,
|
||||||
|
) {}
|
||||||
|
|
||||||
@GrpcMethod('UsersService', 'FindOneByUuid')
|
@GrpcMethod('UsersService', 'FindOneByUuid')
|
||||||
async findOneByUuid(data: FindUserByUuidRequest): Promise<User> {
|
async findOneByUuid(data: FindUserByUuidRequest): Promise<UserPresenter> {
|
||||||
const user = await this._queryBus.execute(
|
const user = await this._queryBus.execute(
|
||||||
new FindUserByUuidQuery(data.uuid),
|
new FindUserByUuidQuery(data.uuid),
|
||||||
);
|
);
|
||||||
if (user) {
|
if (user) {
|
||||||
return user;
|
return this._mapper.map(user, User, UserPresenter);
|
||||||
}
|
}
|
||||||
throw new RpcException({
|
throw new RpcException({
|
||||||
code: 5,
|
code: 5,
|
||||||
message: 'User not found',
|
message: 'User not found',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GrpcMethod('UsersService', 'Create')
|
||||||
|
async createUser(data: CreateUserRequest): Promise<UserPresenter> {
|
||||||
|
try {
|
||||||
|
const user = await this._commandBus.execute(new CreateUserCommand(data));
|
||||||
|
return this._mapper.map(user, User, UserPresenter);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DatabaseException) {
|
||||||
|
if (e.message.includes('Already exists')) {
|
||||||
|
throw new RpcException({
|
||||||
|
code: 6,
|
||||||
|
message: 'User already exists',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RpcException({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GrpcMethod('UsersService', 'Update')
|
||||||
|
async updateUser(data: UpdateUserRequest): Promise<UserPresenter> {
|
||||||
|
try {
|
||||||
|
const user = await this._commandBus.execute(new UpdateUserCommand(data));
|
||||||
|
|
||||||
|
return this._mapper.map(user, User, UserPresenter);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DatabaseException) {
|
||||||
|
if (e.message.includes('not found')) {
|
||||||
|
throw new RpcException({
|
||||||
|
code: 5,
|
||||||
|
message: 'User not found',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RpcException({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GrpcMethod('UsersService', 'Delete')
|
||||||
|
async deleteUser(data: FindUserByUuidRequest): Promise<void> {
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const user = await this._commandBus.execute(
|
||||||
|
new DeleteUserCommand(data.uuid),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DatabaseException) {
|
||||||
|
if (e.message.includes('not found')) {
|
||||||
|
throw new RpcException({
|
||||||
|
code: 5,
|
||||||
|
message: 'User not found',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RpcException({});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { CreateUserRequest } from '../domain/dto/create-user.request';
|
||||||
|
|
||||||
|
export class CreateUserCommand {
|
||||||
|
readonly createUserRequest: CreateUserRequest;
|
||||||
|
|
||||||
|
constructor(request: CreateUserRequest) {
|
||||||
|
this.createUserRequest = request;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
export class DeleteUserCommand {
|
||||||
|
readonly uuid: string;
|
||||||
|
|
||||||
|
constructor(uuid: string) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { UpdateUserRequest } from '../domain/dto/update-user.request';
|
||||||
|
|
||||||
|
export class UpdateUserCommand {
|
||||||
|
readonly updateUserRequest: UpdateUserRequest;
|
||||||
|
|
||||||
|
constructor(request: UpdateUserRequest) {
|
||||||
|
this.updateUserRequest = request;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateUserRequest {
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
firstName: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
lastName: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@AutoMap()
|
||||||
|
email: string;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class FindUserByUuidRequest {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
uuid: string;
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
import { IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class FindUserByUuidRequest {
|
|
||||||
@IsString()
|
|
||||||
uuid: string;
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class UpdateUserRequest {
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
firstName?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
lastName?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
email?: string;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Mapper } from '@automapper/core';
|
||||||
|
import { InjectMapper } from '@automapper/nestjs';
|
||||||
|
import { CommandHandler } from '@nestjs/cqrs';
|
||||||
|
import { UsersRepository } from '../../adapters/secondaries/users.repository';
|
||||||
|
import { CreateUserCommand } from '../../commands/create-user.command';
|
||||||
|
import { CreateUserRequest } from '../dto/create-user.request';
|
||||||
|
import { User } from '../entities/user';
|
||||||
|
|
||||||
|
@CommandHandler(CreateUserCommand)
|
||||||
|
export class CreateUserUseCase {
|
||||||
|
constructor(
|
||||||
|
private readonly _repository: UsersRepository,
|
||||||
|
@InjectMapper() private readonly _mapper: Mapper,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async execute(command: CreateUserCommand): Promise<User> {
|
||||||
|
const entity = this._mapper.map(
|
||||||
|
command.createUserRequest,
|
||||||
|
CreateUserRequest,
|
||||||
|
User,
|
||||||
|
);
|
||||||
|
|
||||||
|
return this._repository.create(entity);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { CommandHandler } from '@nestjs/cqrs';
|
||||||
|
import { UsersRepository } from '../../adapters/secondaries/users.repository';
|
||||||
|
import { DeleteUserCommand } from '../../commands/delete-user.command';
|
||||||
|
|
||||||
|
@CommandHandler(DeleteUserCommand)
|
||||||
|
export class DeleteUserUseCase {
|
||||||
|
constructor(private readonly _repository: UsersRepository) {}
|
||||||
|
|
||||||
|
async execute(command: DeleteUserCommand): Promise<void> {
|
||||||
|
return this._repository.delete(command.uuid);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Mapper } from '@automapper/core';
|
||||||
|
import { InjectMapper } from '@automapper/nestjs';
|
||||||
|
import { CommandHandler } from '@nestjs/cqrs';
|
||||||
|
import { UsersRepository } from '../../adapters/secondaries/users.repository';
|
||||||
|
import { UpdateUserCommand } from '../../commands/update-user.command';
|
||||||
|
import { UpdateUserRequest } from '../dto/update-user.request';
|
||||||
|
import { User } from '../entities/user';
|
||||||
|
|
||||||
|
@CommandHandler(UpdateUserCommand)
|
||||||
|
export class UpdateUserUseCase {
|
||||||
|
constructor(
|
||||||
|
private readonly _repository: UsersRepository,
|
||||||
|
@InjectMapper() private readonly _mapper: Mapper,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async execute(command: UpdateUserCommand): Promise<User> {
|
||||||
|
const entity = this._mapper.map(
|
||||||
|
command.updateUserRequest,
|
||||||
|
UpdateUserRequest,
|
||||||
|
User,
|
||||||
|
);
|
||||||
|
|
||||||
|
return this._repository.update(command.updateUserRequest.uuid, entity);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
import { createMap, Mapper } from '@automapper/core';
|
import { createMap, forMember, ignore, Mapper } from '@automapper/core';
|
||||||
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { UserPresenter } from '../adapters/primaries/user.presenter';
|
import { UserPresenter } from '../adapters/primaries/user.presenter';
|
||||||
|
import { CreateUserRequest } from '../domain/dto/create-user.request';
|
||||||
|
import { UpdateUserRequest } from '../domain/dto/update-user.request';
|
||||||
import { User } from '../domain/entities/user';
|
import { User } from '../domain/entities/user';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -13,6 +15,15 @@ export class UserProfile extends AutomapperProfile {
|
||||||
override get profile() {
|
override get profile() {
|
||||||
return (mapper) => {
|
return (mapper) => {
|
||||||
createMap(mapper, User, UserPresenter);
|
createMap(mapper, User, UserPresenter);
|
||||||
|
|
||||||
|
createMap(mapper, CreateUserRequest, User);
|
||||||
|
|
||||||
|
createMap(
|
||||||
|
mapper,
|
||||||
|
UpdateUserRequest,
|
||||||
|
User,
|
||||||
|
forMember((dest) => dest.uuid, ignore()),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { classes } from '@automapper/classes';
|
||||||
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { UsersRepository } from '../../adapters/secondaries/users.repository';
|
||||||
|
import { CreateUserCommand } from '../../commands/create-user.command';
|
||||||
|
import { CreateUserRequest } from '../../domain/dto/create-user.request';
|
||||||
|
import { User } from '../../domain/entities/user';
|
||||||
|
import { CreateUserUseCase } from '../../domain/usecases/create-user.usecase';
|
||||||
|
import { UserProfile } from '../../mappers/user.profile';
|
||||||
|
|
||||||
|
const newUserRequest: CreateUserRequest = {
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
email: 'john.doe@email.com',
|
||||||
|
};
|
||||||
|
const newUserCommand: CreateUserCommand = new CreateUserCommand(newUserRequest);
|
||||||
|
|
||||||
|
const mockUsersRepository = {
|
||||||
|
create: jest.fn().mockResolvedValue({
|
||||||
|
...newUserRequest,
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('CreateUserUseCase', () => {
|
||||||
|
let createUserUseCase: CreateUserUseCase;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: UsersRepository,
|
||||||
|
useValue: mockUsersRepository,
|
||||||
|
},
|
||||||
|
CreateUserUseCase,
|
||||||
|
UserProfile,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
createUserUseCase = module.get<CreateUserUseCase>(CreateUserUseCase);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(createUserUseCase).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('execute', () => {
|
||||||
|
it('should create an User and returns new entity object', async () => {
|
||||||
|
const newUser: User = await createUserUseCase.execute(newUserCommand);
|
||||||
|
|
||||||
|
expect(newUser.lastName).toBe(newUserRequest.lastName);
|
||||||
|
expect(newUser.uuid).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { UsersRepository } from '../../adapters/secondaries/users.repository';
|
||||||
|
import { DeleteUserCommand } from '../../commands/delete-user.command';
|
||||||
|
import { DeleteUserUseCase } from '../../domain/usecases/delete-user.usecase';
|
||||||
|
|
||||||
|
const usersMock = [
|
||||||
|
{
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
email: 'john.doe@email.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a92',
|
||||||
|
firstName: 'Jane',
|
||||||
|
lastName: 'Doe',
|
||||||
|
email: 'jane.doe@email.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a93',
|
||||||
|
firstName: 'Jimmy',
|
||||||
|
lastName: 'Doe',
|
||||||
|
email: 'jimmy.doe@email.com',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const mockUsersRepository = {
|
||||||
|
delete: jest.fn().mockImplementation((uuid: string) => {
|
||||||
|
usersMock.forEach((user, index) => {
|
||||||
|
if (user.uuid === uuid) {
|
||||||
|
usersMock.splice(index, 1);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('DeleteUserUseCase', () => {
|
||||||
|
let deleteUserUseCase: DeleteUserUseCase;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: UsersRepository,
|
||||||
|
useValue: mockUsersRepository,
|
||||||
|
},
|
||||||
|
DeleteUserUseCase,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
deleteUserUseCase = module.get<DeleteUserUseCase>(DeleteUserUseCase);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(deleteUserUseCase).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('execute', () => {
|
||||||
|
it('should delete an User', async () => {
|
||||||
|
const savedUuid = usersMock[0].uuid;
|
||||||
|
const deleteUserCommand = new DeleteUserCommand(savedUuid);
|
||||||
|
await deleteUserUseCase.execute(deleteUserCommand);
|
||||||
|
|
||||||
|
const deletedUser = usersMock.find((user) => user.uuid === savedUuid);
|
||||||
|
expect(deletedUser).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -28,7 +28,6 @@ describe('FindUserByUuidUseCase', () => {
|
||||||
provide: UsersRepository,
|
provide: UsersRepository,
|
||||||
useValue: mockUserRepository,
|
useValue: mockUserRepository,
|
||||||
},
|
},
|
||||||
|
|
||||||
FindUserByUuidUseCase,
|
FindUserByUuidUseCase,
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
import { classes } from '@automapper/classes';
|
||||||
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { UsersRepository } from '../../adapters/secondaries/users.repository';
|
||||||
|
import { UpdateUserCommand } from '../../commands/update-user.command';
|
||||||
|
import { UpdateUserRequest } from '../../domain/dto/update-user.request';
|
||||||
|
import { User } from '../../domain/entities/user';
|
||||||
|
import { UpdateUserUseCase } from '../../domain/usecases/update-user.usecase';
|
||||||
|
import { UserProfile } from '../../mappers/user.profile';
|
||||||
|
|
||||||
|
const originalUser: User = new User();
|
||||||
|
originalUser.uuid = 'bb281075-1b98-4456-89d6-c643d3044a91';
|
||||||
|
originalUser.lastName = 'Doe';
|
||||||
|
|
||||||
|
const updateUserRequest: UpdateUserRequest = {
|
||||||
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
lastName: 'Dane',
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateUserCommand: UpdateUserCommand = new UpdateUserCommand(
|
||||||
|
updateUserRequest,
|
||||||
|
);
|
||||||
|
|
||||||
|
const mockUsersRepository = {
|
||||||
|
update: jest.fn().mockImplementation((uuid: string, params: any) => {
|
||||||
|
originalUser.lastName = params.lastName;
|
||||||
|
|
||||||
|
return Promise.resolve(originalUser);
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('UpdateUserUseCase', () => {
|
||||||
|
let updateUserUseCase: UpdateUserUseCase;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
||||||
|
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: UsersRepository,
|
||||||
|
useValue: mockUsersRepository,
|
||||||
|
},
|
||||||
|
UpdateUserUseCase,
|
||||||
|
UserProfile,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
updateUserUseCase = module.get<UpdateUserUseCase>(UpdateUserUseCase);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(updateUserUseCase).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('execute', () => {
|
||||||
|
it('should update an User', async () => {
|
||||||
|
const updatedUser: User = await updateUserUseCase.execute(
|
||||||
|
updateUserCommand,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(updatedUser.lastName).toBe(updateUserRequest.lastName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,12 +3,23 @@ import { CqrsModule } from '@nestjs/cqrs';
|
||||||
import { DatabaseModule } from '../database/database.module';
|
import { DatabaseModule } from '../database/database.module';
|
||||||
import { UsersController } from './adapters/primaries/users.controller';
|
import { UsersController } from './adapters/primaries/users.controller';
|
||||||
import { UsersRepository } from './adapters/secondaries/users.repository';
|
import { UsersRepository } from './adapters/secondaries/users.repository';
|
||||||
|
import { CreateUserUseCase } from './domain/usecases/create-user.usecase';
|
||||||
|
import { DeleteUserUseCase } from './domain/usecases/delete-user.usecase';
|
||||||
import { FindUserByUuidUseCase } from './domain/usecases/find-user-by-uuid.usecase';
|
import { FindUserByUuidUseCase } from './domain/usecases/find-user-by-uuid.usecase';
|
||||||
|
import { UpdateUserUseCase } from './domain/usecases/update-user.usecase';
|
||||||
|
import { UserProfile } from './mappers/user.profile';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [DatabaseModule, CqrsModule],
|
imports: [DatabaseModule, CqrsModule],
|
||||||
controllers: [UsersController],
|
controllers: [UsersController],
|
||||||
providers: [UsersRepository, FindUserByUuidUseCase],
|
providers: [
|
||||||
|
UserProfile,
|
||||||
|
UsersRepository,
|
||||||
|
FindUserByUuidUseCase,
|
||||||
|
CreateUserUseCase,
|
||||||
|
UpdateUserUseCase,
|
||||||
|
DeleteUserUseCase,
|
||||||
|
],
|
||||||
exports: [],
|
exports: [],
|
||||||
})
|
})
|
||||||
export class UsersModule {}
|
export class UsersModule {}
|
||||||
|
|
Loading…
Reference in New Issue