Implement the GRPC controller to update ads
This commit is contained in:
parent
7a84bff260
commit
659c1baea8
|
@ -33,12 +33,14 @@ import { DeleteAdGrpcController } from './interface/grpc-controllers/delete-ad.g
|
|||
import { FindAdByIdGrpcController } from './interface/grpc-controllers/find-ad-by-id.grpc.controller';
|
||||
import { FindAdsByIdsGrpcController } from './interface/grpc-controllers/find-ads-by-ids.grpc.controller';
|
||||
import { FindAdsByUserIdGrpcController } from './interface/grpc-controllers/find-ads-by-user-id.grpc.controller';
|
||||
import { UpdateAdGrpcController } from './interface/grpc-controllers/update-ad.grpc.controller';
|
||||
import { MatcherAdCreatedMessageHandler } from './interface/message-handlers/matcher-ad-created.message-handler';
|
||||
import { MatcherAdCreationFailedMessageHandler } from './interface/message-handlers/matcher-ad-creation-failed.message-handler';
|
||||
import { UserDeletedMessageHandler } from './interface/message-handlers/user-deleted.message-handler';
|
||||
|
||||
const grpcControllers = [
|
||||
CreateAdGrpcController,
|
||||
UpdateAdGrpcController,
|
||||
DeleteAdGrpcController,
|
||||
FindAdByIdGrpcController,
|
||||
FindAdsByIdsGrpcController,
|
||||
|
|
|
@ -7,7 +7,7 @@ service AdService {
|
|||
rpc FindAllByIds(AdsById) returns (Ads);
|
||||
rpc FindAllByUserId(UserById) returns (Ads);
|
||||
rpc Create(Ad) returns (AdById);
|
||||
rpc Update(Ad) returns (Ad);
|
||||
rpc Update(Ad) returns (Empty);
|
||||
rpc Delete(AdById) returns (Empty);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import { IsUUID } from 'class-validator';
|
||||
import { CreateAdRequestDto } from './create-ad.request.dto';
|
||||
|
||||
export class UpdateAdRequestDto extends CreateAdRequestDto {
|
||||
@IsUUID(4)
|
||||
id: string;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
import {
|
||||
NotFoundException,
|
||||
RpcExceptionCode,
|
||||
RpcValidationPipe,
|
||||
} from '@mobicoop/ddd-library';
|
||||
import { UpdateAdCommand } from '@modules/ad/core/application/commands/update-ad/update-ad.command';
|
||||
import { Controller, UsePipes } from '@nestjs/common';
|
||||
import { CommandBus } from '@nestjs/cqrs';
|
||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||
import { GRPC_SERVICE_NAME } from '@src/app.constants';
|
||||
import { UpdateAdRequestDto } from './dtos/update-ad.request.dto';
|
||||
|
||||
@UsePipes(
|
||||
new RpcValidationPipe({
|
||||
whitelist: false,
|
||||
forbidUnknownValues: false,
|
||||
}),
|
||||
)
|
||||
@Controller()
|
||||
export class UpdateAdGrpcController {
|
||||
constructor(private readonly commandBus: CommandBus) {}
|
||||
|
||||
@GrpcMethod(GRPC_SERVICE_NAME, 'Update')
|
||||
async update(data: UpdateAdRequestDto): Promise<void> {
|
||||
try {
|
||||
const cmdProps = {
|
||||
adId: data.id,
|
||||
...data,
|
||||
};
|
||||
delete (cmdProps as { id?: string }).id;
|
||||
|
||||
await this.commandBus.execute(new UpdateAdCommand(cmdProps));
|
||||
} catch (error) {
|
||||
if (error instanceof NotFoundException) {
|
||||
throw new RpcException({
|
||||
code: RpcExceptionCode.NOT_FOUND,
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
||||
import { CreateAdRequestDto } from '@modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto';
|
||||
import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto';
|
||||
|
||||
const originWaypoint: WaypointDto = {
|
||||
position: 0,
|
||||
lat: 48.689445,
|
||||
lon: 6.17651,
|
||||
houseNumber: '5',
|
||||
street: 'Avenue Foch',
|
||||
locality: 'Nancy',
|
||||
postalCode: '54000',
|
||||
country: 'France',
|
||||
};
|
||||
const destinationWaypoint: WaypointDto = {
|
||||
position: 1,
|
||||
lat: 48.8566,
|
||||
lon: 2.3522,
|
||||
locality: 'Paris',
|
||||
postalCode: '75000',
|
||||
country: 'France',
|
||||
};
|
||||
export function punctualCreateAdRequest(): CreateAdRequestDto {
|
||||
return {
|
||||
userId: '4eb6a6af-ecfd-41c3-9118-473a507014d4',
|
||||
fromDate: '2023-12-21',
|
||||
toDate: '2023-12-21',
|
||||
schedule: [
|
||||
{
|
||||
time: '08:15',
|
||||
day: 4,
|
||||
margin: 600,
|
||||
},
|
||||
],
|
||||
driver: false,
|
||||
passenger: true,
|
||||
seatsRequested: 1,
|
||||
seatsProposed: 3,
|
||||
strict: false,
|
||||
frequency: Frequency.PUNCTUAL,
|
||||
waypoints: [originWaypoint, destinationWaypoint],
|
||||
};
|
||||
}
|
|
@ -1,51 +1,10 @@
|
|||
import { IdResponse } from '@mobicoop/ddd-library';
|
||||
import { RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||
import { IdResponse, RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||
import { AdAlreadyExistsException } from '@modules/ad/core/domain/ad.errors';
|
||||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
||||
import { CreateAdGrpcController } from '@modules/ad/interface/grpc-controllers/create-ad.grpc.controller';
|
||||
import { CreateAdRequestDto } from '@modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto';
|
||||
import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto';
|
||||
import { CommandBus } from '@nestjs/cqrs';
|
||||
import { RpcException } from '@nestjs/microservices';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
const originWaypoint: WaypointDto = {
|
||||
position: 0,
|
||||
lat: 48.689445,
|
||||
lon: 6.17651,
|
||||
houseNumber: '5',
|
||||
street: 'Avenue Foch',
|
||||
locality: 'Nancy',
|
||||
postalCode: '54000',
|
||||
country: 'France',
|
||||
};
|
||||
const destinationWaypoint: WaypointDto = {
|
||||
position: 1,
|
||||
lat: 48.8566,
|
||||
lon: 2.3522,
|
||||
locality: 'Paris',
|
||||
postalCode: '75000',
|
||||
country: 'France',
|
||||
};
|
||||
const punctualCreateAdRequest: CreateAdRequestDto = {
|
||||
userId: '4eb6a6af-ecfd-41c3-9118-473a507014d4',
|
||||
fromDate: '2023-12-21',
|
||||
toDate: '2023-12-21',
|
||||
schedule: [
|
||||
{
|
||||
time: '08:15',
|
||||
day: 4,
|
||||
margin: 600,
|
||||
},
|
||||
],
|
||||
driver: false,
|
||||
passenger: true,
|
||||
seatsRequested: 1,
|
||||
seatsProposed: 3,
|
||||
strict: false,
|
||||
frequency: Frequency.PUNCTUAL,
|
||||
waypoints: [originWaypoint, destinationWaypoint],
|
||||
};
|
||||
import { punctualCreateAdRequest } from './ad.fixtures';
|
||||
|
||||
const mockCommandBus = {
|
||||
execute: jest
|
||||
|
@ -89,7 +48,7 @@ describe('Create Ad Grpc Controller', () => {
|
|||
it('should create a new ad', async () => {
|
||||
jest.spyOn(mockCommandBus, 'execute');
|
||||
const result: IdResponse = await createAdGrpcController.create(
|
||||
punctualCreateAdRequest,
|
||||
punctualCreateAdRequest(),
|
||||
);
|
||||
expect(result).toBeInstanceOf(IdResponse);
|
||||
expect(result.id).toBe('200d61a8-d878-4378-a609-c19ea71633d2');
|
||||
|
@ -100,7 +59,7 @@ describe('Create Ad Grpc Controller', () => {
|
|||
jest.spyOn(mockCommandBus, 'execute');
|
||||
expect.assertions(3);
|
||||
try {
|
||||
await createAdGrpcController.create(punctualCreateAdRequest);
|
||||
await createAdGrpcController.create(punctualCreateAdRequest());
|
||||
} catch (e: any) {
|
||||
expect(e).toBeInstanceOf(RpcException);
|
||||
expect(e.error.code).toBe(RpcExceptionCode.ALREADY_EXISTS);
|
||||
|
@ -112,7 +71,7 @@ describe('Create Ad Grpc Controller', () => {
|
|||
jest.spyOn(mockCommandBus, 'execute');
|
||||
expect.assertions(3);
|
||||
try {
|
||||
await createAdGrpcController.create(punctualCreateAdRequest);
|
||||
await createAdGrpcController.create(punctualCreateAdRequest());
|
||||
} catch (e: any) {
|
||||
expect(e).toBeInstanceOf(RpcException);
|
||||
expect(e.error.code).toBe(RpcExceptionCode.UNKNOWN);
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import { NotFoundException, RpcExceptionCode } from '@mobicoop/ddd-library';
|
||||
import { UpdateAdGrpcController } from '@modules/ad/interface/grpc-controllers/update-ad.grpc.controller';
|
||||
import { CommandBus } from '@nestjs/cqrs';
|
||||
import { RpcException } from '@nestjs/microservices';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { punctualCreateAdRequest } from './ad.fixtures';
|
||||
|
||||
const validAdId = '200d61a8-d878-4378-a609-c19ea71633d2';
|
||||
const mockCommandBus = {
|
||||
execute: jest.fn().mockImplementation(async (command) => {
|
||||
if (command.adId === '') throw 'Ad id is empty';
|
||||
if (command.adId != validAdId) throw new NotFoundException();
|
||||
}),
|
||||
};
|
||||
|
||||
describe('Update Ad GRPC Controller', () => {
|
||||
let updateAdGrpcController: UpdateAdGrpcController;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
{
|
||||
provide: CommandBus,
|
||||
useValue: mockCommandBus,
|
||||
},
|
||||
UpdateAdGrpcController,
|
||||
],
|
||||
}).compile();
|
||||
updateAdGrpcController = module.get<UpdateAdGrpcController>(
|
||||
UpdateAdGrpcController,
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(updateAdGrpcController).toBeDefined();
|
||||
});
|
||||
|
||||
it('should execute the update ad command', async () => {
|
||||
await updateAdGrpcController.update({
|
||||
id: validAdId,
|
||||
...punctualCreateAdRequest(),
|
||||
});
|
||||
expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should throw a dedicated RpcException if ad is not found', async () => {
|
||||
expect.assertions(3);
|
||||
try {
|
||||
await updateAdGrpcController.update({
|
||||
id: 'ac85f5f4-41cd-4c5d-9aee-0a1acb176fb8',
|
||||
...punctualCreateAdRequest(),
|
||||
});
|
||||
} catch (e: any) {
|
||||
expect(e).toBeInstanceOf(RpcException);
|
||||
expect(e.error.code).toBe(RpcExceptionCode.NOT_FOUND);
|
||||
}
|
||||
expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should rethrow any other exceptions', async () => {
|
||||
expect.assertions(2);
|
||||
try {
|
||||
await updateAdGrpcController.update({
|
||||
id: '',
|
||||
...punctualCreateAdRequest(),
|
||||
});
|
||||
} catch (e: any) {
|
||||
expect(e).toBe('Ad id is empty');
|
||||
}
|
||||
expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue