Implement the delete GRPC command
This commit is contained in:
		
							parent
							
								
									b17fc32a12
								
							
						
					
					
						commit
						e8903099d7
					
				| 
						 | 
				
			
			@ -7,6 +7,8 @@ export const GRPC_SERVICE_NAME = 'AdService';
 | 
			
		|||
 | 
			
		||||
// messaging output
 | 
			
		||||
export const AD_CREATED_ROUTING_KEY = 'ad.created';
 | 
			
		||||
// messaging output
 | 
			
		||||
export const AD_DELETED_ROUTING_KEY = 'ad.deleted';
 | 
			
		||||
 | 
			
		||||
// messaging input
 | 
			
		||||
export const MATCHER_AD_CREATED_MESSAGE_HANDLER = 'matcherAdCreated';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
import { MessageBrokerPublisher } from '@mobicoop/message-broker-module';
 | 
			
		||||
import { Module, Provider } from '@nestjs/common';
 | 
			
		||||
import { CreateAdGrpcController } from './interface/grpc-controllers/create-ad.grpc.controller';
 | 
			
		||||
import { CqrsModule } from '@nestjs/cqrs';
 | 
			
		||||
import {
 | 
			
		||||
  AD_MESSAGE_PUBLISHER,
 | 
			
		||||
| 
						 | 
				
			
			@ -9,29 +9,33 @@ import {
 | 
			
		|||
  TIMEZONE_FINDER,
 | 
			
		||||
  TIME_CONVERTER,
 | 
			
		||||
} from './ad.di-tokens';
 | 
			
		||||
import { AdRepository } from './infrastructure/ad.repository';
 | 
			
		||||
import { AdMapper } from './ad.mapper';
 | 
			
		||||
import { CreateAdService } from './core/application/commands/create-ad/create-ad.service';
 | 
			
		||||
import { TimezoneFinder } from './infrastructure/timezone-finder';
 | 
			
		||||
import { TimeConverter } from './infrastructure/time-converter';
 | 
			
		||||
import { FindAdByIdGrpcController } from './interface/grpc-controllers/find-ad-by-id.grpc.controller';
 | 
			
		||||
import { FindAdByIdQueryHandler } from './core/application/queries/find-ad-by-id/find-ad-by-id.query-handler';
 | 
			
		||||
import { DeleteAdService } from './core/application/commands/delete-ad/delete-ad.service';
 | 
			
		||||
import { InvalidateAdService } from './core/application/commands/invalidate-ad/invalidate-ad.service';
 | 
			
		||||
import { ValidateAdService } from './core/application/commands/validate-ad/validate-ad.service';
 | 
			
		||||
import { PublishMessageWhenAdIsDeletedDomainEventHandler } from './core/application/event-handlers/publish-message-when-ad-deleted.domain-event-handler';
 | 
			
		||||
import { PublishMessageWhenAdIsCreatedDomainEventHandler } from './core/application/event-handlers/publish-message-when-ad-is-created.domain-event-handler';
 | 
			
		||||
import { PrismaService } from './infrastructure/prisma.service';
 | 
			
		||||
import { MessageBrokerPublisher } from '@mobicoop/message-broker-module';
 | 
			
		||||
import { FindAdByIdQueryHandler } from './core/application/queries/find-ad-by-id/find-ad-by-id.query-handler';
 | 
			
		||||
import { FindAdsByIdsQueryHandler } from './core/application/queries/find-ads-by-ids/find-ads-by-ids.query-handler';
 | 
			
		||||
import { FindAdsByUserIdQueryHandler } from './core/application/queries/find-ads-by-user-id/find-ads-by-user-id.query-handler';
 | 
			
		||||
import { AdRepository } from './infrastructure/ad.repository';
 | 
			
		||||
import { InputDateTimeTransformer } from './infrastructure/input-datetime-transformer';
 | 
			
		||||
import { OutputDateTimeTransformer } from './infrastructure/output-datetime-transformer';
 | 
			
		||||
import { PrismaService } from './infrastructure/prisma.service';
 | 
			
		||||
import { TimeConverter } from './infrastructure/time-converter';
 | 
			
		||||
import { TimezoneFinder } from './infrastructure/timezone-finder';
 | 
			
		||||
import { CreateAdGrpcController } from './interface/grpc-controllers/create-ad.grpc.controller';
 | 
			
		||||
import { DeleteAdGrpcController } from './interface/grpc-controllers/delete-ad.grpc.controller';
 | 
			
		||||
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 { FindAdsByIdsQueryHandler } from './core/application/queries/find-ads-by-ids/find-ads-by-ids.query-handler';
 | 
			
		||||
import { MatcherAdCreatedMessageHandler } from './interface/message-handlers/matcher-ad-created.message-handler';
 | 
			
		||||
import { ValidateAdService } from './core/application/commands/validate-ad/validate-ad.service';
 | 
			
		||||
import { MatcherAdCreationFailedMessageHandler } from './interface/message-handlers/matcher-ad-creation-failed.message-handler';
 | 
			
		||||
import { InvalidateAdService } from './core/application/commands/invalidate-ad/invalidate-ad.service';
 | 
			
		||||
import { FindAdsByUserIdGrpcController } from './interface/grpc-controllers/find-ads-by-user-id.grpc.controller';
 | 
			
		||||
import { FindAdsByUserIdQueryHandler } from './core/application/queries/find-ads-by-user-id/find-ads-by-user-id.query-handler';
 | 
			
		||||
import { MatcherAdCreatedMessageHandler } from './interface/message-handlers/matcher-ad-created.message-handler';
 | 
			
		||||
import { MatcherAdCreationFailedMessageHandler } from './interface/message-handlers/matcher-ad-creation-failed.message-handler';
 | 
			
		||||
 | 
			
		||||
const grpcControllers = [
 | 
			
		||||
  CreateAdGrpcController,
 | 
			
		||||
  DeleteAdGrpcController,
 | 
			
		||||
  FindAdByIdGrpcController,
 | 
			
		||||
  FindAdsByIdsGrpcController,
 | 
			
		||||
  FindAdsByUserIdGrpcController,
 | 
			
		||||
| 
						 | 
				
			
			@ -44,10 +48,12 @@ const messageHandlers = [
 | 
			
		|||
 | 
			
		||||
const eventHandlers: Provider[] = [
 | 
			
		||||
  PublishMessageWhenAdIsCreatedDomainEventHandler,
 | 
			
		||||
  PublishMessageWhenAdIsDeletedDomainEventHandler,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const commandHandlers: Provider[] = [
 | 
			
		||||
  CreateAdService,
 | 
			
		||||
  DeleteAdService,
 | 
			
		||||
  ValidateAdService,
 | 
			
		||||
  InvalidateAdService,
 | 
			
		||||
];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
import { Command, CommandProps } from '@mobicoop/ddd-library';
 | 
			
		||||
 | 
			
		||||
export class DeleteAdCommand extends Command {
 | 
			
		||||
  constructor(props: CommandProps<DeleteAdCommand>) {
 | 
			
		||||
    super(props);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
import { AD_REPOSITORY } from '@modules/ad/ad.di-tokens';
 | 
			
		||||
import { Inject } from '@nestjs/common';
 | 
			
		||||
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
 | 
			
		||||
import { AdRepositoryPort } from '../../ports/ad.repository.port';
 | 
			
		||||
import { DeleteAdCommand } from './delete-ad.command';
 | 
			
		||||
 | 
			
		||||
@CommandHandler(DeleteAdCommand)
 | 
			
		||||
export class DeleteAdService implements ICommandHandler {
 | 
			
		||||
  constructor(
 | 
			
		||||
    @Inject(AD_REPOSITORY) private readonly adRepository: AdRepositoryPort,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  async execute(command: DeleteAdCommand): Promise<boolean> {
 | 
			
		||||
    const ad = await this.adRepository.findOneById(command.id);
 | 
			
		||||
    ad.delete();
 | 
			
		||||
    return this.adRepository.delete(ad);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import { MessagePublisherPort } from '@mobicoop/ddd-library';
 | 
			
		||||
import { AD_MESSAGE_PUBLISHER } from '@modules/ad/ad.di-tokens';
 | 
			
		||||
import { Inject, Injectable } from '@nestjs/common';
 | 
			
		||||
import { OnEvent } from '@nestjs/event-emitter';
 | 
			
		||||
import { AD_DELETED_ROUTING_KEY } from '@src/app.constants';
 | 
			
		||||
import { AdDeletedDomainEvent } from '../../domain/events/ad-delete.domain-event';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class PublishMessageWhenAdIsDeletedDomainEventHandler {
 | 
			
		||||
  constructor(
 | 
			
		||||
    @Inject(AD_MESSAGE_PUBLISHER)
 | 
			
		||||
    private readonly messagePublisher: MessagePublisherPort,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  @OnEvent(AdDeletedDomainEvent.name, { async: true, promisify: true })
 | 
			
		||||
  async handle(event: AdDeletedDomainEvent): Promise<void> {
 | 
			
		||||
    this.messagePublisher.publish(
 | 
			
		||||
      AD_DELETED_ROUTING_KEY,
 | 
			
		||||
      JSON.stringify(event),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,12 +1,13 @@
 | 
			
		|||
import { AggregateRoot, AggregateID } from '@mobicoop/ddd-library';
 | 
			
		||||
import { AggregateID, AggregateRoot } from '@mobicoop/ddd-library';
 | 
			
		||||
import { v4 } from 'uuid';
 | 
			
		||||
import { AdCreatedDomainEvent } from './events/ad-created.domain-event';
 | 
			
		||||
import { AdProps, CreateAdProps, Status } from './ad.types';
 | 
			
		||||
import { ScheduleItemProps } from './value-objects/schedule-item.value-object';
 | 
			
		||||
import { WaypointProps } from './value-objects/waypoint.value-object';
 | 
			
		||||
import { AdValidatedDomainEvent } from './events/ad-validated.domain-event';
 | 
			
		||||
import { AdCreatedDomainEvent } from './events/ad-created.domain-event';
 | 
			
		||||
import { AdDeletedDomainEvent } from './events/ad-delete.domain-event';
 | 
			
		||||
import { AdInvalidatedDomainEvent } from './events/ad-invalidated.domain-event';
 | 
			
		||||
import { AdSuspendedDomainEvent } from './events/ad-suspended.domain-event';
 | 
			
		||||
import { AdValidatedDomainEvent } from './events/ad-validated.domain-event';
 | 
			
		||||
import { ScheduleItemProps } from './value-objects/schedule-item.value-object';
 | 
			
		||||
import { WaypointProps } from './value-objects/waypoint.value-object';
 | 
			
		||||
 | 
			
		||||
export class AdEntity extends AggregateRoot<AdProps> {
 | 
			
		||||
  protected readonly _id: AggregateID;
 | 
			
		||||
| 
						 | 
				
			
			@ -95,6 +96,14 @@ export class AdEntity extends AggregateRoot<AdProps> {
 | 
			
		|||
    return this;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  delete(): void {
 | 
			
		||||
    this.addEvent(
 | 
			
		||||
      new AdDeletedDomainEvent({
 | 
			
		||||
        aggregateId: this.id,
 | 
			
		||||
      }),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  validate(): void {
 | 
			
		||||
    // entity business rules validation to protect it's invariant before saving entity to a database
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library';
 | 
			
		||||
 | 
			
		||||
export class AdDeletedDomainEvent extends DomainEvent {
 | 
			
		||||
  constructor(props: DomainEventProps<AdDeletedDomainEvent>) {
 | 
			
		||||
    super(props);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
import {
 | 
			
		||||
  DatabaseErrorException,
 | 
			
		||||
  NotFoundException,
 | 
			
		||||
  RpcExceptionCode,
 | 
			
		||||
  RpcValidationPipe,
 | 
			
		||||
} from '@mobicoop/ddd-library';
 | 
			
		||||
import { DeleteAdCommand } from '@modules/ad/core/application/commands/delete-ad/delete-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 { DeleteAdRequestDto } from './dtos/delete-ad.request.dto';
 | 
			
		||||
 | 
			
		||||
@UsePipes(
 | 
			
		||||
  new RpcValidationPipe({
 | 
			
		||||
    whitelist: false,
 | 
			
		||||
    forbidUnknownValues: false,
 | 
			
		||||
  }),
 | 
			
		||||
)
 | 
			
		||||
@Controller()
 | 
			
		||||
export class DeleteAdGrpcController {
 | 
			
		||||
  constructor(private readonly commandBus: CommandBus) {}
 | 
			
		||||
 | 
			
		||||
  @GrpcMethod(GRPC_SERVICE_NAME, 'Delete')
 | 
			
		||||
  async delete(data: DeleteAdRequestDto): Promise<void> {
 | 
			
		||||
    try {
 | 
			
		||||
      await this.commandBus.execute(new DeleteAdCommand(data));
 | 
			
		||||
    } catch (error: any) {
 | 
			
		||||
      if (error instanceof NotFoundException)
 | 
			
		||||
        throw new RpcException({
 | 
			
		||||
          code: RpcExceptionCode.NOT_FOUND,
 | 
			
		||||
          message: error.message,
 | 
			
		||||
        });
 | 
			
		||||
      if (error instanceof DatabaseErrorException)
 | 
			
		||||
        throw new RpcException({
 | 
			
		||||
          code: RpcExceptionCode.INTERNAL,
 | 
			
		||||
          message: error.message,
 | 
			
		||||
        });
 | 
			
		||||
      throw new RpcException({
 | 
			
		||||
        code: RpcExceptionCode.UNKNOWN,
 | 
			
		||||
        message: error.message,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
import { IsNotEmpty, IsString } from 'class-validator';
 | 
			
		||||
 | 
			
		||||
export class DeleteAdRequestDto {
 | 
			
		||||
  @IsString()
 | 
			
		||||
  @IsNotEmpty()
 | 
			
		||||
  id: string;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
import { CreateAdProps, Frequency } from '@modules/ad/core/domain/ad.types';
 | 
			
		||||
import { WaypointProps } from '@modules/ad/core/domain/value-objects/waypoint.value-object';
 | 
			
		||||
 | 
			
		||||
const originWaypointProps: WaypointProps = {
 | 
			
		||||
  position: 0,
 | 
			
		||||
  address: {
 | 
			
		||||
    houseNumber: '5',
 | 
			
		||||
    street: 'Avenue Foch',
 | 
			
		||||
    locality: 'Nancy',
 | 
			
		||||
    postalCode: '54000',
 | 
			
		||||
    country: 'France',
 | 
			
		||||
    coordinates: {
 | 
			
		||||
      lat: 48.689445,
 | 
			
		||||
      lon: 6.17651,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
const destinationWaypointProps: WaypointProps = {
 | 
			
		||||
  position: 1,
 | 
			
		||||
  address: {
 | 
			
		||||
    locality: 'Paris',
 | 
			
		||||
    postalCode: '75000',
 | 
			
		||||
    country: 'France',
 | 
			
		||||
    coordinates: {
 | 
			
		||||
      lat: 48.8566,
 | 
			
		||||
      lon: 2.3522,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
const baseCreateAdProps = {
 | 
			
		||||
  userId: 'e8fe64b1-4c33-49e1-9f69-4db48b21df36',
 | 
			
		||||
  seatsProposed: 3,
 | 
			
		||||
  seatsRequested: 1,
 | 
			
		||||
  strict: false,
 | 
			
		||||
  waypoints: [originWaypointProps, destinationWaypointProps],
 | 
			
		||||
};
 | 
			
		||||
const punctualCreateAdProps = {
 | 
			
		||||
  fromDate: '2023-06-22',
 | 
			
		||||
  toDate: '2023-06-22',
 | 
			
		||||
  schedule: [
 | 
			
		||||
    {
 | 
			
		||||
      time: '08:30',
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
  frequency: Frequency.PUNCTUAL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function punctualPassengerCreateAdProps(): CreateAdProps {
 | 
			
		||||
  return {
 | 
			
		||||
    ...baseCreateAdProps,
 | 
			
		||||
    ...punctualCreateAdProps,
 | 
			
		||||
    driver: false,
 | 
			
		||||
    passenger: true,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
import { AD_REPOSITORY } from '@modules/ad/ad.di-tokens';
 | 
			
		||||
import { DeleteAdCommand } from '@modules/ad/core/application/commands/delete-ad/delete-ad.command';
 | 
			
		||||
import { DeleteAdService } from '@modules/ad/core/application/commands/delete-ad/delete-ad.service';
 | 
			
		||||
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
 | 
			
		||||
import { Test, TestingModule } from '@nestjs/testing';
 | 
			
		||||
import { punctualPassengerCreateAdProps } from './ad.fixtures';
 | 
			
		||||
 | 
			
		||||
const ad: AdEntity = AdEntity.create(punctualPassengerCreateAdProps());
 | 
			
		||||
jest.spyOn(ad, 'delete');
 | 
			
		||||
 | 
			
		||||
const mockAdRepository = {
 | 
			
		||||
  findOneById: jest.fn().mockImplementation(() => ad),
 | 
			
		||||
  delete: jest.fn(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('delete-ad.service', () => {
 | 
			
		||||
  let deleteAdService: DeleteAdService;
 | 
			
		||||
 | 
			
		||||
  beforeAll(async () => {
 | 
			
		||||
    const module: TestingModule = await Test.createTestingModule({
 | 
			
		||||
      providers: [
 | 
			
		||||
        {
 | 
			
		||||
          provide: AD_REPOSITORY,
 | 
			
		||||
          useValue: mockAdRepository,
 | 
			
		||||
        },
 | 
			
		||||
        DeleteAdService,
 | 
			
		||||
      ],
 | 
			
		||||
    }).compile();
 | 
			
		||||
 | 
			
		||||
    deleteAdService = module.get<DeleteAdService>(DeleteAdService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be defined', () => {
 | 
			
		||||
    expect(deleteAdService).toBeDefined();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should trigger the delete logic and delete the ad from the repository', async () => {
 | 
			
		||||
    await deleteAdService.execute(new DeleteAdCommand({ id: ad.id }));
 | 
			
		||||
    expect(ad.delete).toHaveBeenCalled();
 | 
			
		||||
    expect(mockAdRepository.delete).toHaveBeenCalledWith(ad);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -1,62 +1,11 @@
 | 
			
		|||
import { AD_REPOSITORY } from '@modules/ad/ad.di-tokens';
 | 
			
		||||
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
 | 
			
		||||
import { CreateAdProps, Frequency } from '@modules/ad/core/domain/ad.types';
 | 
			
		||||
import { FindAdByIdQuery } from '@modules/ad/core/application/queries/find-ad-by-id/find-ad-by-id.query';
 | 
			
		||||
import { FindAdByIdQueryHandler } from '@modules/ad/core/application/queries/find-ad-by-id/find-ad-by-id.query-handler';
 | 
			
		||||
import { WaypointProps } from '@modules/ad/core/domain/value-objects/waypoint.value-object';
 | 
			
		||||
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
 | 
			
		||||
import { Test, TestingModule } from '@nestjs/testing';
 | 
			
		||||
import { punctualPassengerCreateAdProps } from './ad.fixtures';
 | 
			
		||||
 | 
			
		||||
const originWaypointProps: WaypointProps = {
 | 
			
		||||
  position: 0,
 | 
			
		||||
  address: {
 | 
			
		||||
    houseNumber: '5',
 | 
			
		||||
    street: 'Avenue Foch',
 | 
			
		||||
    locality: 'Nancy',
 | 
			
		||||
    postalCode: '54000',
 | 
			
		||||
    country: 'France',
 | 
			
		||||
    coordinates: {
 | 
			
		||||
      lat: 48.689445,
 | 
			
		||||
      lon: 6.17651,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
const destinationWaypointProps: WaypointProps = {
 | 
			
		||||
  position: 1,
 | 
			
		||||
  address: {
 | 
			
		||||
    locality: 'Paris',
 | 
			
		||||
    postalCode: '75000',
 | 
			
		||||
    country: 'France',
 | 
			
		||||
    coordinates: {
 | 
			
		||||
      lat: 48.8566,
 | 
			
		||||
      lon: 2.3522,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
const baseCreateAdProps = {
 | 
			
		||||
  userId: 'e8fe64b1-4c33-49e1-9f69-4db48b21df36',
 | 
			
		||||
  seatsProposed: 3,
 | 
			
		||||
  seatsRequested: 1,
 | 
			
		||||
  strict: false,
 | 
			
		||||
  waypoints: [originWaypointProps, destinationWaypointProps],
 | 
			
		||||
};
 | 
			
		||||
const punctualCreateAdProps = {
 | 
			
		||||
  fromDate: '2023-06-22',
 | 
			
		||||
  toDate: '2023-06-22',
 | 
			
		||||
  schedule: [
 | 
			
		||||
    {
 | 
			
		||||
      time: '08:30',
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
  frequency: Frequency.PUNCTUAL,
 | 
			
		||||
};
 | 
			
		||||
const punctualPassengerCreateAdProps: CreateAdProps = {
 | 
			
		||||
  ...baseCreateAdProps,
 | 
			
		||||
  ...punctualCreateAdProps,
 | 
			
		||||
  driver: false,
 | 
			
		||||
  passenger: true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const ad: AdEntity = AdEntity.create(punctualPassengerCreateAdProps);
 | 
			
		||||
const ad: AdEntity = AdEntity.create(punctualPassengerCreateAdProps());
 | 
			
		||||
 | 
			
		||||
const mockAdRepository = {
 | 
			
		||||
  findOneById: jest.fn().mockImplementation(() => ad),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
import { DeleteAdGrpcController } from '@modules/ad/interface/grpc-controllers/delete-ad.grpc.controller';
 | 
			
		||||
import { CommandBus } from '@nestjs/cqrs';
 | 
			
		||||
import { Test, TestingModule } from '@nestjs/testing';
 | 
			
		||||
 | 
			
		||||
const mockCommandBus = {
 | 
			
		||||
  execute: jest.fn(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('Delete Ad Grpc Controller', () => {
 | 
			
		||||
  let deleteAdGrpcController: DeleteAdGrpcController;
 | 
			
		||||
 | 
			
		||||
  beforeAll(async () => {
 | 
			
		||||
    const module: TestingModule = await Test.createTestingModule({
 | 
			
		||||
      providers: [
 | 
			
		||||
        {
 | 
			
		||||
          provide: CommandBus,
 | 
			
		||||
          useValue: mockCommandBus,
 | 
			
		||||
        },
 | 
			
		||||
        DeleteAdGrpcController,
 | 
			
		||||
      ],
 | 
			
		||||
    }).compile();
 | 
			
		||||
 | 
			
		||||
    deleteAdGrpcController = module.get<DeleteAdGrpcController>(
 | 
			
		||||
      DeleteAdGrpcController,
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  afterEach(async () => {
 | 
			
		||||
    jest.clearAllMocks();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be defined', () => {
 | 
			
		||||
    expect(deleteAdGrpcController).toBeDefined();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should execute the delete ad command', async () => {
 | 
			
		||||
    await deleteAdGrpcController.delete({
 | 
			
		||||
      id: '200d61a8-d878-4378-a609-c19ea71633d2',
 | 
			
		||||
    });
 | 
			
		||||
    expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
		Loading…
	
		Reference in New Issue