divide admodel to support different read-write models
This commit is contained in:
parent
1989ff6e67
commit
65f9ed4172
|
@ -12,20 +12,22 @@ import { ConflictException, DatabaseErrorException } from '@libs/exceptions';
|
||||||
|
|
||||||
export abstract class PrismaRepositoryBase<
|
export abstract class PrismaRepositoryBase<
|
||||||
Aggregate extends AggregateRoot<any>,
|
Aggregate extends AggregateRoot<any>,
|
||||||
DbModel extends ObjectLiteral,
|
DbReadModel extends ObjectLiteral,
|
||||||
|
DbWriteModel extends ObjectLiteral,
|
||||||
> implements RepositoryPort<Aggregate>
|
> implements RepositoryPort<Aggregate>
|
||||||
{
|
{
|
||||||
protected constructor(
|
protected constructor(
|
||||||
protected readonly prisma: PrismaRepositoryPort<Aggregate> | any,
|
protected readonly prisma: PrismaRepositoryPort<Aggregate> | any,
|
||||||
protected readonly prismaRaw: PrismaRawRepositoryPort,
|
protected readonly prismaRaw: PrismaRawRepositoryPort,
|
||||||
protected readonly mapper: Mapper<Aggregate, DbModel>,
|
protected readonly mapper: Mapper<Aggregate, DbReadModel, DbWriteModel>,
|
||||||
protected readonly eventEmitter: EventEmitter2,
|
protected readonly eventEmitter: EventEmitter2,
|
||||||
protected readonly logger: LoggerPort,
|
protected readonly logger: LoggerPort,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async findOneById(id: string): Promise<Option<Aggregate>> {
|
async findOneById(id: string, include?: any): Promise<Option<Aggregate>> {
|
||||||
const entity = await this.prisma.findUnique({
|
const entity = await this.prisma.findUnique({
|
||||||
where: { uuid: id },
|
where: { uuid: id },
|
||||||
|
include,
|
||||||
});
|
});
|
||||||
return entity ? Some(this.mapper.toDomain(entity)) : None;
|
return entity ? Some(this.mapper.toDomain(entity)) : None;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +49,7 @@ export abstract class PrismaRepositoryBase<
|
||||||
|
|
||||||
async healthCheck(): Promise<boolean> {
|
async healthCheck(): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
await this.prismaRaw.$queryRaw`SELECT 1`;
|
await this.prisma.$queryRaw`SELECT 1`;
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|
|
@ -2,10 +2,11 @@ import { Entity } from './entity.base';
|
||||||
|
|
||||||
export interface Mapper<
|
export interface Mapper<
|
||||||
DomainEntity extends Entity<any>,
|
DomainEntity extends Entity<any>,
|
||||||
DbRecord,
|
DbReadRecord,
|
||||||
|
DbWriteRecord,
|
||||||
Response = any,
|
Response = any,
|
||||||
> {
|
> {
|
||||||
toPersistence(entity: DomainEntity): DbRecord;
|
toPersistence(entity: DomainEntity): DbWriteRecord;
|
||||||
toDomain(record: any): DomainEntity;
|
toDomain(record: DbReadRecord): DomainEntity;
|
||||||
toResponse(entity: DomainEntity): Response;
|
toResponse(entity: DomainEntity): Response;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,11 @@ import { Mapper } from '@libs/ddd';
|
||||||
import { AdResponseDto } from './interface/dtos/ad.response.dto';
|
import { AdResponseDto } from './interface/dtos/ad.response.dto';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { AdEntity } from './core/ad.entity';
|
import { AdEntity } from './core/ad.entity';
|
||||||
import { AdModel, WaypointModel } from './infrastructure/ad.repository';
|
import {
|
||||||
|
AdWriteModel,
|
||||||
|
AdReadModel,
|
||||||
|
WaypointModel,
|
||||||
|
} from './infrastructure/ad.repository';
|
||||||
import { Frequency } from './core/ad.types';
|
import { Frequency } from './core/ad.types';
|
||||||
import { WaypointProps } from './core/value-objects/waypoint.value-object';
|
import { WaypointProps } from './core/value-objects/waypoint.value-object';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
@ -21,7 +25,9 @@ import { DateTime, TimeZone } from 'timezonecomplete';
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AdMapper implements Mapper<AdEntity, AdModel, AdResponseDto> {
|
export class AdMapper
|
||||||
|
implements Mapper<AdEntity, AdReadModel, AdWriteModel, AdResponseDto>
|
||||||
|
{
|
||||||
private timezone: string;
|
private timezone: string;
|
||||||
private readonly defaultParams: DefaultParams;
|
private readonly defaultParams: DefaultParams;
|
||||||
|
|
||||||
|
@ -34,11 +40,11 @@ export class AdMapper implements Mapper<AdEntity, AdModel, AdResponseDto> {
|
||||||
this.defaultParams = defaultParamsProvider.getParams();
|
this.defaultParams = defaultParamsProvider.getParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
toPersistence = (entity: AdEntity): AdModel => {
|
toPersistence = (entity: AdEntity): AdWriteModel => {
|
||||||
const copy = entity.getProps();
|
const copy = entity.getProps();
|
||||||
const timezone = this.getTimezone(copy.waypoints[0].address.coordinates);
|
const timezone = this.getTimezone(copy.waypoints[0].address.coordinates);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const record: AdModel = {
|
const record: AdWriteModel = {
|
||||||
uuid: copy.id,
|
uuid: copy.id,
|
||||||
userUuid: copy.userId,
|
userUuid: copy.userId,
|
||||||
driver: copy.driver,
|
driver: copy.driver,
|
||||||
|
@ -127,7 +133,7 @@ export class AdMapper implements Mapper<AdEntity, AdModel, AdResponseDto> {
|
||||||
return record;
|
return record;
|
||||||
};
|
};
|
||||||
|
|
||||||
toDomain = (record: AdModel): AdEntity => {
|
toDomain = (record: AdReadModel): AdEntity => {
|
||||||
const entity = new AdEntity({
|
const entity = new AdEntity({
|
||||||
id: record.uuid,
|
id: record.uuid,
|
||||||
createdAt: new Date(record.createdAt),
|
createdAt: new Date(record.createdAt),
|
||||||
|
@ -140,13 +146,13 @@ export class AdMapper implements Mapper<AdEntity, AdModel, AdResponseDto> {
|
||||||
fromDate: record.fromDate.toISOString(),
|
fromDate: record.fromDate.toISOString(),
|
||||||
toDate: record.toDate.toISOString(),
|
toDate: record.toDate.toISOString(),
|
||||||
schedule: {
|
schedule: {
|
||||||
mon: record.monTime.toISOString(),
|
mon: record.monTime?.toISOString(),
|
||||||
tue: record.tueTime.toISOString(),
|
tue: record.tueTime?.toISOString(),
|
||||||
wed: record.wedTime.toISOString(),
|
wed: record.wedTime?.toISOString(),
|
||||||
thu: record.thuTime.toISOString(),
|
thu: record.thuTime?.toISOString(),
|
||||||
fri: record.friTime.toISOString(),
|
fri: record.friTime?.toISOString(),
|
||||||
sat: record.satTime.toISOString(),
|
sat: record.satTime?.toISOString(),
|
||||||
sun: record.sunTime.toISOString(),
|
sun: record.sunTime?.toISOString(),
|
||||||
},
|
},
|
||||||
marginDurations: {
|
marginDurations: {
|
||||||
mon: record.monMargin,
|
mon: record.monMargin,
|
||||||
|
@ -160,7 +166,7 @@ export class AdMapper implements Mapper<AdEntity, AdModel, AdResponseDto> {
|
||||||
seatsProposed: record.seatsProposed,
|
seatsProposed: record.seatsProposed,
|
||||||
seatsRequested: record.seatsRequested,
|
seatsRequested: record.seatsRequested,
|
||||||
strict: record.strict,
|
strict: record.strict,
|
||||||
waypoints: record.waypoints.create.map((waypoint: WaypointModel) => ({
|
waypoints: record.waypoints.map((waypoint: WaypointModel) => ({
|
||||||
position: waypoint.position,
|
position: waypoint.position,
|
||||||
address: {
|
address: {
|
||||||
name: waypoint.name,
|
name: waypoint.name,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { PrismaService } from '@libs/db/prisma.service';
|
||||||
import { AdMapper } from '../ad.mapper';
|
import { AdMapper } from '../ad.mapper';
|
||||||
import { PrismaRepositoryBase } from '@libs/db/prisma-repository.base';
|
import { PrismaRepositoryBase } from '@libs/db/prisma-repository.base';
|
||||||
|
|
||||||
export type AdModel = {
|
export type AdBaseModel = {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
userUuid: string;
|
userUuid: string;
|
||||||
driver: boolean;
|
driver: boolean;
|
||||||
|
@ -31,11 +31,18 @@ export type AdModel = {
|
||||||
seatsProposed: number;
|
seatsProposed: number;
|
||||||
seatsRequested: number;
|
seatsRequested: number;
|
||||||
strict: boolean;
|
strict: boolean;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AdReadModel = AdBaseModel & {
|
||||||
|
waypoints: WaypointModel[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AdWriteModel = AdBaseModel & {
|
||||||
waypoints: {
|
waypoints: {
|
||||||
create: WaypointModel[];
|
create: WaypointModel[];
|
||||||
};
|
};
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WaypointModel = {
|
export type WaypointModel = {
|
||||||
|
@ -58,7 +65,7 @@ export type WaypointModel = {
|
||||||
* */
|
* */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AdRepository
|
export class AdRepository
|
||||||
extends PrismaRepositoryBase<AdEntity, AdModel>
|
extends PrismaRepositoryBase<AdEntity, AdReadModel, AdWriteModel>
|
||||||
implements AdRepositoryPort
|
implements AdRepositoryPort
|
||||||
{
|
{
|
||||||
constructor(
|
constructor(
|
||||||
|
|
|
@ -1,295 +0,0 @@
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
|
||||||
import { CreateAdUseCase } from '../../../core/usecases/create-ad.usecase';
|
|
||||||
import { CreateAdRequestDTO } from '../../../interface/commands/create-ad.request.dto';
|
|
||||||
import { AdsRepository } from '../../../adapters/secondaries/ads.repository';
|
|
||||||
import { CreateAdCommand } from '../../../interface/commands/create-ad.command';
|
|
||||||
import { AutomapperModule } from '@automapper/nestjs';
|
|
||||||
import { classes } from '@automapper/classes';
|
|
||||||
import { Frequency } from '../../../interface/commands/frequency.enum';
|
|
||||||
import { Ad } from '../../../core/entities/ad';
|
|
||||||
import { AdProfile } from '../../../mappers/ad.profile';
|
|
||||||
import { Waypoint } from '../../../interface/commands/waypoint';
|
|
||||||
import { AdDTO } from '../../../core/dtos/ad.dto';
|
|
||||||
import { PARAMS_PROVIDER } from '../../../ad.di-tokens';
|
|
||||||
import { MESSAGE_PUBLISHER } from '../../../../../app.constants';
|
|
||||||
|
|
||||||
const originWaypoint: Waypoint = {
|
|
||||||
position: 0,
|
|
||||||
lon: 48.68944505415954,
|
|
||||||
lat: 6.176510296462267,
|
|
||||||
houseNumber: '5',
|
|
||||||
street: 'Avenue Foch',
|
|
||||||
locality: 'Nancy',
|
|
||||||
postalCode: '54000',
|
|
||||||
country: 'France',
|
|
||||||
};
|
|
||||||
const destinationWaypoint: Waypoint = {
|
|
||||||
position: 1,
|
|
||||||
lon: 48.8566,
|
|
||||||
lat: 2.3522,
|
|
||||||
locality: 'Paris',
|
|
||||||
postalCode: '75000',
|
|
||||||
country: 'France',
|
|
||||||
};
|
|
||||||
const originWaypointWithoutPosition: Waypoint = {
|
|
||||||
lon: 43.2965,
|
|
||||||
lat: 5.3698,
|
|
||||||
locality: 'Marseille',
|
|
||||||
postalCode: '13000',
|
|
||||||
country: 'France',
|
|
||||||
};
|
|
||||||
const destinationWaypointWithoutPosition: Waypoint = {
|
|
||||||
lon: 43.7102,
|
|
||||||
lat: 7.262,
|
|
||||||
locality: 'Nice',
|
|
||||||
postalCode: '06000',
|
|
||||||
country: 'France',
|
|
||||||
};
|
|
||||||
const newAdRequest: CreateAdRequestDTO = {
|
|
||||||
userUuid: '113e0000-0000-4000-a000-000000000000',
|
|
||||||
driver: true,
|
|
||||||
passenger: false,
|
|
||||||
frequency: Frequency.RECURRENT,
|
|
||||||
fromDate: new Date('2023-05-01'),
|
|
||||||
toDate: new Date('2023-08-20'),
|
|
||||||
schedule: {
|
|
||||||
tue: '08:00',
|
|
||||||
wed: '08:30',
|
|
||||||
},
|
|
||||||
marginDurations: {
|
|
||||||
mon: undefined,
|
|
||||||
tue: undefined,
|
|
||||||
wed: undefined,
|
|
||||||
thu: undefined,
|
|
||||||
fri: undefined,
|
|
||||||
sat: undefined,
|
|
||||||
sun: undefined,
|
|
||||||
},
|
|
||||||
seatsProposed: 2,
|
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
|
||||||
};
|
|
||||||
|
|
||||||
const mockMessagePublisher = {
|
|
||||||
publish: jest.fn().mockImplementation(),
|
|
||||||
};
|
|
||||||
const mockDefaultParamsProvider = {
|
|
||||||
getParams: () => {
|
|
||||||
return {
|
|
||||||
MON_MARGIN: 900,
|
|
||||||
TUE_MARGIN: 900,
|
|
||||||
WED_MARGIN: 900,
|
|
||||||
THU_MARGIN: 900,
|
|
||||||
FRI_MARGIN: 900,
|
|
||||||
SAT_MARGIN: 900,
|
|
||||||
SUN_MARGIN: 900,
|
|
||||||
DRIVER: false,
|
|
||||||
SEATS_PROPOSED: 3,
|
|
||||||
PASSENGER: true,
|
|
||||||
SEATS_REQUESTED: 1,
|
|
||||||
STRICT: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const mockAdRepository = {
|
|
||||||
create: jest
|
|
||||||
.fn()
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
.mockImplementationOnce((command?: CreateAdCommand) => {
|
|
||||||
return Promise.resolve({
|
|
||||||
...newAdRequest,
|
|
||||||
uuid: 'ad000000-0000-4000-a000-000000000000',
|
|
||||||
createdAt: new Date('2023-05-01'),
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.mockImplementationOnce(() => {
|
|
||||||
throw new Error('Already exists');
|
|
||||||
})
|
|
||||||
.mockImplementation(),
|
|
||||||
};
|
|
||||||
describe('CreateAdUseCase', () => {
|
|
||||||
let createAdUseCase: CreateAdUseCase;
|
|
||||||
beforeAll(async () => {
|
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
|
||||||
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: AdsRepository,
|
|
||||||
useValue: mockAdRepository,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: MESSAGE_PUBLISHER,
|
|
||||||
useValue: mockMessagePublisher,
|
|
||||||
},
|
|
||||||
CreateAdUseCase,
|
|
||||||
AdProfile,
|
|
||||||
{
|
|
||||||
provide: PARAMS_PROVIDER,
|
|
||||||
useValue: mockDefaultParamsProvider,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
createAdUseCase = module.get<CreateAdUseCase>(CreateAdUseCase);
|
|
||||||
});
|
|
||||||
it('should be defined', () => {
|
|
||||||
expect(createAdUseCase).toBeDefined();
|
|
||||||
});
|
|
||||||
describe('execution', () => {
|
|
||||||
const newAdCommand = new CreateAdCommand(newAdRequest);
|
|
||||||
it('should create a new ad', async () => {
|
|
||||||
const newAd: Ad = await createAdUseCase.execute(newAdCommand);
|
|
||||||
expect(newAd.userUuid).toBe('113e0000-0000-4000-a000-000000000000');
|
|
||||||
expect(newAd.uuid).toBe('ad000000-0000-4000-a000-000000000000');
|
|
||||||
});
|
|
||||||
it('should throw an error if the ad already exists', async () => {
|
|
||||||
await expect(
|
|
||||||
createAdUseCase.execute(newAdCommand),
|
|
||||||
).rejects.toBeInstanceOf(Error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Ad parameter default setting ', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
mockAdRepository.create.mockClear();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should define minimal recurrent ad as passenger', async () => {
|
|
||||||
const minimalRecurrentAdRequest: CreateAdRequestDTO = {
|
|
||||||
userUuid: '224e0000-0000-4000-a000-000000000000',
|
|
||||||
frequency: Frequency.RECURRENT,
|
|
||||||
fromDate: new Date('2023-05-01'),
|
|
||||||
toDate: new Date('2024-05-01'),
|
|
||||||
schedule: {
|
|
||||||
mon: '08:00',
|
|
||||||
},
|
|
||||||
waypoints: [originWaypoint, destinationWaypoint],
|
|
||||||
};
|
|
||||||
const newAdCommand = new CreateAdCommand(minimalRecurrentAdRequest);
|
|
||||||
const expectedAdCreation: AdDTO = {
|
|
||||||
userUuid: '224e0000-0000-4000-a000-000000000000',
|
|
||||||
frequency: Frequency.RECURRENT,
|
|
||||||
fromDate: new Date('2023-05-01'),
|
|
||||||
toDate: new Date('2024-05-01'),
|
|
||||||
monTime: '08:00',
|
|
||||||
tueTime: undefined,
|
|
||||||
wedTime: undefined,
|
|
||||||
thuTime: undefined,
|
|
||||||
friTime: undefined,
|
|
||||||
satTime: undefined,
|
|
||||||
sunTime: undefined,
|
|
||||||
monMargin: 900,
|
|
||||||
tueMargin: 900,
|
|
||||||
wedMargin: 900,
|
|
||||||
thuMargin: 900,
|
|
||||||
friMargin: 900,
|
|
||||||
satMargin: 900,
|
|
||||||
sunMargin: 900,
|
|
||||||
driver: false,
|
|
||||||
seatsProposed: 3,
|
|
||||||
passenger: true,
|
|
||||||
seatsRequested: 1,
|
|
||||||
strict: false,
|
|
||||||
waypoints: {
|
|
||||||
create: [
|
|
||||||
{
|
|
||||||
uuid: undefined,
|
|
||||||
adUuid: undefined,
|
|
||||||
position: 0,
|
|
||||||
lon: 48.68944505415954,
|
|
||||||
lat: 6.176510296462267,
|
|
||||||
houseNumber: '5',
|
|
||||||
street: 'Avenue Foch',
|
|
||||||
locality: 'Nancy',
|
|
||||||
postalCode: '54000',
|
|
||||||
country: 'France',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
uuid: undefined,
|
|
||||||
adUuid: undefined,
|
|
||||||
position: 1,
|
|
||||||
lon: 48.8566,
|
|
||||||
lat: 2.3522,
|
|
||||||
locality: 'Paris',
|
|
||||||
postalCode: '75000',
|
|
||||||
country: 'France',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
createdAt: undefined,
|
|
||||||
};
|
|
||||||
await createAdUseCase.execute(newAdCommand);
|
|
||||||
expect(mockAdRepository.create).toBeCalledWith(expectedAdCreation, {
|
|
||||||
waypoints: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('should create a passenger ad with waypoints without position', async () => {
|
|
||||||
const newPunctualPassengerAdRequest: CreateAdRequestDTO = {
|
|
||||||
userUuid: '113e0000-0000-4000-a000-000000000000',
|
|
||||||
passenger: true,
|
|
||||||
frequency: Frequency.PUNCTUAL,
|
|
||||||
departureDate: new Date('2023-05-22 09:36'),
|
|
||||||
seatsRequested: 1,
|
|
||||||
waypoints: [
|
|
||||||
originWaypointWithoutPosition,
|
|
||||||
destinationWaypointWithoutPosition,
|
|
||||||
],
|
|
||||||
schedule: {},
|
|
||||||
};
|
|
||||||
const newAdCommand = new CreateAdCommand(newPunctualPassengerAdRequest);
|
|
||||||
const expectedAdCreation: AdDTO = {
|
|
||||||
userUuid: '113e0000-0000-4000-a000-000000000000',
|
|
||||||
frequency: Frequency.PUNCTUAL,
|
|
||||||
fromDate: new Date('2023-05-22'),
|
|
||||||
toDate: new Date('2023-05-22'),
|
|
||||||
monTime: '09:36',
|
|
||||||
tueTime: undefined,
|
|
||||||
wedTime: undefined,
|
|
||||||
thuTime: undefined,
|
|
||||||
friTime: undefined,
|
|
||||||
satTime: undefined,
|
|
||||||
sunTime: undefined,
|
|
||||||
monMargin: 900,
|
|
||||||
tueMargin: 900,
|
|
||||||
wedMargin: 900,
|
|
||||||
thuMargin: 900,
|
|
||||||
friMargin: 900,
|
|
||||||
satMargin: 900,
|
|
||||||
sunMargin: 900,
|
|
||||||
driver: false,
|
|
||||||
seatsProposed: 3,
|
|
||||||
passenger: true,
|
|
||||||
seatsRequested: 1,
|
|
||||||
strict: false,
|
|
||||||
waypoints: {
|
|
||||||
create: [
|
|
||||||
{
|
|
||||||
uuid: undefined,
|
|
||||||
adUuid: undefined,
|
|
||||||
position: 0,
|
|
||||||
lon: 43.2965,
|
|
||||||
lat: 5.3698,
|
|
||||||
locality: 'Marseille',
|
|
||||||
postalCode: '13000',
|
|
||||||
country: 'France',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
uuid: undefined,
|
|
||||||
adUuid: undefined,
|
|
||||||
position: 1,
|
|
||||||
lon: 43.7102,
|
|
||||||
lat: 7.262,
|
|
||||||
locality: 'Nice',
|
|
||||||
postalCode: '06000',
|
|
||||||
country: 'France',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
createdAt: undefined,
|
|
||||||
};
|
|
||||||
await createAdUseCase.execute(newAdCommand);
|
|
||||||
expect(mockAdRepository.create).toBeCalledWith(expectedAdCreation, {
|
|
||||||
waypoints: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,71 +0,0 @@
|
||||||
import { NotFoundException } from '@nestjs/common';
|
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
|
||||||
import { FindAdByUuidQuery } from '../../../queries/find-ad-by-uuid.query';
|
|
||||||
import { AdsRepository } from '../../../adapters/secondaries/ads.repository';
|
|
||||||
import { FindAdByIdUseCase } from '../../../core/usecases/find-ad-by-uuid.usecase';
|
|
||||||
import { FindAdByIdRequestDTO } from '../../../interface/queries/find-ad-by-id/dtos/find-ad-by-id.request.dto';
|
|
||||||
import { MESSAGE_PUBLISHER } from '../../../../../app.constants';
|
|
||||||
|
|
||||||
const mockAd = {
|
|
||||||
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
|
||||||
};
|
|
||||||
|
|
||||||
const mockAdRepository = {
|
|
||||||
findOneByUuid: jest
|
|
||||||
.fn()
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
.mockImplementationOnce((query?: FindAdByUuidQuery) => {
|
|
||||||
return Promise.resolve(mockAd);
|
|
||||||
})
|
|
||||||
.mockImplementation(() => {
|
|
||||||
return Promise.resolve(null);
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
const mockMessagePublisher = {
|
|
||||||
publish: jest.fn().mockImplementation(),
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('FindAdByUuidUseCase', () => {
|
|
||||||
let findAdByUuidUseCase: FindAdByIdUseCase;
|
|
||||||
beforeAll(async () => {
|
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
|
||||||
imports: [],
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: AdsRepository,
|
|
||||||
useValue: mockAdRepository,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: MESSAGE_PUBLISHER,
|
|
||||||
useValue: mockMessagePublisher,
|
|
||||||
},
|
|
||||||
FindAdByIdUseCase,
|
|
||||||
],
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
findAdByUuidUseCase = module.get<FindAdByIdUseCase>(FindAdByIdUseCase);
|
|
||||||
});
|
|
||||||
it('should be defined', () => {
|
|
||||||
expect(findAdByUuidUseCase).toBeDefined();
|
|
||||||
});
|
|
||||||
describe('execute', () => {
|
|
||||||
it('should return an ad', async () => {
|
|
||||||
const findAdByUuidRequest: FindAdByIdRequestDTO =
|
|
||||||
new FindAdByIdRequestDTO();
|
|
||||||
findAdByUuidRequest.id = 'bb281075-1b98-4456-89d6-c643d3044a91';
|
|
||||||
const ad = await findAdByUuidUseCase.execute(
|
|
||||||
new FindAdByUuidQuery(findAdByUuidRequest),
|
|
||||||
);
|
|
||||||
expect(ad).toBe(mockAd);
|
|
||||||
});
|
|
||||||
it('should throw an error if ad does not exist', async () => {
|
|
||||||
const findAdByUuidRequest: FindAdByIdRequestDTO =
|
|
||||||
new FindAdByIdRequestDTO();
|
|
||||||
findAdByUuidRequest.id = 'bb281075-1b98-4456-89d6-c643d3044a90';
|
|
||||||
await expect(
|
|
||||||
findAdByUuidUseCase.execute(new FindAdByUuidQuery(findAdByUuidRequest)),
|
|
||||||
).rejects.toBeInstanceOf(NotFoundException);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,14 +1,20 @@
|
||||||
|
import { PrismaService } from '@libs/db/prisma.service';
|
||||||
|
import {
|
||||||
|
AD_REPOSITORY,
|
||||||
|
PARAMS_PROVIDER,
|
||||||
|
TIMEZONE_FINDER,
|
||||||
|
} from '@modules/ad/ad.di-tokens';
|
||||||
|
import { AdMapper } from '@modules/ad/ad.mapper';
|
||||||
|
import { AdRepository } from '@modules/ad/infrastructure/ad.repository';
|
||||||
|
import { DefaultParamsProvider } from '@modules/ad/infrastructure/default-params-provider';
|
||||||
|
import { TimezoneFinder } from '@modules/ad/infrastructure/timezone-finder';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { EventEmitterModule } from '@nestjs/event-emitter';
|
||||||
import { Test } from '@nestjs/testing';
|
import { Test } from '@nestjs/testing';
|
||||||
import { PrismaService } from '../../../database/adapters/secondaries/prisma-service';
|
|
||||||
import { AdsRepository } from '../../adapters/secondaries/ads.repository';
|
|
||||||
import { DatabaseModule } from '../../../database/database.module';
|
|
||||||
import { Frequency } from '../../interface/commands/frequency.enum';
|
|
||||||
import { AdDTO } from '../../core/dtos/ad.dto';
|
|
||||||
import { Waypoint } from '../../core/entities/waypoint';
|
|
||||||
|
|
||||||
describe('Ad Repository', () => {
|
describe('Ad Repository', () => {
|
||||||
let prismaService: PrismaService;
|
let prismaService: PrismaService;
|
||||||
let adsRepository: AdsRepository;
|
let adRepository: AdRepository;
|
||||||
|
|
||||||
const executeInsertCommand = async (table: string, object: any) => {
|
const executeInsertCommand = async (table: string, object: any) => {
|
||||||
const command = `INSERT INTO ${table} ("${Object.keys(object).join(
|
const command = `INSERT INTO ${table} ("${Object.keys(object).join(
|
||||||
|
@ -20,13 +26,14 @@ describe('Ad Repository', () => {
|
||||||
const getSeed = (index: number, uuid: string): string => {
|
const getSeed = (index: number, uuid: string): string => {
|
||||||
return `'${uuid.slice(0, -2)}${index.toString(16).padStart(2, '0')}'`;
|
return `'${uuid.slice(0, -2)}${index.toString(16).padStart(2, '0')}'`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseUuid = {
|
const baseUuid = {
|
||||||
uuid: 'be459a29-7a41-4c0b-b371-abe90bfb6f00',
|
uuid: 'be459a29-7a41-4c0b-b371-abe90bfb6f00',
|
||||||
};
|
};
|
||||||
const baseAdress0Uuid = {
|
const baseOriginWaypointUuid = {
|
||||||
uuid: 'bad5e786-3b15-4e51-a8fc-926fa9327ff1',
|
uuid: 'bad5e786-3b15-4e51-a8fc-926fa9327ff1',
|
||||||
};
|
};
|
||||||
const baseAdress1Uuid = {
|
const baseDestinationWaypointUuid = {
|
||||||
uuid: '4d200eb6-7389-487f-a1ca-dbc0e40381c9',
|
uuid: '4d200eb6-7389-487f-a1ca-dbc0e40381c9',
|
||||||
};
|
};
|
||||||
const baseUserUuid = {
|
const baseUserUuid = {
|
||||||
|
@ -35,24 +42,24 @@ describe('Ad Repository', () => {
|
||||||
const driverAd = {
|
const driverAd = {
|
||||||
driver: 'true',
|
driver: 'true',
|
||||||
passenger: 'false',
|
passenger: 'false',
|
||||||
seatsDriver: 3,
|
seatsProposed: 3,
|
||||||
seatsPassenger: 0,
|
seatsRequested: 0,
|
||||||
strict: 'false',
|
|
||||||
};
|
|
||||||
const passengerAd = {
|
|
||||||
driver: 'false',
|
|
||||||
passenger: 'true',
|
|
||||||
seatsDriver: 0,
|
|
||||||
seatsPassenger: 1,
|
|
||||||
strict: 'false',
|
|
||||||
};
|
|
||||||
const driverAndPassengerAd = {
|
|
||||||
driver: 'true',
|
|
||||||
passenger: 'true',
|
|
||||||
seatsDriver: 3,
|
|
||||||
seatsPassenger: 1,
|
|
||||||
strict: 'false',
|
strict: 'false',
|
||||||
};
|
};
|
||||||
|
// const passengerAd = {
|
||||||
|
// driver: 'false',
|
||||||
|
// passenger: 'true',
|
||||||
|
// seatsProposed: 0,
|
||||||
|
// seatsRequested: 1,
|
||||||
|
// strict: 'false',
|
||||||
|
// };
|
||||||
|
// const driverAndPassengerAd = {
|
||||||
|
// driver: 'true',
|
||||||
|
// passenger: 'true',
|
||||||
|
// seatsProposed: 3,
|
||||||
|
// seatsRequested: 1,
|
||||||
|
// strict: 'false',
|
||||||
|
// };
|
||||||
const punctualAd = {
|
const punctualAd = {
|
||||||
frequency: `'PUNCTUAL'`,
|
frequency: `'PUNCTUAL'`,
|
||||||
fromDate: `'2023-01-01'`,
|
fromDate: `'2023-01-01'`,
|
||||||
|
@ -63,7 +70,7 @@ describe('Ad Repository', () => {
|
||||||
thuTime: 'NULL',
|
thuTime: 'NULL',
|
||||||
friTime: 'NULL',
|
friTime: 'NULL',
|
||||||
satTime: 'NULL',
|
satTime: 'NULL',
|
||||||
sunTime: `'07:00'`,
|
sunTime: `'2023-01-01T07:00:00Z'`,
|
||||||
monMargin: 900,
|
monMargin: 900,
|
||||||
tueMargin: 900,
|
tueMargin: 900,
|
||||||
wedMargin: 900,
|
wedMargin: 900,
|
||||||
|
@ -72,27 +79,26 @@ describe('Ad Repository', () => {
|
||||||
satMargin: 900,
|
satMargin: 900,
|
||||||
sunMargin: 900,
|
sunMargin: 900,
|
||||||
};
|
};
|
||||||
const recurrentAd = {
|
// const recurrentAd = {
|
||||||
frequency: `'RECURRENT'`,
|
// frequency: `'RECURRENT'`,
|
||||||
fromDate: `'2023-01-01'`,
|
// fromDate: `'2023-01-01'`,
|
||||||
toDate: `'2023-12-31'`,
|
// toDate: `'2023-12-31'`,
|
||||||
monTime: `'07:00'`,
|
// monTime: `'2023-01-01T07:15:00Z'`,
|
||||||
tueTime: `'07:00'`,
|
// tueTime: `'2023-01-01T07:15:00Z'`,
|
||||||
wedTime: `'07:00'`,
|
// wedTime: `'2023-01-01T07:05:00Z'`,
|
||||||
thuTime: `'07:00'`,
|
// thuTime: `'2023-01-01T07:15:00Z'`,
|
||||||
friTime: `'07:00'`,
|
// friTime: `'2023-01-01T07:15:00Z'`,
|
||||||
satTime: 'NULL',
|
// satTime: 'NULL',
|
||||||
sunTime: 'NULL',
|
// sunTime: 'NULL',
|
||||||
monMargin: 900,
|
// monMargin: 900,
|
||||||
tueMargin: 900,
|
// tueMargin: 900,
|
||||||
wedMargin: 900,
|
// wedMargin: 900,
|
||||||
thuMargin: 900,
|
// thuMargin: 900,
|
||||||
friMargin: 900,
|
// friMargin: 900,
|
||||||
satMargin: 900,
|
// satMargin: 900,
|
||||||
sunMargin: 900,
|
// sunMargin: 900,
|
||||||
};
|
// };
|
||||||
|
const originWaypoint = {
|
||||||
const address0 = {
|
|
||||||
position: 0,
|
position: 0,
|
||||||
lon: 43.7102,
|
lon: 43.7102,
|
||||||
lat: 7.262,
|
lat: 7.262,
|
||||||
|
@ -100,7 +106,7 @@ describe('Ad Repository', () => {
|
||||||
postalCode: "'06000'",
|
postalCode: "'06000'",
|
||||||
country: "'France'",
|
country: "'France'",
|
||||||
};
|
};
|
||||||
const address1 = {
|
const destinationWaypoint = {
|
||||||
position: 1,
|
position: 1,
|
||||||
lon: 43.2965,
|
lon: 43.2965,
|
||||||
lat: 5.3698,
|
lat: 5.3698,
|
||||||
|
@ -108,6 +114,7 @@ describe('Ad Repository', () => {
|
||||||
postalCode: "'13000'",
|
postalCode: "'13000'",
|
||||||
country: "'France'",
|
country: "'France'",
|
||||||
};
|
};
|
||||||
|
|
||||||
const createPunctualDriverAds = async (nbToCreate = 10) => {
|
const createPunctualDriverAds = async (nbToCreate = 10) => {
|
||||||
const adToCreate = {
|
const adToCreate = {
|
||||||
...baseUuid,
|
...baseUuid,
|
||||||
|
@ -118,139 +125,159 @@ describe('Ad Repository', () => {
|
||||||
for (let i = 0; i < nbToCreate; i++) {
|
for (let i = 0; i < nbToCreate; i++) {
|
||||||
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
await executeInsertCommand('ad', adToCreate);
|
await executeInsertCommand('ad', adToCreate);
|
||||||
await executeInsertCommand('address', {
|
await executeInsertCommand('waypoint', {
|
||||||
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
uuid: getSeed(i, baseOriginWaypointUuid.uuid),
|
||||||
adUuid: adToCreate.uuid,
|
adUuid: adToCreate.uuid,
|
||||||
...address0,
|
...originWaypoint,
|
||||||
});
|
});
|
||||||
await executeInsertCommand('address', {
|
await executeInsertCommand('waypoint', {
|
||||||
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
uuid: getSeed(i, baseDestinationWaypointUuid.uuid),
|
||||||
adUuid: adToCreate.uuid,
|
adUuid: adToCreate.uuid,
|
||||||
...address1,
|
...destinationWaypoint,
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const createRecurrentDriverAds = async (nbToCreate = 10) => {
|
|
||||||
const adToCreate = {
|
|
||||||
...baseUuid,
|
|
||||||
...baseUserUuid,
|
|
||||||
...driverAd,
|
|
||||||
...punctualAd,
|
|
||||||
};
|
|
||||||
for (let i = 0; i < nbToCreate; i++) {
|
|
||||||
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
|
||||||
await executeInsertCommand('ad', adToCreate);
|
|
||||||
await executeInsertCommand('address', {
|
|
||||||
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
|
||||||
adUuid: adToCreate.uuid,
|
|
||||||
...address0,
|
|
||||||
});
|
|
||||||
await executeInsertCommand('address', {
|
|
||||||
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
|
||||||
adUuid: adToCreate.uuid,
|
|
||||||
...address1,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const createPunctualPassengerAds = async (nbToCreate = 10) => {
|
// const createRecurrentDriverAds = async (nbToCreate = 10) => {
|
||||||
const adToCreate = {
|
// const adToCreate = {
|
||||||
...baseUuid,
|
// ...baseUuid,
|
||||||
...baseUserUuid,
|
// ...baseUserUuid,
|
||||||
...passengerAd,
|
// ...driverAd,
|
||||||
...punctualAd,
|
// ...punctualAd,
|
||||||
};
|
// };
|
||||||
for (let i = 0; i < nbToCreate; i++) {
|
// for (let i = 0; i < nbToCreate; i++) {
|
||||||
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
// adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
await executeInsertCommand('ad', adToCreate);
|
// await executeInsertCommand('ad', adToCreate);
|
||||||
await executeInsertCommand('address', {
|
// await executeInsertCommand('waypoint', {
|
||||||
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
// uuid: getSeed(i, baseOriginWaypointUuid.uuid),
|
||||||
adUuid: adToCreate.uuid,
|
// adUuid: adToCreate.uuid,
|
||||||
...address0,
|
// ...originWaypoint,
|
||||||
});
|
// });
|
||||||
await executeInsertCommand('address', {
|
// await executeInsertCommand('waypoint', {
|
||||||
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
// uuid: getSeed(i, baseDestinationWaypointUuid.uuid),
|
||||||
adUuid: adToCreate.uuid,
|
// adUuid: adToCreate.uuid,
|
||||||
...address1,
|
// ...destinationWaypoint,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
const createRecurrentPassengerAds = async (nbToCreate = 10) => {
|
// const createPunctualPassengerAds = async (nbToCreate = 10) => {
|
||||||
const adToCreate = {
|
// const adToCreate = {
|
||||||
...baseUuid,
|
// ...baseUuid,
|
||||||
...baseUserUuid,
|
// ...baseUserUuid,
|
||||||
...passengerAd,
|
// ...passengerAd,
|
||||||
...recurrentAd,
|
// ...punctualAd,
|
||||||
};
|
// };
|
||||||
for (let i = 0; i < nbToCreate; i++) {
|
// for (let i = 0; i < nbToCreate; i++) {
|
||||||
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
// adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
await executeInsertCommand('ad', adToCreate);
|
// await executeInsertCommand('ad', adToCreate);
|
||||||
await executeInsertCommand('address', {
|
// await executeInsertCommand('waypoint', {
|
||||||
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
// uuid: getSeed(i, baseOriginWaypointUuid.uuid),
|
||||||
adUuid: adToCreate.uuid,
|
// adUuid: adToCreate.uuid,
|
||||||
...address0,
|
// ...originWaypoint,
|
||||||
});
|
// });
|
||||||
await executeInsertCommand('address', {
|
// await executeInsertCommand('waypoint', {
|
||||||
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
// uuid: getSeed(i, baseDestinationWaypointUuid.uuid),
|
||||||
adUuid: adToCreate.uuid,
|
// adUuid: adToCreate.uuid,
|
||||||
...address1,
|
// ...destinationWaypoint,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
const createPunctualDriverPassengerAds = async (nbToCreate = 10) => {
|
// const createRecurrentPassengerAds = async (nbToCreate = 10) => {
|
||||||
const adToCreate = {
|
// const adToCreate = {
|
||||||
...baseUuid,
|
// ...baseUuid,
|
||||||
...baseUserUuid,
|
// ...baseUserUuid,
|
||||||
...driverAndPassengerAd,
|
// ...passengerAd,
|
||||||
...punctualAd,
|
// ...recurrentAd,
|
||||||
};
|
// };
|
||||||
for (let i = 0; i < nbToCreate; i++) {
|
// for (let i = 0; i < nbToCreate; i++) {
|
||||||
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
// adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
await executeInsertCommand('ad', adToCreate);
|
// await executeInsertCommand('ad', adToCreate);
|
||||||
await executeInsertCommand('address', {
|
// await executeInsertCommand('waypoint', {
|
||||||
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
// uuid: getSeed(i, baseOriginWaypointUuid.uuid),
|
||||||
adUuid: adToCreate.uuid,
|
// adUuid: adToCreate.uuid,
|
||||||
...address0,
|
// ...originWaypoint,
|
||||||
});
|
// });
|
||||||
await executeInsertCommand('address', {
|
// await executeInsertCommand('waypoint', {
|
||||||
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
// uuid: getSeed(i, baseDestinationWaypointUuid.uuid),
|
||||||
adUuid: adToCreate.uuid,
|
// adUuid: adToCreate.uuid,
|
||||||
...address1,
|
// ...destinationWaypoint,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
// const createPunctualDriverPassengerAds = async (nbToCreate = 10) => {
|
||||||
|
// const adToCreate = {
|
||||||
|
// ...baseUuid,
|
||||||
|
// ...baseUserUuid,
|
||||||
|
// ...driverAndPassengerAd,
|
||||||
|
// ...punctualAd,
|
||||||
|
// };
|
||||||
|
// for (let i = 0; i < nbToCreate; i++) {
|
||||||
|
// adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
|
// await executeInsertCommand('ad', adToCreate);
|
||||||
|
// await executeInsertCommand('waypoint', {
|
||||||
|
// uuid: getSeed(i, baseOriginWaypointUuid.uuid),
|
||||||
|
// adUuid: adToCreate.uuid,
|
||||||
|
// ...originWaypoint,
|
||||||
|
// });
|
||||||
|
// await executeInsertCommand('waypoint', {
|
||||||
|
// uuid: getSeed(i, baseDestinationWaypointUuid.uuid),
|
||||||
|
// adUuid: adToCreate.uuid,
|
||||||
|
// ...destinationWaypoint,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const createRecurrentDriverPassengerAds = async (nbToCreate = 10) => {
|
||||||
|
// const adToCreate = {
|
||||||
|
// ...baseUuid,
|
||||||
|
// ...baseUserUuid,
|
||||||
|
// ...driverAndPassengerAd,
|
||||||
|
// ...recurrentAd,
|
||||||
|
// };
|
||||||
|
// for (let i = 0; i < nbToCreate; i++) {
|
||||||
|
// adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
|
// await executeInsertCommand('ad', adToCreate);
|
||||||
|
// await executeInsertCommand('waypoint', {
|
||||||
|
// uuid: getSeed(i, baseOriginWaypointUuid.uuid),
|
||||||
|
// adUuid: adToCreate.uuid,
|
||||||
|
// ...originWaypoint,
|
||||||
|
// });
|
||||||
|
// await executeInsertCommand('waypoint', {
|
||||||
|
// uuid: getSeed(i, baseDestinationWaypointUuid.uuid),
|
||||||
|
// adUuid: adToCreate.uuid,
|
||||||
|
// ...destinationWaypoint,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
const createRecurrentDriverPassengerAds = async (nbToCreate = 10) => {
|
|
||||||
const adToCreate = {
|
|
||||||
...baseUuid,
|
|
||||||
...baseUserUuid,
|
|
||||||
...driverAndPassengerAd,
|
|
||||||
...recurrentAd,
|
|
||||||
};
|
|
||||||
for (let i = 0; i < nbToCreate; i++) {
|
|
||||||
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
|
||||||
await executeInsertCommand('ad', adToCreate);
|
|
||||||
await executeInsertCommand('address', {
|
|
||||||
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
|
||||||
adUuid: adToCreate.uuid,
|
|
||||||
...address0,
|
|
||||||
});
|
|
||||||
await executeInsertCommand('address', {
|
|
||||||
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
|
||||||
adUuid: adToCreate.uuid,
|
|
||||||
...address1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const module = await Test.createTestingModule({
|
const module = await Test.createTestingModule({
|
||||||
imports: [DatabaseModule],
|
imports: [
|
||||||
providers: [PrismaService, AdsRepository],
|
EventEmitterModule.forRoot(),
|
||||||
|
ConfigModule.forRoot({ isGlobal: true }),
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
PrismaService,
|
||||||
|
AdMapper,
|
||||||
|
{
|
||||||
|
provide: AD_REPOSITORY,
|
||||||
|
useClass: AdRepository,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: PARAMS_PROVIDER,
|
||||||
|
useClass: DefaultParamsProvider,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: TIMEZONE_FINDER,
|
||||||
|
useClass: TimezoneFinder,
|
||||||
|
},
|
||||||
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
prismaService = module.get<PrismaService>(PrismaService);
|
prismaService = module.get<PrismaService>(PrismaService);
|
||||||
adsRepository = module.get<AdsRepository>(AdsRepository);
|
adRepository = module.get<AdRepository>(AD_REPOSITORY);
|
||||||
});
|
});
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await prismaService.$disconnect();
|
await prismaService.$disconnect();
|
||||||
|
@ -259,210 +286,212 @@ describe('Ad Repository', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await prismaService.ad.deleteMany();
|
await prismaService.ad.deleteMany();
|
||||||
});
|
});
|
||||||
describe('findAll', () => {
|
// describe('findAll', () => {
|
||||||
it('should return an empty data array', async () => {
|
// it('should return an empty data array', async () => {
|
||||||
const res = await adsRepository.findAll();
|
// const res = await adRepository.findAll();
|
||||||
expect(res).toEqual({
|
// expect(res).toEqual({
|
||||||
data: [],
|
// data: [],
|
||||||
total: 0,
|
// total: 0,
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
|
||||||
describe('drivers', () => {
|
// describe('drivers', () => {
|
||||||
it('should return a data array with 8 punctual driver ads', async () => {
|
// it('should return a data array with 8 punctual driver ads', async () => {
|
||||||
await createPunctualDriverAds(8);
|
// await createPunctualDriverAds(8);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(8);
|
// expect(ads.data.length).toBe(8);
|
||||||
expect(ads.total).toBe(8);
|
// expect(ads.total).toBe(8);
|
||||||
expect(ads.data[0].driver).toBeTruthy();
|
// expect(ads.data[0].driver).toBeTruthy();
|
||||||
expect(ads.data[0].passenger).toBeFalsy();
|
// expect(ads.data[0].passenger).toBeFalsy();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should return a data array limited to 10 punctual driver ads', async () => {
|
// it('should return a data array limited to 10 punctual driver ads', async () => {
|
||||||
await createPunctualDriverAds(20);
|
// await createPunctualDriverAds(20);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(10);
|
// expect(ads.data.length).toBe(10);
|
||||||
expect(ads.total).toBe(20);
|
// expect(ads.total).toBe(20);
|
||||||
expect(ads.data[1].driver).toBeTruthy();
|
// expect(ads.data[1].driver).toBeTruthy();
|
||||||
expect(ads.data[1].passenger).toBeFalsy();
|
// expect(ads.data[1].passenger).toBeFalsy();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should return a data array with 8 recurrent driver ads', async () => {
|
// it('should return a data array with 8 recurrent driver ads', async () => {
|
||||||
await createRecurrentDriverAds(8);
|
// await createRecurrentDriverAds(8);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(8);
|
// expect(ads.data.length).toBe(8);
|
||||||
expect(ads.total).toBe(8);
|
// expect(ads.total).toBe(8);
|
||||||
expect(ads.data[2].driver).toBeTruthy();
|
// expect(ads.data[2].driver).toBeTruthy();
|
||||||
expect(ads.data[2].passenger).toBeFalsy();
|
// expect(ads.data[2].passenger).toBeFalsy();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should return a data array limited to 10 recurrent driver ads', async () => {
|
// it('should return a data array limited to 10 recurrent driver ads', async () => {
|
||||||
await createRecurrentDriverAds(20);
|
// await createRecurrentDriverAds(20);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(10);
|
// expect(ads.data.length).toBe(10);
|
||||||
expect(ads.total).toBe(20);
|
// expect(ads.total).toBe(20);
|
||||||
expect(ads.data[3].driver).toBeTruthy();
|
// expect(ads.data[3].driver).toBeTruthy();
|
||||||
expect(ads.data[3].passenger).toBeFalsy();
|
// expect(ads.data[3].passenger).toBeFalsy();
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
|
||||||
describe('passengers', () => {
|
// describe('passengers', () => {
|
||||||
it('should return a data array with 7 punctual passenger ads', async () => {
|
// it('should return a data array with 7 punctual passenger ads', async () => {
|
||||||
await createPunctualPassengerAds(7);
|
// await createPunctualPassengerAds(7);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(7);
|
// expect(ads.data.length).toBe(7);
|
||||||
expect(ads.total).toBe(7);
|
// expect(ads.total).toBe(7);
|
||||||
expect(ads.data[0].passenger).toBeTruthy();
|
// expect(ads.data[0].passenger).toBeTruthy();
|
||||||
expect(ads.data[0].driver).toBeFalsy();
|
// expect(ads.data[0].driver).toBeFalsy();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should return a data array limited to 10 punctual passenger ads', async () => {
|
// it('should return a data array limited to 10 punctual passenger ads', async () => {
|
||||||
await createPunctualPassengerAds(15);
|
// await createPunctualPassengerAds(15);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(10);
|
// expect(ads.data.length).toBe(10);
|
||||||
expect(ads.total).toBe(15);
|
// expect(ads.total).toBe(15);
|
||||||
expect(ads.data[1].passenger).toBeTruthy();
|
// expect(ads.data[1].passenger).toBeTruthy();
|
||||||
expect(ads.data[1].driver).toBeFalsy();
|
// expect(ads.data[1].driver).toBeFalsy();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should return a data array with 7 recurrent passenger ads', async () => {
|
// it('should return a data array with 7 recurrent passenger ads', async () => {
|
||||||
await createRecurrentPassengerAds(7);
|
// await createRecurrentPassengerAds(7);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(7);
|
// expect(ads.data.length).toBe(7);
|
||||||
expect(ads.total).toBe(7);
|
// expect(ads.total).toBe(7);
|
||||||
expect(ads.data[2].passenger).toBeTruthy();
|
// expect(ads.data[2].passenger).toBeTruthy();
|
||||||
expect(ads.data[2].driver).toBeFalsy();
|
// expect(ads.data[2].driver).toBeFalsy();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should return a data array limited to 10 recurrent passenger ads', async () => {
|
// it('should return a data array limited to 10 recurrent passenger ads', async () => {
|
||||||
await createRecurrentPassengerAds(15);
|
// await createRecurrentPassengerAds(15);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(10);
|
// expect(ads.data.length).toBe(10);
|
||||||
expect(ads.total).toBe(15);
|
// expect(ads.total).toBe(15);
|
||||||
expect(ads.data[3].passenger).toBeTruthy();
|
// expect(ads.data[3].passenger).toBeTruthy();
|
||||||
expect(ads.data[3].driver).toBeFalsy();
|
// expect(ads.data[3].driver).toBeFalsy();
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
|
||||||
describe('drivers and passengers', () => {
|
// describe('drivers and passengers', () => {
|
||||||
it('should return a data array with 6 punctual driver and passenger ads', async () => {
|
// it('should return a data array with 6 punctual driver and passenger ads', async () => {
|
||||||
await createPunctualDriverPassengerAds(6);
|
// await createPunctualDriverPassengerAds(6);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(6);
|
// expect(ads.data.length).toBe(6);
|
||||||
expect(ads.total).toBe(6);
|
// expect(ads.total).toBe(6);
|
||||||
expect(ads.data[0].passenger).toBeTruthy();
|
// expect(ads.data[0].passenger).toBeTruthy();
|
||||||
expect(ads.data[0].driver).toBeTruthy();
|
// expect(ads.data[0].driver).toBeTruthy();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should return a data array limited to 10 punctual driver and passenger ads', async () => {
|
// it('should return a data array limited to 10 punctual driver and passenger ads', async () => {
|
||||||
await createPunctualDriverPassengerAds(16);
|
// await createPunctualDriverPassengerAds(16);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(10);
|
// expect(ads.data.length).toBe(10);
|
||||||
expect(ads.total).toBe(16);
|
// expect(ads.total).toBe(16);
|
||||||
expect(ads.data[1].passenger).toBeTruthy();
|
// expect(ads.data[1].passenger).toBeTruthy();
|
||||||
expect(ads.data[1].driver).toBeTruthy();
|
// expect(ads.data[1].driver).toBeTruthy();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should return a data array with 6 recurrent driver and passenger ads', async () => {
|
// it('should return a data array with 6 recurrent driver and passenger ads', async () => {
|
||||||
await createRecurrentDriverPassengerAds(6);
|
// await createRecurrentDriverPassengerAds(6);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(6);
|
// expect(ads.data.length).toBe(6);
|
||||||
expect(ads.total).toBe(6);
|
// expect(ads.total).toBe(6);
|
||||||
expect(ads.data[2].passenger).toBeTruthy();
|
// expect(ads.data[2].passenger).toBeTruthy();
|
||||||
expect(ads.data[2].driver).toBeTruthy();
|
// expect(ads.data[2].driver).toBeTruthy();
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('should return a data array limited to 10 recurrent driver and passenger ads', async () => {
|
// it('should return a data array limited to 10 recurrent driver and passenger ads', async () => {
|
||||||
await createRecurrentDriverPassengerAds(16);
|
// await createRecurrentDriverPassengerAds(16);
|
||||||
const ads = await adsRepository.findAll();
|
// const ads = await adRepository.findAll();
|
||||||
expect(ads.data.length).toBe(10);
|
// expect(ads.data.length).toBe(10);
|
||||||
expect(ads.total).toBe(16);
|
// expect(ads.total).toBe(16);
|
||||||
expect(ads.data[3].passenger).toBeTruthy();
|
// expect(ads.data[3].passenger).toBeTruthy();
|
||||||
expect(ads.data[3].driver).toBeTruthy();
|
// expect(ads.data[3].driver).toBeTruthy();
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
describe('findOneByUuid', () => {
|
describe('findOneById', () => {
|
||||||
it('should return an ad', async () => {
|
it('should return an ad', async () => {
|
||||||
await createPunctualDriverAds(1);
|
await createPunctualDriverAds(1);
|
||||||
const ad = await adsRepository.findOneByUuid(baseUuid.uuid);
|
const result = await adRepository.findOneById(baseUuid.uuid, {
|
||||||
|
waypoints: true,
|
||||||
|
});
|
||||||
|
|
||||||
expect(ad.uuid).toBe(baseUuid.uuid);
|
expect(result.unwrap().id).toBe(baseUuid.uuid);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return null', async () => {
|
// it('should return null', async () => {
|
||||||
const ad = await adsRepository.findOneByUuid(
|
// const ad = await adRepository.findOneById(
|
||||||
'544572be-11fb-4244-8235-587221fc9104',
|
// '544572be-11fb-4244-8235-587221fc9104',
|
||||||
);
|
// );
|
||||||
expect(ad).toBeNull();
|
// expect(ad).toBeNull();
|
||||||
});
|
// });
|
||||||
});
|
});
|
||||||
describe('create', () => {
|
// describe('create', () => {
|
||||||
it('should create an punctual ad', async () => {
|
// it('should create a punctual ad', async () => {
|
||||||
const beforeCount = await prismaService.ad.count();
|
// const beforeCount = await prismaService.ad.count();
|
||||||
const adToCreate: AdDTO = new AdDTO();
|
// const adToCreate: AdDTO = new AdDTO();
|
||||||
|
|
||||||
adToCreate.uuid = 'be459a29-7a41-4c0b-b371-abe90bfb6f00';
|
// adToCreate.uuid = 'be459a29-7a41-4c0b-b371-abe90bfb6f00';
|
||||||
adToCreate.userUuid = '4e52b54d-a729-4dbd-9283-f84a11bb2200';
|
// adToCreate.userUuid = '4e52b54d-a729-4dbd-9283-f84a11bb2200';
|
||||||
adToCreate.driver = true;
|
// adToCreate.driver = true;
|
||||||
adToCreate.passenger = false;
|
// adToCreate.passenger = false;
|
||||||
adToCreate.frequency = Frequency.PUNCTUAL;
|
// adToCreate.frequency = Frequency.PUNCTUAL;
|
||||||
adToCreate.fromDate = new Date('05-22-2023 09:36');
|
// adToCreate.fromDate = new Date('05-22-2023 09:36');
|
||||||
adToCreate.toDate = new Date('05-22-2023 09:36');
|
// adToCreate.toDate = new Date('05-22-2023 09:36');
|
||||||
adToCreate.monTime = '09:36';
|
// adToCreate.monTime = '09:36';
|
||||||
adToCreate.monMargin = 900;
|
// adToCreate.monMargin = 900;
|
||||||
adToCreate.tueMargin = 900;
|
// adToCreate.tueMargin = 900;
|
||||||
adToCreate.wedMargin = 900;
|
// adToCreate.wedMargin = 900;
|
||||||
adToCreate.thuMargin = 900;
|
// adToCreate.thuMargin = 900;
|
||||||
adToCreate.friMargin = 900;
|
// adToCreate.friMargin = 900;
|
||||||
adToCreate.satMargin = 900;
|
// adToCreate.satMargin = 900;
|
||||||
adToCreate.sunMargin = 900;
|
// adToCreate.sunMargin = 900;
|
||||||
adToCreate.seatsProposed = 3;
|
// adToCreate.seatsProposed = 3;
|
||||||
adToCreate.seatsRequested = 0;
|
// adToCreate.seatsRequested = 0;
|
||||||
adToCreate.strict = false;
|
// adToCreate.strict = false;
|
||||||
adToCreate.waypoints = {
|
// adToCreate.waypoints = {
|
||||||
create: [address0 as Waypoint, address1 as Waypoint],
|
// create: [originWaypoint as Waypoint, destinationWaypoint as Waypoint],
|
||||||
};
|
// };
|
||||||
const ad = await adsRepository.create(adToCreate);
|
// const ad = await adRepository.create(adToCreate);
|
||||||
|
|
||||||
const afterCount = await prismaService.ad.count();
|
// const afterCount = await prismaService.ad.count();
|
||||||
|
|
||||||
expect(afterCount - beforeCount).toBe(1);
|
// expect(afterCount - beforeCount).toBe(1);
|
||||||
expect(ad.uuid).toBe('be459a29-7a41-4c0b-b371-abe90bfb6f00');
|
// expect(ad.uuid).toBe('be459a29-7a41-4c0b-b371-abe90bfb6f00');
|
||||||
});
|
// });
|
||||||
it('should create an recurrent ad', async () => {
|
// it('should create a recurrent ad', async () => {
|
||||||
const beforeCount = await prismaService.ad.count();
|
// const beforeCount = await prismaService.ad.count();
|
||||||
const adToCreate: AdDTO = new AdDTO();
|
// const adToCreate: AdDTO = new AdDTO();
|
||||||
|
|
||||||
adToCreate.uuid = '137a26fa-4b38-48ba-aecf-1a75f6b20f3d';
|
// adToCreate.uuid = '137a26fa-4b38-48ba-aecf-1a75f6b20f3d';
|
||||||
adToCreate.userUuid = '4e52b54d-a729-4dbd-9283-f84a11bb2200';
|
// adToCreate.userUuid = '4e52b54d-a729-4dbd-9283-f84a11bb2200';
|
||||||
adToCreate.driver = true;
|
// adToCreate.driver = true;
|
||||||
adToCreate.passenger = false;
|
// adToCreate.passenger = false;
|
||||||
adToCreate.frequency = Frequency.RECURRENT;
|
// adToCreate.frequency = Frequency.RECURRENT;
|
||||||
adToCreate.fromDate = new Date('01-15-2023 ');
|
// adToCreate.fromDate = new Date('01-15-2023 ');
|
||||||
adToCreate.toDate = new Date('10-31-2023');
|
// adToCreate.toDate = new Date('10-31-2023');
|
||||||
adToCreate.monTime = '07:30';
|
// adToCreate.monTime = '07:30';
|
||||||
adToCreate.friTime = '07:45';
|
// adToCreate.friTime = '07:45';
|
||||||
adToCreate.thuTime = '08:00';
|
// adToCreate.thuTime = '08:00';
|
||||||
adToCreate.monMargin = 900;
|
// adToCreate.monMargin = 900;
|
||||||
adToCreate.tueMargin = 900;
|
// adToCreate.tueMargin = 900;
|
||||||
adToCreate.wedMargin = 900;
|
// adToCreate.wedMargin = 900;
|
||||||
adToCreate.thuMargin = 900;
|
// adToCreate.thuMargin = 900;
|
||||||
adToCreate.friMargin = 900;
|
// adToCreate.friMargin = 900;
|
||||||
adToCreate.satMargin = 900;
|
// adToCreate.satMargin = 900;
|
||||||
adToCreate.sunMargin = 900;
|
// adToCreate.sunMargin = 900;
|
||||||
adToCreate.seatsProposed = 2;
|
// adToCreate.seatsProposed = 2;
|
||||||
adToCreate.seatsRequested = 0;
|
// adToCreate.seatsRequested = 0;
|
||||||
adToCreate.strict = false;
|
// adToCreate.strict = false;
|
||||||
adToCreate.waypoints = {
|
// adToCreate.waypoints = {
|
||||||
create: [address0 as Waypoint, address1 as Waypoint],
|
// create: [originWaypoint as Waypoint, destinationWaypoint as Waypoint],
|
||||||
};
|
// };
|
||||||
const ad = await adsRepository.create(adToCreate);
|
// const ad = await adRepository.create(adToCreate);
|
||||||
|
|
||||||
const afterCount = await prismaService.ad.count();
|
// const afterCount = await prismaService.ad.count();
|
||||||
|
|
||||||
expect(afterCount - beforeCount).toBe(1);
|
// expect(afterCount - beforeCount).toBe(1);
|
||||||
expect(ad.uuid).toBe('137a26fa-4b38-48ba-aecf-1a75f6b20f3d');
|
// expect(ad.uuid).toBe('137a26fa-4b38-48ba-aecf-1a75f6b20f3d');
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,409 @@
|
||||||
|
import { AdEntity } from '@modules/ad/core/ad.entity';
|
||||||
|
import {
|
||||||
|
CreateAdProps,
|
||||||
|
DefaultAdProps,
|
||||||
|
Frequency,
|
||||||
|
} from '@modules/ad/core/ad.types';
|
||||||
|
import { MarginDurationsProps } from '@modules/ad/core/value-objects/margin-durations.value-object';
|
||||||
|
import { WaypointProps } from '@modules/ad/core/value-objects/waypoint.value-object';
|
||||||
|
|
||||||
|
const originWaypointProps: WaypointProps = {
|
||||||
|
position: 0,
|
||||||
|
address: {
|
||||||
|
houseNumber: '5',
|
||||||
|
street: 'Avenue Foch',
|
||||||
|
locality: 'Nancy',
|
||||||
|
postalCode: '54000',
|
||||||
|
country: 'France',
|
||||||
|
coordinates: {
|
||||||
|
lon: 48.68944505415954,
|
||||||
|
lat: 6.176510296462267,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const destinationWaypointProps: WaypointProps = {
|
||||||
|
position: 1,
|
||||||
|
address: {
|
||||||
|
locality: 'Paris',
|
||||||
|
postalCode: '75000',
|
||||||
|
country: 'France',
|
||||||
|
coordinates: {
|
||||||
|
lon: 48.8566,
|
||||||
|
lat: 2.3522,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const marginDurationsProps: MarginDurationsProps = {
|
||||||
|
mon: 600,
|
||||||
|
tue: 600,
|
||||||
|
wed: 600,
|
||||||
|
thu: 600,
|
||||||
|
fri: 600,
|
||||||
|
sat: 600,
|
||||||
|
sun: 600,
|
||||||
|
};
|
||||||
|
const baseCreateAdProps = {
|
||||||
|
userId: 'e8fe64b1-4c33-49e1-9f69-4db48b21df36',
|
||||||
|
seatsProposed: 3,
|
||||||
|
seatsRequested: 1,
|
||||||
|
strict: false,
|
||||||
|
waypoints: [originWaypointProps, destinationWaypointProps],
|
||||||
|
};
|
||||||
|
const punctualCreateAdProps = {
|
||||||
|
fromDate: '2023-06-21',
|
||||||
|
toDate: '2023-06-21',
|
||||||
|
schedule: {
|
||||||
|
wed: '08:30',
|
||||||
|
},
|
||||||
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
};
|
||||||
|
const recurrentCreateAdProps = {
|
||||||
|
fromDate: '2023-06-21',
|
||||||
|
toDate: '2024-06-20',
|
||||||
|
schedule: {
|
||||||
|
mon: '08:30',
|
||||||
|
tue: '08:30',
|
||||||
|
wed: '08:00',
|
||||||
|
thu: '08:30',
|
||||||
|
fri: '08:30',
|
||||||
|
},
|
||||||
|
frequency: Frequency.RECURRENT,
|
||||||
|
};
|
||||||
|
const punctualPassengerCreateAdProps: CreateAdProps = {
|
||||||
|
...baseCreateAdProps,
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: false,
|
||||||
|
passenger: true,
|
||||||
|
};
|
||||||
|
const recurrentPassengerCreateAdProps: CreateAdProps = {
|
||||||
|
...baseCreateAdProps,
|
||||||
|
...recurrentCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: false,
|
||||||
|
passenger: true,
|
||||||
|
};
|
||||||
|
const punctualDriverCreateAdProps: CreateAdProps = {
|
||||||
|
...baseCreateAdProps,
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: true,
|
||||||
|
passenger: false,
|
||||||
|
};
|
||||||
|
const recurrentDriverCreateAdProps: CreateAdProps = {
|
||||||
|
...baseCreateAdProps,
|
||||||
|
...recurrentCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: true,
|
||||||
|
passenger: false,
|
||||||
|
};
|
||||||
|
const punctualDriverPassengerCreateAdProps: CreateAdProps = {
|
||||||
|
...baseCreateAdProps,
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: true,
|
||||||
|
passenger: true,
|
||||||
|
};
|
||||||
|
const recurrentDriverPassengerCreateAdProps: CreateAdProps = {
|
||||||
|
...baseCreateAdProps,
|
||||||
|
...recurrentCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: true,
|
||||||
|
passenger: true,
|
||||||
|
};
|
||||||
|
const defaultAdProps: DefaultAdProps = {
|
||||||
|
driver: false,
|
||||||
|
passenger: true,
|
||||||
|
marginDurations: {
|
||||||
|
mon: 900,
|
||||||
|
tue: 900,
|
||||||
|
wed: 900,
|
||||||
|
thu: 900,
|
||||||
|
fri: 900,
|
||||||
|
sat: 900,
|
||||||
|
sun: 900,
|
||||||
|
},
|
||||||
|
seatsProposed: 3,
|
||||||
|
seatsRequested: 1,
|
||||||
|
strict: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Ad entity create', () => {
|
||||||
|
describe('With complete props', () => {
|
||||||
|
it('should create a new punctual passenger ad entity', async () => {
|
||||||
|
const punctualPassengerAd: AdEntity = AdEntity.create(
|
||||||
|
punctualPassengerCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualPassengerAd.id.length).toBe(36);
|
||||||
|
expect(punctualPassengerAd.getProps().schedule.mon).toBeUndefined();
|
||||||
|
expect(punctualPassengerAd.getProps().schedule.wed).toBe('08:30');
|
||||||
|
expect(punctualPassengerAd.getProps().driver).toBeFalsy();
|
||||||
|
expect(punctualPassengerAd.getProps().passenger).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('should create a new punctual driver ad entity', async () => {
|
||||||
|
const punctualDriverAd: AdEntity = AdEntity.create(
|
||||||
|
punctualDriverCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualDriverAd.id.length).toBe(36);
|
||||||
|
expect(punctualDriverAd.getProps().schedule.mon).toBeUndefined();
|
||||||
|
expect(punctualDriverAd.getProps().schedule.wed).toBe('08:30');
|
||||||
|
expect(punctualDriverAd.getProps().driver).toBeTruthy();
|
||||||
|
expect(punctualDriverAd.getProps().passenger).toBeFalsy();
|
||||||
|
});
|
||||||
|
it('should create a new punctual driver and passenger ad entity', async () => {
|
||||||
|
const punctualDriverPassengerAd: AdEntity = AdEntity.create(
|
||||||
|
punctualDriverPassengerCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualDriverPassengerAd.id.length).toBe(36);
|
||||||
|
expect(punctualDriverPassengerAd.getProps().schedule.mon).toBeUndefined();
|
||||||
|
expect(punctualDriverPassengerAd.getProps().schedule.wed).toBe('08:30');
|
||||||
|
expect(punctualDriverPassengerAd.getProps().driver).toBeTruthy();
|
||||||
|
expect(punctualDriverPassengerAd.getProps().passenger).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('should create a new recurrent passenger ad entity', async () => {
|
||||||
|
const recurrentPassengerAd: AdEntity = AdEntity.create(
|
||||||
|
recurrentPassengerCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(recurrentPassengerAd.id.length).toBe(36);
|
||||||
|
expect(recurrentPassengerAd.getProps().schedule.mon).toBe('08:30');
|
||||||
|
expect(recurrentPassengerAd.getProps().schedule.sat).toBeUndefined();
|
||||||
|
expect(recurrentPassengerAd.getProps().driver).toBeFalsy();
|
||||||
|
expect(recurrentPassengerAd.getProps().passenger).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('should create a new recurrent driver ad entity', async () => {
|
||||||
|
const recurrentDriverAd: AdEntity = AdEntity.create(
|
||||||
|
recurrentDriverCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(recurrentDriverAd.id.length).toBe(36);
|
||||||
|
expect(recurrentDriverAd.getProps().schedule.mon).toBe('08:30');
|
||||||
|
expect(recurrentDriverAd.getProps().schedule.sat).toBeUndefined();
|
||||||
|
expect(recurrentDriverAd.getProps().driver).toBeTruthy();
|
||||||
|
expect(recurrentDriverAd.getProps().passenger).toBeFalsy();
|
||||||
|
});
|
||||||
|
it('should create a new recurrent driver and passenger ad entity', async () => {
|
||||||
|
const recurrentDriverPassengerAd: AdEntity = AdEntity.create(
|
||||||
|
recurrentDriverPassengerCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(recurrentDriverPassengerAd.id.length).toBe(36);
|
||||||
|
expect(recurrentDriverPassengerAd.getProps().schedule.mon).toBe('08:30');
|
||||||
|
expect(
|
||||||
|
recurrentDriverPassengerAd.getProps().schedule.sat,
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(recurrentDriverPassengerAd.getProps().driver).toBeTruthy();
|
||||||
|
expect(recurrentDriverPassengerAd.getProps().passenger).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('With incomplete props', () => {
|
||||||
|
it('should create a new punctual passenger ad entity if no role is given', async () => {
|
||||||
|
const punctualWithoutRoleCreateAdProps: CreateAdProps = {
|
||||||
|
...baseCreateAdProps,
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: false,
|
||||||
|
passenger: false,
|
||||||
|
};
|
||||||
|
const punctualWithoutRoleAd: AdEntity = AdEntity.create(
|
||||||
|
punctualWithoutRoleCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualWithoutRoleAd.id.length).toBe(36);
|
||||||
|
expect(punctualWithoutRoleAd.getProps().schedule.mon).toBeUndefined();
|
||||||
|
expect(punctualWithoutRoleAd.getProps().schedule.wed).toBe('08:30');
|
||||||
|
expect(punctualWithoutRoleAd.getProps().driver).toBeFalsy();
|
||||||
|
expect(punctualWithoutRoleAd.getProps().passenger).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('should create a new strict punctual passenger ad entity if no strict param is given', async () => {
|
||||||
|
const punctualWithoutStrictCreateAdProps: CreateAdProps = {
|
||||||
|
userId: 'e8fe64b1-4c33-49e1-9f69-4db48b21df36',
|
||||||
|
seatsProposed: 3,
|
||||||
|
seatsRequested: 1,
|
||||||
|
strict: undefined,
|
||||||
|
waypoints: [originWaypointProps, destinationWaypointProps],
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: false,
|
||||||
|
passenger: true,
|
||||||
|
};
|
||||||
|
const punctualWithoutStrictAd: AdEntity = AdEntity.create(
|
||||||
|
punctualWithoutStrictCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualWithoutStrictAd.id.length).toBe(36);
|
||||||
|
expect(punctualWithoutStrictAd.getProps().schedule.mon).toBeUndefined();
|
||||||
|
expect(punctualWithoutStrictAd.getProps().schedule.wed).toBe('08:30');
|
||||||
|
expect(punctualWithoutStrictAd.getProps().driver).toBeFalsy();
|
||||||
|
expect(punctualWithoutStrictAd.getProps().passenger).toBeTruthy();
|
||||||
|
expect(punctualWithoutStrictAd.getProps().strict).toBeFalsy();
|
||||||
|
});
|
||||||
|
it('should create a new punctual passenger ad entity with seats requested if no seats requested param is given', async () => {
|
||||||
|
const punctualWithoutSeatsRequestedCreateAdProps: CreateAdProps = {
|
||||||
|
userId: 'e8fe64b1-4c33-49e1-9f69-4db48b21df36',
|
||||||
|
seatsProposed: 3,
|
||||||
|
seatsRequested: undefined,
|
||||||
|
strict: false,
|
||||||
|
waypoints: [originWaypointProps, destinationWaypointProps],
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: false,
|
||||||
|
passenger: true,
|
||||||
|
};
|
||||||
|
const punctualWithoutSeatsRequestedAd: AdEntity = AdEntity.create(
|
||||||
|
punctualWithoutSeatsRequestedCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualWithoutSeatsRequestedAd.id.length).toBe(36);
|
||||||
|
expect(
|
||||||
|
punctualWithoutSeatsRequestedAd.getProps().schedule.mon,
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(punctualWithoutSeatsRequestedAd.getProps().schedule.wed).toBe(
|
||||||
|
'08:30',
|
||||||
|
);
|
||||||
|
expect(punctualWithoutSeatsRequestedAd.getProps().driver).toBeFalsy();
|
||||||
|
expect(punctualWithoutSeatsRequestedAd.getProps().passenger).toBeTruthy();
|
||||||
|
expect(punctualWithoutSeatsRequestedAd.getProps().seatsRequested).toBe(1);
|
||||||
|
});
|
||||||
|
it('should create a new punctual driver ad entity with seats proposed if no seats proposed param is given', async () => {
|
||||||
|
const punctualWithoutSeatsProposedCreateAdProps: CreateAdProps = {
|
||||||
|
userId: 'e8fe64b1-4c33-49e1-9f69-4db48b21df36',
|
||||||
|
seatsProposed: undefined,
|
||||||
|
seatsRequested: 1,
|
||||||
|
strict: false,
|
||||||
|
waypoints: [originWaypointProps, destinationWaypointProps],
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: true,
|
||||||
|
passenger: false,
|
||||||
|
};
|
||||||
|
const punctualWithoutSeatsProposedAd: AdEntity = AdEntity.create(
|
||||||
|
punctualWithoutSeatsProposedCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualWithoutSeatsProposedAd.id.length).toBe(36);
|
||||||
|
expect(
|
||||||
|
punctualWithoutSeatsProposedAd.getProps().schedule.mon,
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(punctualWithoutSeatsProposedAd.getProps().schedule.wed).toBe(
|
||||||
|
'08:30',
|
||||||
|
);
|
||||||
|
expect(punctualWithoutSeatsProposedAd.getProps().driver).toBeTruthy();
|
||||||
|
expect(punctualWithoutSeatsProposedAd.getProps().passenger).toBeFalsy();
|
||||||
|
expect(punctualWithoutSeatsProposedAd.getProps().seatsProposed).toBe(3);
|
||||||
|
});
|
||||||
|
it('should create a new punctual driver ad entity with margin durations if margin durations are empty', async () => {
|
||||||
|
const punctualWithoutMarginDurationsCreateAdProps: CreateAdProps = {
|
||||||
|
...baseCreateAdProps,
|
||||||
|
waypoints: [originWaypointProps, destinationWaypointProps],
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: {},
|
||||||
|
driver: true,
|
||||||
|
passenger: false,
|
||||||
|
};
|
||||||
|
const punctualWithoutMarginDurationsAd: AdEntity = AdEntity.create(
|
||||||
|
punctualWithoutMarginDurationsCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualWithoutMarginDurationsAd.id.length).toBe(36);
|
||||||
|
expect(
|
||||||
|
punctualWithoutMarginDurationsAd.getProps().schedule.mon,
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(punctualWithoutMarginDurationsAd.getProps().schedule.wed).toBe(
|
||||||
|
'08:30',
|
||||||
|
);
|
||||||
|
expect(punctualWithoutMarginDurationsAd.getProps().driver).toBeTruthy();
|
||||||
|
expect(punctualWithoutMarginDurationsAd.getProps().passenger).toBeFalsy();
|
||||||
|
expect(
|
||||||
|
punctualWithoutMarginDurationsAd.getProps().marginDurations.mon,
|
||||||
|
).toBe(900);
|
||||||
|
});
|
||||||
|
it('should create a new punctual driver ad entity with margin durations if margin durations are undefined', async () => {
|
||||||
|
const punctualWithoutMarginDurationsCreateAdProps: CreateAdProps = {
|
||||||
|
...baseCreateAdProps,
|
||||||
|
waypoints: [originWaypointProps, destinationWaypointProps],
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: undefined,
|
||||||
|
driver: true,
|
||||||
|
passenger: false,
|
||||||
|
};
|
||||||
|
const punctualWithoutMarginDurationsAd: AdEntity = AdEntity.create(
|
||||||
|
punctualWithoutMarginDurationsCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualWithoutMarginDurationsAd.id.length).toBe(36);
|
||||||
|
expect(
|
||||||
|
punctualWithoutMarginDurationsAd.getProps().schedule.mon,
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(punctualWithoutMarginDurationsAd.getProps().schedule.wed).toBe(
|
||||||
|
'08:30',
|
||||||
|
);
|
||||||
|
expect(punctualWithoutMarginDurationsAd.getProps().driver).toBeTruthy();
|
||||||
|
expect(punctualWithoutMarginDurationsAd.getProps().passenger).toBeFalsy();
|
||||||
|
expect(
|
||||||
|
punctualWithoutMarginDurationsAd.getProps().marginDurations.mon,
|
||||||
|
).toBe(900);
|
||||||
|
});
|
||||||
|
it('should create a new punctual passenger ad entity with valid positions if positions are missing', async () => {
|
||||||
|
const punctualWithoutPositionsCreateAdProps: CreateAdProps = {
|
||||||
|
userId: 'e8fe64b1-4c33-49e1-9f69-4db48b21df36',
|
||||||
|
seatsProposed: 3,
|
||||||
|
seatsRequested: 1,
|
||||||
|
strict: undefined,
|
||||||
|
waypoints: [
|
||||||
|
{
|
||||||
|
position: undefined,
|
||||||
|
address: {
|
||||||
|
houseNumber: '5',
|
||||||
|
street: 'Avenue Foch',
|
||||||
|
locality: 'Nancy',
|
||||||
|
postalCode: '54000',
|
||||||
|
country: 'France',
|
||||||
|
coordinates: {
|
||||||
|
lon: 48.68944505415954,
|
||||||
|
lat: 6.176510296462267,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
position: undefined,
|
||||||
|
address: {
|
||||||
|
locality: 'Paris',
|
||||||
|
postalCode: '75000',
|
||||||
|
country: 'France',
|
||||||
|
coordinates: {
|
||||||
|
lon: 48.8566,
|
||||||
|
lat: 2.3522,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...punctualCreateAdProps,
|
||||||
|
marginDurations: marginDurationsProps,
|
||||||
|
driver: false,
|
||||||
|
passenger: false,
|
||||||
|
};
|
||||||
|
const punctualWithoutPositionsAd: AdEntity = AdEntity.create(
|
||||||
|
punctualWithoutPositionsCreateAdProps,
|
||||||
|
defaultAdProps,
|
||||||
|
);
|
||||||
|
expect(punctualWithoutPositionsAd.id.length).toBe(36);
|
||||||
|
expect(
|
||||||
|
punctualWithoutPositionsAd.getProps().schedule.mon,
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(punctualWithoutPositionsAd.getProps().schedule.wed).toBe('08:30');
|
||||||
|
expect(punctualWithoutPositionsAd.getProps().driver).toBeFalsy();
|
||||||
|
expect(punctualWithoutPositionsAd.getProps().passenger).toBeTruthy();
|
||||||
|
expect(punctualWithoutPositionsAd.getProps().waypoints[0].position).toBe(
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
expect(punctualWithoutPositionsAd.getProps().waypoints[1].position).toBe(
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -10,6 +10,7 @@ import { Result } from 'oxide.ts';
|
||||||
import { AggregateID } from '@libs/ddd';
|
import { AggregateID } from '@libs/ddd';
|
||||||
import { AdAlreadyExistsError } from '@modules/ad/core/ad.errors';
|
import { AdAlreadyExistsError } from '@modules/ad/core/ad.errors';
|
||||||
import { AdEntity } from '@modules/ad/core/ad.entity';
|
import { AdEntity } from '@modules/ad/core/ad.entity';
|
||||||
|
import { ConflictException } from '@libs/exceptions';
|
||||||
|
|
||||||
const originWaypoint: WaypointDTO = {
|
const originWaypoint: WaypointDTO = {
|
||||||
position: 0,
|
position: 0,
|
||||||
|
@ -44,7 +45,15 @@ const punctualCreateAdRequest: CreateAdRequestDTO = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockAdRepository = {
|
const mockAdRepository = {
|
||||||
insert: jest.fn(),
|
insert: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementationOnce(() => ({}))
|
||||||
|
.mockImplementationOnce(() => {
|
||||||
|
throw new Error();
|
||||||
|
})
|
||||||
|
.mockImplementationOnce(() => {
|
||||||
|
throw new ConflictException('already exists');
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockDefaultParamsProvider: DefaultParamsProviderPort = {
|
const mockDefaultParamsProvider: DefaultParamsProviderPort = {
|
||||||
|
@ -102,5 +111,21 @@ describe('create-ad.service', () => {
|
||||||
await createAdService.execute(createAdCommand);
|
await createAdService.execute(createAdCommand);
|
||||||
expect(result.unwrap()).toBe('047a6ecf-23d4-4d3e-877c-3225d560a8da');
|
expect(result.unwrap()).toBe('047a6ecf-23d4-4d3e-877c-3225d560a8da');
|
||||||
});
|
});
|
||||||
|
it('should throw an error if something bad happens', async () => {
|
||||||
|
AdEntity.create = jest.fn().mockReturnValue({
|
||||||
|
id: '047a6ecf-23d4-4d3e-877c-3225d560a8da',
|
||||||
|
});
|
||||||
|
await expect(
|
||||||
|
createAdService.execute(createAdCommand),
|
||||||
|
).rejects.toBeInstanceOf(Error);
|
||||||
|
});
|
||||||
|
it('should return an Err if Ad already exists', async () => {
|
||||||
|
AdEntity.create = jest.fn().mockReturnValue({
|
||||||
|
id: '047a6ecf-23d4-4d3e-877c-3225d560a8da',
|
||||||
|
});
|
||||||
|
const result: Result<AggregateID, AdAlreadyExistsError> =
|
||||||
|
await createAdService.execute(createAdCommand);
|
||||||
|
expect(result.isErr()).toBeTruthy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue