improve tests
This commit is contained in:
parent
075a856d09
commit
efea6fe13c
|
@ -29,7 +29,7 @@ export class RouteCompleter extends Completer {
|
|||
break;
|
||||
case RouteCompleterType.DETAILED:
|
||||
const detailedCandidateRoute =
|
||||
await this.query.routeProvider.getBasic(
|
||||
await this.query.routeProvider.getDetailed(
|
||||
(candidate.getProps().carpoolSteps as WayStep[]).map(
|
||||
(wayStep: WayStep) => wayStep.point,
|
||||
),
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { RouteProviderPort } from '../core/application/ports/route-provider.port';
|
||||
import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port';
|
||||
import { AD_GET_BASIC_ROUTE_CONTROLLER } from '../ad.di-tokens';
|
||||
import {
|
||||
AD_GET_BASIC_ROUTE_CONTROLLER,
|
||||
AD_GET_DETAILED_ROUTE_CONTROLLER,
|
||||
} from '../ad.di-tokens';
|
||||
import { Point, Route } from '@modules/geography/core/domain/route.types';
|
||||
|
||||
@Injectable()
|
||||
|
@ -9,6 +12,8 @@ export class RouteProvider implements RouteProviderPort {
|
|||
constructor(
|
||||
@Inject(AD_GET_BASIC_ROUTE_CONTROLLER)
|
||||
private readonly getBasicRouteController: GetRouteControllerPort,
|
||||
@Inject(AD_GET_DETAILED_ROUTE_CONTROLLER)
|
||||
private readonly getDetailedRouteController: GetRouteControllerPort,
|
||||
) {}
|
||||
|
||||
getBasic = async (waypoints: Point[]): Promise<Route> =>
|
||||
|
@ -17,7 +22,7 @@ export class RouteProvider implements RouteProviderPort {
|
|||
});
|
||||
|
||||
getDetailed = async (waypoints: Point[]): Promise<Route> =>
|
||||
await this.getBasicRouteController.get({
|
||||
await this.getDetailedRouteController.get({
|
||||
waypoints,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
import { AdRepositoryPort } from '@modules/ad/core/application/ports/ad.repository.port';
|
||||
import { RouteProviderPort } from '@modules/ad/core/application/ports/route-provider.port';
|
||||
import {
|
||||
Algorithm,
|
||||
Selector,
|
||||
} from '@modules/ad/core/application/queries/match/algorithm.abstract';
|
||||
import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query';
|
||||
import { Waypoint } from '@modules/ad/core/application/types/waypoint.type';
|
||||
import { Frequency, Role } from '@modules/ad/core/domain/ad.types';
|
||||
import { CandidateEntity } from '@modules/ad/core/domain/candidate.entity';
|
||||
import { MatchEntity } from '@modules/ad/core/domain/match.entity';
|
||||
|
||||
const originWaypoint: Waypoint = {
|
||||
position: 0,
|
||||
lat: 48.689445,
|
||||
lon: 6.17651,
|
||||
houseNumber: '5',
|
||||
street: 'Avenue Foch',
|
||||
locality: 'Nancy',
|
||||
postalCode: '54000',
|
||||
country: 'France',
|
||||
};
|
||||
const destinationWaypoint: Waypoint = {
|
||||
position: 1,
|
||||
lat: 48.8566,
|
||||
lon: 2.3522,
|
||||
locality: 'Paris',
|
||||
postalCode: '75000',
|
||||
country: 'France',
|
||||
};
|
||||
|
||||
const mockRouteProvider: RouteProviderPort = {
|
||||
getBasic: jest.fn(),
|
||||
getDetailed: jest.fn(),
|
||||
};
|
||||
|
||||
const matchQuery = new MatchQuery(
|
||||
{
|
||||
frequency: Frequency.PUNCTUAL,
|
||||
fromDate: '2023-08-28',
|
||||
toDate: '2023-08-28',
|
||||
schedule: [
|
||||
{
|
||||
time: '01:05',
|
||||
},
|
||||
],
|
||||
waypoints: [originWaypoint, destinationWaypoint],
|
||||
},
|
||||
mockRouteProvider,
|
||||
);
|
||||
|
||||
const mockAdRepository: AdRepositoryPort = {
|
||||
insertExtra: jest.fn(),
|
||||
findOneById: jest.fn(),
|
||||
findOne: jest.fn(),
|
||||
insert: jest.fn(),
|
||||
update: jest.fn(),
|
||||
updateWhere: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
count: jest.fn(),
|
||||
healthCheck: jest.fn(),
|
||||
getCandidateAds: jest.fn(),
|
||||
};
|
||||
|
||||
class SomeSelector extends Selector {
|
||||
select = async (): Promise<CandidateEntity[]> => [
|
||||
CandidateEntity.create({
|
||||
id: 'cc260669-1c6d-441f-80a5-19cd59afb777',
|
||||
role: Role.DRIVER,
|
||||
driverWaypoints: [
|
||||
{
|
||||
lat: 48.678454,
|
||||
lon: 6.189745,
|
||||
},
|
||||
{
|
||||
lat: 48.84877,
|
||||
lon: 2.398457,
|
||||
},
|
||||
],
|
||||
passengerWaypoints: [
|
||||
{
|
||||
lat: 48.849445,
|
||||
lon: 6.68651,
|
||||
},
|
||||
{
|
||||
lat: 47.18746,
|
||||
lon: 2.89742,
|
||||
},
|
||||
],
|
||||
driverDistance: 350145,
|
||||
driverDuration: 13548,
|
||||
spacetimeDetourRatio: {
|
||||
maxDistanceDetourRatio: 0.3,
|
||||
maxDurationDetourRatio: 0.3,
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
class SomeAlgorithm extends Algorithm {
|
||||
constructor(
|
||||
protected readonly query: MatchQuery,
|
||||
protected readonly repository: AdRepositoryPort,
|
||||
) {
|
||||
super(query, repository);
|
||||
this.selector = new SomeSelector(query, repository);
|
||||
this.processors = [];
|
||||
}
|
||||
}
|
||||
|
||||
describe('Abstract Algorithm', () => {
|
||||
it('should return matches', async () => {
|
||||
const someAlgorithm = new SomeAlgorithm(matchQuery, mockAdRepository);
|
||||
const matches: MatchEntity[] = await someAlgorithm.match();
|
||||
expect(matches).toHaveLength(1);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,154 @@
|
|||
import {
|
||||
RouteCompleter,
|
||||
RouteCompleterType,
|
||||
} from '@modules/ad/core/application/queries/match/completer/route.completer';
|
||||
import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query';
|
||||
import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types';
|
||||
import { Waypoint } from '@modules/ad/core/application/types/waypoint.type';
|
||||
import { Frequency, Role } from '@modules/ad/core/domain/ad.types';
|
||||
import { CandidateEntity } from '@modules/ad/core/domain/candidate.entity';
|
||||
import { Target } from '@modules/ad/core/domain/candidate.types';
|
||||
import { Actor } from '@modules/ad/core/domain/value-objects/actor.value-object';
|
||||
import { Point } from '@modules/ad/core/domain/value-objects/point.value-object';
|
||||
|
||||
const originWaypoint: Waypoint = {
|
||||
position: 0,
|
||||
lat: 48.689445,
|
||||
lon: 6.17651,
|
||||
houseNumber: '5',
|
||||
street: 'Avenue Foch',
|
||||
locality: 'Nancy',
|
||||
postalCode: '54000',
|
||||
country: 'France',
|
||||
};
|
||||
const destinationWaypoint: Waypoint = {
|
||||
position: 1,
|
||||
lat: 48.8566,
|
||||
lon: 2.3522,
|
||||
locality: 'Paris',
|
||||
postalCode: '75000',
|
||||
country: 'France',
|
||||
};
|
||||
|
||||
const matchQuery = new MatchQuery(
|
||||
{
|
||||
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
||||
driver: true,
|
||||
passenger: true,
|
||||
frequency: Frequency.PUNCTUAL,
|
||||
fromDate: '2023-08-28',
|
||||
toDate: '2023-08-28',
|
||||
schedule: [
|
||||
{
|
||||
time: '07:05',
|
||||
},
|
||||
],
|
||||
strict: false,
|
||||
waypoints: [originWaypoint, destinationWaypoint],
|
||||
},
|
||||
{
|
||||
getBasic: jest.fn().mockImplementation(() => ({
|
||||
distance: 350101,
|
||||
duration: 14422,
|
||||
fwdAzimuth: 273,
|
||||
backAzimuth: 93,
|
||||
distanceAzimuth: 336544,
|
||||
points: [],
|
||||
})),
|
||||
getDetailed: jest.fn().mockImplementation(() => ({
|
||||
distance: 350102,
|
||||
duration: 14423,
|
||||
fwdAzimuth: 273,
|
||||
backAzimuth: 93,
|
||||
distanceAzimuth: 336544,
|
||||
points: [],
|
||||
})),
|
||||
},
|
||||
);
|
||||
|
||||
const candidate: CandidateEntity = CandidateEntity.create({
|
||||
id: 'cc260669-1c6d-441f-80a5-19cd59afb777',
|
||||
role: Role.DRIVER,
|
||||
driverWaypoints: [
|
||||
{
|
||||
lat: 48.678454,
|
||||
lon: 6.189745,
|
||||
},
|
||||
{
|
||||
lat: 48.84877,
|
||||
lon: 2.398457,
|
||||
},
|
||||
],
|
||||
passengerWaypoints: [
|
||||
{
|
||||
lat: 48.689445,
|
||||
lon: 6.17651,
|
||||
},
|
||||
{
|
||||
lat: 48.8566,
|
||||
lon: 2.3522,
|
||||
},
|
||||
],
|
||||
driverDistance: 350145,
|
||||
driverDuration: 13548,
|
||||
spacetimeDetourRatio: {
|
||||
maxDistanceDetourRatio: 0.3,
|
||||
maxDurationDetourRatio: 0.3,
|
||||
},
|
||||
}).setCarpoolPath([
|
||||
{
|
||||
point: new Point({
|
||||
lat: 48.689445,
|
||||
lon: 6.17651,
|
||||
}),
|
||||
actors: [
|
||||
new Actor({
|
||||
role: Role.DRIVER,
|
||||
target: Target.START,
|
||||
}),
|
||||
new Actor({
|
||||
role: Role.PASSENGER,
|
||||
target: Target.START,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
point: new Point({
|
||||
lat: 48.8566,
|
||||
lon: 2.3522,
|
||||
}),
|
||||
actors: [
|
||||
new Actor({
|
||||
role: Role.DRIVER,
|
||||
target: Target.FINISH,
|
||||
}),
|
||||
new Actor({
|
||||
role: Role.PASSENGER,
|
||||
target: Target.FINISH,
|
||||
}),
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
describe('Route completer', () => {
|
||||
it('should complete candidates with basic setting', async () => {
|
||||
const routeCompleter: RouteCompleter = new RouteCompleter(
|
||||
matchQuery,
|
||||
RouteCompleterType.BASIC,
|
||||
);
|
||||
const completedCandidates: CandidateEntity[] =
|
||||
await routeCompleter.complete([candidate]);
|
||||
expect(completedCandidates.length).toBe(1);
|
||||
expect(completedCandidates[0].getProps().distance).toBe(350101);
|
||||
});
|
||||
it('should complete candidates with detailed setting', async () => {
|
||||
const routeCompleter: RouteCompleter = new RouteCompleter(
|
||||
matchQuery,
|
||||
RouteCompleterType.DETAILED,
|
||||
);
|
||||
const completedCandidates: CandidateEntity[] =
|
||||
await routeCompleter.complete([candidate]);
|
||||
expect(completedCandidates.length).toBe(1);
|
||||
expect(completedCandidates[0].getProps().distance).toBe(350102);
|
||||
});
|
||||
});
|
|
@ -1,4 +1,7 @@
|
|||
import { AD_GET_BASIC_ROUTE_CONTROLLER } from '@modules/ad/ad.di-tokens';
|
||||
import {
|
||||
AD_GET_BASIC_ROUTE_CONTROLLER,
|
||||
AD_GET_DETAILED_ROUTE_CONTROLLER,
|
||||
} from '@modules/ad/ad.di-tokens';
|
||||
import { Point } from '@modules/ad/core/application/types/point.type';
|
||||
import { RouteProvider } from '@modules/ad/infrastructure/route-provider';
|
||||
import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port';
|
||||
|
@ -38,6 +41,30 @@ const mockGetBasicRouteController: GetRouteControllerPort = {
|
|||
})),
|
||||
};
|
||||
|
||||
const mockGetDetailedRouteController: GetRouteControllerPort = {
|
||||
get: jest.fn().mockImplementationOnce(() => ({
|
||||
distance: 350102,
|
||||
duration: 14423,
|
||||
fwdAzimuth: 273,
|
||||
backAzimuth: 93,
|
||||
distanceAzimuth: 336544,
|
||||
points: [
|
||||
{
|
||||
lon: 6.1765102,
|
||||
lat: 48.689445,
|
||||
},
|
||||
{
|
||||
lon: 4.984578,
|
||||
lat: 48.725687,
|
||||
},
|
||||
{
|
||||
lon: 2.3522,
|
||||
lat: 48.8566,
|
||||
},
|
||||
],
|
||||
})),
|
||||
};
|
||||
|
||||
describe('Route provider', () => {
|
||||
let routeProvider: RouteProvider;
|
||||
|
||||
|
@ -49,6 +76,10 @@ describe('Route provider', () => {
|
|||
provide: AD_GET_BASIC_ROUTE_CONTROLLER,
|
||||
useValue: mockGetBasicRouteController,
|
||||
},
|
||||
{
|
||||
provide: AD_GET_DETAILED_ROUTE_CONTROLLER,
|
||||
useValue: mockGetDetailedRouteController,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
|
@ -67,4 +98,13 @@ describe('Route provider', () => {
|
|||
expect(route.distance).toBe(350101);
|
||||
expect(route.duration).toBe(14422);
|
||||
});
|
||||
|
||||
it('should provide a detailed route', async () => {
|
||||
const route: Route = await routeProvider.getDetailed([
|
||||
originPoint,
|
||||
destinationPoint,
|
||||
]);
|
||||
expect(route.distance).toBe(350102);
|
||||
expect(route.duration).toBe(14423);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import { GetDetailedRouteController } from '@modules/geography/interface/controllers/get-detailed-route.controller';
|
||||
import { RouteMapper } from '@modules/geography/route.mapper';
|
||||
import { QueryBus } from '@nestjs/cqrs';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
const mockQueryBus = {
|
||||
execute: jest.fn(),
|
||||
};
|
||||
|
||||
const mockRouteMapper = {
|
||||
toPersistence: jest.fn(),
|
||||
toDomain: jest.fn(),
|
||||
toResponse: jest.fn(),
|
||||
};
|
||||
|
||||
describe('Get Detailed Route Controller', () => {
|
||||
let getDetailedRouteController: GetDetailedRouteController;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
{
|
||||
provide: QueryBus,
|
||||
useValue: mockQueryBus,
|
||||
},
|
||||
{
|
||||
provide: RouteMapper,
|
||||
useValue: mockRouteMapper,
|
||||
},
|
||||
GetDetailedRouteController,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
getDetailedRouteController = module.get<GetDetailedRouteController>(
|
||||
GetDetailedRouteController,
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(getDetailedRouteController).toBeDefined();
|
||||
});
|
||||
|
||||
it('should get a route', async () => {
|
||||
jest.spyOn(mockQueryBus, 'execute');
|
||||
await getDetailedRouteController.get({
|
||||
waypoints: [
|
||||
{
|
||||
lat: 48.689445,
|
||||
lon: 6.17651,
|
||||
},
|
||||
{
|
||||
lat: 48.8566,
|
||||
lon: 2.3522,
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(mockQueryBus.execute).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue