Add integration tests for PassengerOrientedSelector to reproduce Redmine#7812
This commit is contained in:
parent
f6b27978e9
commit
a9f5c36d49
|
@ -1,11 +1,17 @@
|
||||||
import { Frequency, Role } from '@modules/ad/core/domain/ad.types';
|
|
||||||
import { Selector } from '../algorithm.abstract';
|
|
||||||
import { Waypoint } from '../../../types/waypoint.type';
|
|
||||||
import { Point } from '../../../types/point.type';
|
|
||||||
import { CandidateEntity } from '@modules/ad/core/domain/candidate.entity';
|
|
||||||
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
||||||
|
import { Frequency, Role } from '@modules/ad/core/domain/ad.types';
|
||||||
|
import { CandidateEntity } from '@modules/ad/core/domain/candidate.entity';
|
||||||
import { ScheduleItem } from '@modules/ad/core/domain/value-objects/schedule-item.value-object';
|
import { ScheduleItem } from '@modules/ad/core/domain/value-objects/schedule-item.value-object';
|
||||||
|
import { Point } from '../../../types/point.type';
|
||||||
|
import { Waypoint } from '../../../types/waypoint.type';
|
||||||
|
import { Selector } from '../algorithm.abstract';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class complements the AdRepository prisma service by turning a match query object into a SQL query,
|
||||||
|
* with the assumption that the query is passenger-oriented (i.e. it is up to the driver to go out of his way to pick up the passenger)
|
||||||
|
* TODO: Converting the query object into a SQL query is a job for the prisma service / repository implementation,
|
||||||
|
* any logic related to being passenger-oriented should be in the domain layer
|
||||||
|
*/
|
||||||
export class PassengerOrientedSelector extends Selector {
|
export class PassengerOrientedSelector extends Selector {
|
||||||
select = async (): Promise<CandidateEntity[]> => {
|
select = async (): Promise<CandidateEntity[]> => {
|
||||||
const queryStringRoles: QueryStringRole[] = [];
|
const queryStringRoles: QueryStringRole[] = [];
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { CreateAdProps, Frequency } from '@modules/ad/core/domain/ad.types';
|
import { CreateAdProps, Frequency } from '@modules/ad/core/domain/ad.types';
|
||||||
import { PointProps } from '@modules/ad/core/domain/value-objects/point.value-object';
|
import { PointProps } from '@modules/ad/core/domain/value-objects/point.value-object';
|
||||||
import { ScheduleItemProps } from '@modules/ad/core/domain/value-objects/schedule-item.value-object';
|
import { ScheduleItemProps } from '@modules/ad/core/domain/value-objects/schedule-item.value-object';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
export const Nice: PointProps = {
|
export const Nice: PointProps = {
|
||||||
lat: 43.7102,
|
lat: 43.7102,
|
||||||
|
@ -22,9 +23,16 @@ export const Toulon: PointProps = {
|
||||||
lon: 5.95,
|
lon: 5.95,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function monday(time: string): ScheduleItemProps {
|
||||||
|
return { day: 1, time: time, margin: 900 };
|
||||||
|
}
|
||||||
|
|
||||||
export function wednesday(time: string): ScheduleItemProps {
|
export function wednesday(time: string): ScheduleItemProps {
|
||||||
return { day: 3, time: time, margin: 900 };
|
return { day: 3, time: time, margin: 900 };
|
||||||
}
|
}
|
||||||
|
export function thursday(time: string): ScheduleItemProps {
|
||||||
|
return { day: 4, time: time, margin: 900 };
|
||||||
|
}
|
||||||
|
|
||||||
export function weekdays(time: string): ScheduleItemProps[] {
|
export function weekdays(time: string): ScheduleItemProps[] {
|
||||||
return [1, 2, 3, 4, 5].map<ScheduleItemProps>((day) => ({
|
return [1, 2, 3, 4, 5].map<ScheduleItemProps>((day) => ({
|
||||||
|
@ -34,22 +42,41 @@ export function weekdays(time: string): ScheduleItemProps[] {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NiceMarseille(
|
function createAdPropsDefaults(): CreateAdProps {
|
||||||
|
return {
|
||||||
|
id: uuidv4(),
|
||||||
|
driver: false,
|
||||||
|
passenger: false,
|
||||||
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
fromDate: '',
|
||||||
|
toDate: '',
|
||||||
|
schedule: [],
|
||||||
|
seatsProposed: 1,
|
||||||
|
seatsRequested: 1,
|
||||||
|
strict: false,
|
||||||
|
waypoints: [],
|
||||||
|
points: [],
|
||||||
|
driverDuration: 0,
|
||||||
|
driverDistance: 0,
|
||||||
|
passengerDuration: 0,
|
||||||
|
passengerDistance: 0,
|
||||||
|
fwdAzimuth: 0,
|
||||||
|
backAzimuth: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function driverNiceMarseille(
|
||||||
frequency: Frequency,
|
frequency: Frequency,
|
||||||
dates: string[],
|
dates: string[],
|
||||||
schedule: ScheduleItemProps[],
|
schedule: ScheduleItemProps[],
|
||||||
): CreateAdProps {
|
): CreateAdProps {
|
||||||
return {
|
return {
|
||||||
id: 'b4b56444-f8d3-4110-917c-e37bba77f383',
|
...createAdPropsDefaults(),
|
||||||
driver: true,
|
driver: true,
|
||||||
passenger: false,
|
|
||||||
frequency: frequency,
|
frequency: frequency,
|
||||||
fromDate: dates[0],
|
fromDate: dates[0],
|
||||||
toDate: dates[1],
|
toDate: dates[1],
|
||||||
schedule: schedule,
|
schedule: schedule,
|
||||||
seatsProposed: 3,
|
|
||||||
seatsRequested: 1,
|
|
||||||
strict: false,
|
|
||||||
waypoints: [Nice, Marseille],
|
waypoints: [Nice, Marseille],
|
||||||
points: [Nice, SaintRaphael, Toulon, Marseille],
|
points: [Nice, SaintRaphael, Toulon, Marseille],
|
||||||
driverDuration: 7668,
|
driverDuration: 7668,
|
||||||
|
@ -60,3 +87,24 @@ export function NiceMarseille(
|
||||||
backAzimuth: 93,
|
backAzimuth: 93,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function passengerToulonMarseille(
|
||||||
|
frequency: Frequency,
|
||||||
|
dates: string[],
|
||||||
|
schedule: ScheduleItemProps[],
|
||||||
|
): CreateAdProps {
|
||||||
|
return {
|
||||||
|
...createAdPropsDefaults(),
|
||||||
|
passenger: true,
|
||||||
|
frequency: frequency,
|
||||||
|
fromDate: dates[0],
|
||||||
|
toDate: dates[1],
|
||||||
|
schedule: schedule,
|
||||||
|
waypoints: [Toulon, Marseille],
|
||||||
|
points: [Toulon, Marseille],
|
||||||
|
driverDuration: 2460,
|
||||||
|
driverDistance: 64000,
|
||||||
|
passengerDuration: 2460,
|
||||||
|
passengerDistance: 64000,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
||||||
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
import { Frequency } from '@modules/ad/core/domain/ad.types';
|
||||||
import { AdRepository } from '@modules/ad/infrastructure/ad.repository';
|
import { AdRepository } from '@modules/ad/infrastructure/ad.repository';
|
||||||
import { PrismaService } from '@modules/ad/infrastructure/prisma.service';
|
import { PrismaService } from '@modules/ad/infrastructure/prisma.service';
|
||||||
import { NiceMarseille, wednesday, weekdays } from './ad.fixtures';
|
import { driverNiceMarseille, wednesday, weekdays } from './ad.fixtures';
|
||||||
import { integrationTestingModule } from './integration.setup';
|
import { integrationTestingModule } from './integration.setup';
|
||||||
|
|
||||||
describe('Ad Repository', () => {
|
describe('Ad Repository', () => {
|
||||||
|
@ -25,7 +25,7 @@ describe('Ad Repository', () => {
|
||||||
it('should create a punctual ad', async () => {
|
it('should create a punctual ad', async () => {
|
||||||
const beforeCount = await prismaService.ad.count();
|
const beforeCount = await prismaService.ad.count();
|
||||||
|
|
||||||
const createAdProps = NiceMarseille(
|
const createAdProps = driverNiceMarseille(
|
||||||
Frequency.PUNCTUAL,
|
Frequency.PUNCTUAL,
|
||||||
['2023-02-01', '2023-02-01'],
|
['2023-02-01', '2023-02-01'],
|
||||||
[wednesday('08:30')],
|
[wednesday('08:30')],
|
||||||
|
@ -41,7 +41,7 @@ describe('Ad Repository', () => {
|
||||||
it('should create a recurrent ad', async () => {
|
it('should create a recurrent ad', async () => {
|
||||||
const beforeCount = await prismaService.ad.count();
|
const beforeCount = await prismaService.ad.count();
|
||||||
|
|
||||||
const createAdProps = NiceMarseille(
|
const createAdProps = driverNiceMarseille(
|
||||||
Frequency.RECURRENT,
|
Frequency.RECURRENT,
|
||||||
['2023-02-01', '2024-01-31'],
|
['2023-02-01', '2024-01-31'],
|
||||||
weekdays('08:30'),
|
weekdays('08:30'),
|
||||||
|
|
|
@ -0,0 +1,467 @@
|
||||||
|
import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query';
|
||||||
|
import { PassengerOrientedSelector } from '@modules/ad/core/application/queries/match/selector/passenger-oriented.selector';
|
||||||
|
import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types';
|
||||||
|
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
||||||
|
import { CreateAdProps, Frequency } from '@modules/ad/core/domain/ad.types';
|
||||||
|
import { ScheduleItemProps } from '@modules/ad/core/domain/value-objects/schedule-item.value-object';
|
||||||
|
import { AdRepository } from '@modules/ad/infrastructure/ad.repository';
|
||||||
|
import { PrismaService } from '@modules/ad/infrastructure/prisma.service';
|
||||||
|
import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto';
|
||||||
|
import { bareMockGeorouter } from '../unit/georouter.mock';
|
||||||
|
import {
|
||||||
|
Marseille,
|
||||||
|
Nice,
|
||||||
|
SaintRaphael,
|
||||||
|
Toulon,
|
||||||
|
driverNiceMarseille,
|
||||||
|
monday,
|
||||||
|
passengerToulonMarseille,
|
||||||
|
thursday,
|
||||||
|
wednesday,
|
||||||
|
} from './ad.fixtures';
|
||||||
|
import { integrationTestingModule } from './integration.setup';
|
||||||
|
function baseMatchQuery(
|
||||||
|
frequency: Frequency,
|
||||||
|
dates: [string, string],
|
||||||
|
scheduleItems: ScheduleItemProps[],
|
||||||
|
waypoints: WaypointDto[],
|
||||||
|
): MatchQuery {
|
||||||
|
return new MatchQuery(
|
||||||
|
{
|
||||||
|
algorithmType: AlgorithmType.PASSENGER_ORIENTED,
|
||||||
|
driver: false,
|
||||||
|
passenger: false,
|
||||||
|
frequency: frequency,
|
||||||
|
fromDate: dates[0],
|
||||||
|
toDate: dates[1],
|
||||||
|
useAzimuth: false,
|
||||||
|
useProportion: false,
|
||||||
|
remoteness: 15000,
|
||||||
|
schedule: scheduleItems,
|
||||||
|
strict: false,
|
||||||
|
waypoints: waypoints,
|
||||||
|
},
|
||||||
|
bareMockGeorouter,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function passengerQueryToulonMarseille(
|
||||||
|
frequency: Frequency,
|
||||||
|
dates: [string, string],
|
||||||
|
scheduleItems: ScheduleItemProps[],
|
||||||
|
): MatchQuery {
|
||||||
|
const matchQuery = baseMatchQuery(frequency, dates, scheduleItems, [
|
||||||
|
{ position: 0, ...Toulon },
|
||||||
|
{ position: 1, ...Marseille },
|
||||||
|
]);
|
||||||
|
matchQuery.passenger = true;
|
||||||
|
matchQuery.passengerRoute = {
|
||||||
|
distance: 64000,
|
||||||
|
duration: 2460,
|
||||||
|
points: [Toulon, Marseille],
|
||||||
|
// Not used by this query
|
||||||
|
fwdAzimuth: 0,
|
||||||
|
backAzimuth: 0,
|
||||||
|
distanceAzimuth: 0,
|
||||||
|
};
|
||||||
|
return matchQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
function driverQueryNiceMarseille(
|
||||||
|
frequency: Frequency,
|
||||||
|
dates: [string, string],
|
||||||
|
scheduleItems: ScheduleItemProps[],
|
||||||
|
): MatchQuery {
|
||||||
|
const matchQuery = baseMatchQuery(frequency, dates, scheduleItems, [
|
||||||
|
{ position: 0, ...Nice },
|
||||||
|
{ position: 1, ...Marseille },
|
||||||
|
]);
|
||||||
|
matchQuery.driver = true;
|
||||||
|
matchQuery.driverRoute = {
|
||||||
|
distance: 199000,
|
||||||
|
duration: 7668,
|
||||||
|
points: [Nice, SaintRaphael, Toulon, Marseille],
|
||||||
|
// Not used by this query
|
||||||
|
fwdAzimuth: 0,
|
||||||
|
backAzimuth: 0,
|
||||||
|
distanceAzimuth: 0,
|
||||||
|
};
|
||||||
|
return matchQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('PassengerOriented selector', () => {
|
||||||
|
let prismaService: PrismaService;
|
||||||
|
let adRepository: AdRepository;
|
||||||
|
|
||||||
|
const insertAd = async (adProps: CreateAdProps): Promise<void> => {
|
||||||
|
const ad = AdEntity.create(adProps);
|
||||||
|
return adRepository.insertExtra(ad, 'ad');
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
({ prismaService, adRepository } = await integrationTestingModule());
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await prismaService.$disconnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await prismaService.ad.deleteMany();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('select', () => {
|
||||||
|
it('should find a driver that departs on the same day', async () => {
|
||||||
|
await insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-01', '2023-02-01'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
passengerQueryToulonMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-01', '2023-02-01'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find a passenger that departs on the same day', async () => {
|
||||||
|
await insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-01', '2023-02-01'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
driverQueryNiceMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-01', '2023-02-01'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find a driver that departs the day before', async () => {
|
||||||
|
await insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-01', '2023-02-01'],
|
||||||
|
[wednesday('23:45')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
passengerQueryToulonMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-02', '2023-02-02'],
|
||||||
|
[thursday('01:15')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find a passenger that departs the day after', async () => {
|
||||||
|
await insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-02', '2023-02-02'],
|
||||||
|
[thursday('01:15')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
driverQueryNiceMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-01', '2023-02-01'],
|
||||||
|
[wednesday('23:45')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find a driver that departs shortly after midnight', async () => {
|
||||||
|
await insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-02', '2023-02-02'],
|
||||||
|
//01:30 in Nice is 00:30 in UTC
|
||||||
|
[thursday('01:30')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
passengerQueryToulonMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-02', '2023-02-02'],
|
||||||
|
[thursday('03:00')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find a passenger that departs shortly after midnight', async () => {
|
||||||
|
await insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-02', '2023-02-02'],
|
||||||
|
[thursday('03:00')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
driverQueryNiceMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-02', '2023-02-02'],
|
||||||
|
[thursday('01:30')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT find a driver that departs the day after', async () => {
|
||||||
|
await insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-02', '2023-02-02'],
|
||||||
|
[thursday('08:30')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
passengerQueryToulonMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-01', '2023-02-01'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT find a passenger that departs the day before', async () => {
|
||||||
|
await insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-01', '2023-02-01'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
driverQueryNiceMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-02', '2023-02-02'],
|
||||||
|
[thursday('08:30')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find a recurring driver that interesects', async () => {
|
||||||
|
await Promise.all([
|
||||||
|
insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-01', '2023-02-28'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-01', '2023-02-18'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-12', '2023-02-28'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-12', '2023-02-18'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
passengerQueryToulonMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-10', '2023-02-20'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should NOT find a recurring driver that doesn't interesect", async () => {
|
||||||
|
await Promise.all([
|
||||||
|
insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-01', '2023-02-10'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-20', '2023-02-28'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
passengerQueryToulonMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-12', '2023-02-18'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find a recurring passenger that interesects', async () => {
|
||||||
|
await Promise.all([
|
||||||
|
insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-01', '2023-02-28'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-01', '2023-02-18'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-12', '2023-02-28'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-12', '2023-02-18'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
driverQueryNiceMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-10', '2023-02-20'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should NOT find a recurring passenger that doesn't interesect", async () => {
|
||||||
|
await Promise.all([
|
||||||
|
insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-01', '2023-02-10'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-20', '2023-02-28'],
|
||||||
|
[wednesday('10:00')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
driverQueryNiceMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-12', '2023-02-18'],
|
||||||
|
[wednesday('08:30')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find a borderline driver that departs the day before a recurring query', async () => {
|
||||||
|
await insertAd(
|
||||||
|
driverNiceMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-01', '2023-02-01'],
|
||||||
|
[wednesday('23:45')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
passengerQueryToulonMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-02-02', '2023-02-28'],
|
||||||
|
[monday('13:45'), thursday('01:15')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find a borderline passenger that departs the day after a recurring query', async () => {
|
||||||
|
await insertAd(
|
||||||
|
passengerToulonMarseille(
|
||||||
|
Frequency.PUNCTUAL,
|
||||||
|
['2023-02-02', '2023-02-02'],
|
||||||
|
[thursday('01:15')],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const passengerOrientedSelector = new PassengerOrientedSelector(
|
||||||
|
driverQueryNiceMarseille(
|
||||||
|
Frequency.RECURRENT,
|
||||||
|
['2023-01-01', '2023-02-01'],
|
||||||
|
[monday('13:45'), wednesday('23:45')],
|
||||||
|
),
|
||||||
|
adRepository,
|
||||||
|
);
|
||||||
|
const candidates = await passengerOrientedSelector.select();
|
||||||
|
expect(candidates.length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -72,27 +72,7 @@ matchQuery.driverRoute = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
matchQuery.passengerRoute = {
|
matchQuery.passengerRoute = { ...matchQuery.driverRoute };
|
||||||
distance: 150120,
|
|
||||||
duration: 6540,
|
|
||||||
fwdAzimuth: 276,
|
|
||||||
backAzimuth: 96,
|
|
||||||
distanceAzimuth: 148321,
|
|
||||||
points: [
|
|
||||||
{
|
|
||||||
lat: 48.689445,
|
|
||||||
lon: 6.17651,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
lat: 48.7566,
|
|
||||||
lon: 4.3522,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
lat: 48.8566,
|
|
||||||
lon: 2.3522,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const mockMatcherRepository: AdRepositoryPort = {
|
const mockMatcherRepository: AdRepositoryPort = {
|
||||||
insertExtra: jest.fn(),
|
insertExtra: jest.fn(),
|
||||||
|
|
Loading…
Reference in New Issue