diff --git a/package.json b/package.json index b2265f2..43e918b 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "test:integration": "npm run migrate:test && dotenv -e .env.test -- jest --testPathPattern 'tests/integration/' --verbose", "test:integration:ci": "npm run migrate:test:ci && dotenv -e ci/.env.ci -- jest --testPathPattern 'tests/integration/'", "test:cov": "jest --testPathPattern 'tests/unit/' --coverage", + "test:cov:watch": "jest --testPathPattern 'tests/unit/' --coverage --watch", "test:e2e": "jest --config ./test/jest-e2e.json", "generate": "docker exec v3-matcher-api sh -c 'npx prisma generate'", "migrate": "docker exec v3-matcher-api sh -c 'npx prisma migrate dev'", diff --git a/src/modules/matcher/domain/entities/engine/factory/algorithm-factory-creator.ts b/src/modules/matcher/domain/entities/engine/factory/algorithm-factory-creator.ts index 585f96e..1bce748 100644 --- a/src/modules/matcher/domain/entities/engine/factory/algorithm-factory-creator.ts +++ b/src/modules/matcher/domain/entities/engine/factory/algorithm-factory-creator.ts @@ -7,12 +7,12 @@ import { Injectable } from '@nestjs/common'; @Injectable() export class AlgorithmFactoryCreator { create = (matchQuery: MatchQuery): AlgorithmFactory => { - let algorithm: AlgorithmFactory; + let algorithmFactory: AlgorithmFactory; switch (matchQuery.algorithmSettings.algorithmType) { case AlgorithmType.CLASSIC: - algorithm = new ClassicAlgorithmFactory(matchQuery); + algorithmFactory = new ClassicAlgorithmFactory(matchQuery); break; } - return algorithm; + return algorithmFactory; }; } diff --git a/src/modules/matcher/domain/entities/engine/processor/completer/classic-waypoint.completer.processor.ts b/src/modules/matcher/domain/entities/engine/processor/completer/classic-waypoint.completer.processor.ts index bec51b6..baccba9 100644 --- a/src/modules/matcher/domain/entities/engine/processor/completer/classic-waypoint.completer.processor.ts +++ b/src/modules/matcher/domain/entities/engine/processor/completer/classic-waypoint.completer.processor.ts @@ -2,8 +2,7 @@ import { Candidate } from '../../candidate'; import { Completer } from './completer.abstract'; export class ClassicWaypointsCompleter extends Completer { - // eslint-disable-next-line @typescript-eslint/no-unused-vars complete = (candidates: Array): Array => { - return []; + return candidates; }; } diff --git a/src/modules/matcher/domain/entities/engine/processor/completer/journey.completer.processor.ts b/src/modules/matcher/domain/entities/engine/processor/completer/journey.completer.processor.ts index 34559a5..69042b9 100644 --- a/src/modules/matcher/domain/entities/engine/processor/completer/journey.completer.processor.ts +++ b/src/modules/matcher/domain/entities/engine/processor/completer/journey.completer.processor.ts @@ -2,8 +2,7 @@ import { Candidate } from '../../candidate'; import { Completer } from './completer.abstract'; export class JourneyCompleter extends Completer { - // eslint-disable-next-line @typescript-eslint/no-unused-vars complete = (candidates: Array): Array => { - return []; + return candidates; }; } diff --git a/src/modules/matcher/domain/entities/engine/processor/completer/route.completer.processor.ts b/src/modules/matcher/domain/entities/engine/processor/completer/route.completer.processor.ts index 5d6c36a..582bc03 100644 --- a/src/modules/matcher/domain/entities/engine/processor/completer/route.completer.processor.ts +++ b/src/modules/matcher/domain/entities/engine/processor/completer/route.completer.processor.ts @@ -19,8 +19,7 @@ export class RouteCompleter extends Completer { this.withDistance = withDistance; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars complete = (candidates: Array): Array => { - return []; + return candidates; }; } diff --git a/src/modules/matcher/domain/entities/engine/processor/filter/geofilter/classic.filter.processor.ts b/src/modules/matcher/domain/entities/engine/processor/filter/geofilter/classic.filter.processor.ts index 3c9b60c..dc0dc66 100644 --- a/src/modules/matcher/domain/entities/engine/processor/filter/geofilter/classic.filter.processor.ts +++ b/src/modules/matcher/domain/entities/engine/processor/filter/geofilter/classic.filter.processor.ts @@ -2,8 +2,7 @@ import { Candidate } from '../../../candidate'; import { Filter } from '../filter.abstract'; export class ClassicGeoFilter extends Filter { - // eslint-disable-next-line @typescript-eslint/no-unused-vars filter = (candidates: Array): Array => { - return []; + return candidates; }; } diff --git a/src/modules/matcher/domain/entities/engine/processor/filter/timefilter/classic.filter.processor.ts b/src/modules/matcher/domain/entities/engine/processor/filter/timefilter/classic.filter.processor.ts index c10336f..b69c32e 100644 --- a/src/modules/matcher/domain/entities/engine/processor/filter/timefilter/classic.filter.processor.ts +++ b/src/modules/matcher/domain/entities/engine/processor/filter/timefilter/classic.filter.processor.ts @@ -2,8 +2,7 @@ import { Candidate } from '../../../candidate'; import { Filter } from '../filter.abstract'; export class ClassicTimeFilter extends Filter { - // eslint-disable-next-line @typescript-eslint/no-unused-vars filter = (candidates: Array): Array => { - return []; + return candidates; }; } diff --git a/src/modules/matcher/tests/unit/domain/engine/algorithm-factory-creator.spec.ts b/src/modules/matcher/tests/unit/domain/engine/algorithm-factory-creator.spec.ts new file mode 100644 index 0000000..79bf1fc --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/algorithm-factory-creator.spec.ts @@ -0,0 +1,61 @@ +import { AlgorithmFactoryCreator } from '../../../../domain/entities/engine/factory/algorithm-factory-creator'; +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; +import { ClassicAlgorithmFactory } from '../../../../domain/entities/engine/factory/classic'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +describe('AlgorithmFactoryCreator', () => { + it('should be defined', () => { + expect(new AlgorithmFactoryCreator()).toBeDefined(); + }); + + it('should create a classic algorithm factory', () => { + expect(new AlgorithmFactoryCreator().create(matchQuery)).toBeInstanceOf( + ClassicAlgorithmFactory, + ); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/algorithm-factory.abstract.spec.ts b/src/modules/matcher/tests/unit/domain/engine/algorithm-factory.abstract.spec.ts new file mode 100644 index 0000000..7ec1886 --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/algorithm-factory.abstract.spec.ts @@ -0,0 +1,78 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { AlgorithmFactory } from '../../../../domain/entities/engine/factory/algorithm-factory.abstract'; +import { Processor } from '../../../../domain/entities/engine/processor/processor.abstract'; +import { Selector } from '../../../../domain/entities/engine/selector/selector.abstract'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +class FakeSelector extends Selector { + select = (): Promise => { + return Promise.resolve([new Candidate()]); + }; +} + +class FakeProcessor extends Processor { + execute = (candidates: Candidate[]): Candidate[] => { + return candidates; + }; +} + +class FakeAlgorithmFactory extends AlgorithmFactory { + createSelector = (): Selector => { + return new FakeSelector(matchQuery); + }; + createProcessors = (): Processor[] => { + return [new FakeProcessor(matchQuery)]; + }; +} + +describe('AlgorithmFactory', () => { + it('should create an extended class', () => { + expect(new FakeAlgorithmFactory(matchQuery)).toBeDefined(); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/classic-algorithm-factory.spec.ts b/src/modules/matcher/tests/unit/domain/engine/classic-algorithm-factory.spec.ts new file mode 100644 index 0000000..45d8a31 --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/classic-algorithm-factory.spec.ts @@ -0,0 +1,69 @@ +import { ClassicSelector } from '../../../../domain/entities/engine/selector/classic.selector'; +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { ClassicAlgorithmFactory } from '../../../../domain/entities/engine/factory/classic'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +describe('ClassicAlgorithmFactory', () => { + it('should be defined', () => { + expect(new ClassicAlgorithmFactory(matchQuery)).toBeDefined(); + }); + + it('should create a classic selector', () => { + const classicAlgorithmFactory: ClassicAlgorithmFactory = + new ClassicAlgorithmFactory(matchQuery); + expect(classicAlgorithmFactory.createSelector()).toBeInstanceOf( + ClassicSelector, + ); + }); + + it('should create processors', () => { + const classicAlgorithmFactory: ClassicAlgorithmFactory = + new ClassicAlgorithmFactory(matchQuery); + expect(classicAlgorithmFactory.createProcessors().length).toBe(6); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/classic-geo.filter.processor.spec.ts b/src/modules/matcher/tests/unit/domain/engine/classic-geo.filter.processor.spec.ts new file mode 100644 index 0000000..abd06b8 --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/classic-geo.filter.processor.spec.ts @@ -0,0 +1,63 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { ClassicGeoFilter } from '../../../../domain/entities/engine/processor/filter/geofilter/classic.filter.processor'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +describe('ClassicGeoFilter', () => { + it('should be defined', () => { + expect(new ClassicGeoFilter(matchQuery)).toBeDefined(); + }); + + it('should filter candidates', () => { + const candidates = [new Candidate(), new Candidate()]; + const classicWaypointCompleter: ClassicGeoFilter = new ClassicGeoFilter( + matchQuery, + ); + expect(classicWaypointCompleter.filter(candidates).length).toBe(2); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/classic-time.filter.processor.spec.ts b/src/modules/matcher/tests/unit/domain/engine/classic-time.filter.processor.spec.ts new file mode 100644 index 0000000..fe92e70 --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/classic-time.filter.processor.spec.ts @@ -0,0 +1,63 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { ClassicTimeFilter } from '../../../../domain/entities/engine/processor/filter/timefilter/classic.filter.processor'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +describe('ClassicTimeFilter', () => { + it('should be defined', () => { + expect(new ClassicTimeFilter(matchQuery)).toBeDefined(); + }); + + it('should filter candidates', () => { + const candidates = [new Candidate(), new Candidate()]; + const classicWaypointCompleter: ClassicTimeFilter = new ClassicTimeFilter( + matchQuery, + ); + expect(classicWaypointCompleter.filter(candidates).length).toBe(2); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/classic-waypoint.completer.processor.spec.ts b/src/modules/matcher/tests/unit/domain/engine/classic-waypoint.completer.processor.spec.ts new file mode 100644 index 0000000..500193e --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/classic-waypoint.completer.processor.spec.ts @@ -0,0 +1,62 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; +import { ClassicWaypointsCompleter } from '../../../../domain/entities/engine/processor/completer/classic-waypoint.completer.processor'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +describe('ClassicWaypointCompleter', () => { + it('should be defined', () => { + expect(new ClassicWaypointsCompleter(matchQuery)).toBeDefined(); + }); + + it('should complete candidates', () => { + const candidates = [new Candidate(), new Candidate()]; + const classicWaypointCompleter: ClassicWaypointsCompleter = + new ClassicWaypointsCompleter(matchQuery); + expect(classicWaypointCompleter.complete(candidates).length).toBe(2); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/classic.selector.spec.ts b/src/modules/matcher/tests/unit/domain/engine/classic.selector.spec.ts new file mode 100644 index 0000000..8eb2954 --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/classic.selector.spec.ts @@ -0,0 +1,61 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { ClassicSelector } from '../../../../domain/entities/engine/selector/classic.selector'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +describe('ClassicSelector', () => { + it('should be defined', () => { + expect(new ClassicSelector(matchQuery)).toBeDefined(); + }); + + it('should select candidates', async () => { + const classicSelector: ClassicSelector = new ClassicSelector(matchQuery); + const candidates: Candidate[] = await classicSelector.select(); + expect(candidates.length).toBe(0); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/completer.abstract.spec.ts b/src/modules/matcher/tests/unit/domain/engine/completer.abstract.spec.ts new file mode 100644 index 0000000..f94bbcf --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/completer.abstract.spec.ts @@ -0,0 +1,68 @@ +import { Completer } from '../../../../domain/entities/engine/processor/completer/completer.abstract'; +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +class FakeCompleter extends Completer { + complete = (candidates: Candidate[]): Candidate[] => { + return candidates; + }; +} + +describe('Completer', () => { + it('should create an extended class', () => { + expect(new FakeCompleter(matchQuery)).toBeDefined(); + }); + + it('should call complete method', () => { + const fakeCompleter: Completer = new FakeCompleter(matchQuery); + const completerSpy = jest.spyOn(fakeCompleter, 'complete'); + fakeCompleter.execute([new Candidate()]); + expect(completerSpy).toHaveBeenCalled(); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/filter.abstract.spec.ts b/src/modules/matcher/tests/unit/domain/engine/filter.abstract.spec.ts new file mode 100644 index 0000000..dfb1e64 --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/filter.abstract.spec.ts @@ -0,0 +1,68 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; +import { Filter } from '../../../../domain/entities/engine/processor/filter/filter.abstract'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +class FakeFilter extends Filter { + filter = (candidates: Candidate[]): Candidate[] => { + return candidates; + }; +} + +describe('Filter', () => { + it('should create an extended class', () => { + expect(new FakeFilter(matchQuery)).toBeDefined(); + }); + + it('should call complete method', () => { + const fakeFilter: Filter = new FakeFilter(matchQuery); + const filterSpy = jest.spyOn(fakeFilter, 'filter'); + fakeFilter.execute([new Candidate()]); + expect(filterSpy).toHaveBeenCalled(); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/journey.completer.processor.spec.ts b/src/modules/matcher/tests/unit/domain/engine/journey.completer.processor.spec.ts new file mode 100644 index 0000000..9eb9a58 --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/journey.completer.processor.spec.ts @@ -0,0 +1,61 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { JourneyCompleter } from '../../../../domain/entities/engine/processor/completer/journey.completer.processor'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +describe('JourneyCompleter', () => { + it('should be defined', () => { + expect(new JourneyCompleter(matchQuery)).toBeDefined(); + }); + + it('should complete candidates', () => { + const candidates = [new Candidate(), new Candidate()]; + const journeyCompleter: JourneyCompleter = new JourneyCompleter(matchQuery); + expect(journeyCompleter.complete(candidates).length).toBe(2); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/processor.abstract.spec.ts b/src/modules/matcher/tests/unit/domain/engine/processor.abstract.spec.ts new file mode 100644 index 0000000..66bfefb --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/processor.abstract.spec.ts @@ -0,0 +1,61 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { Processor } from '../../../../domain/entities/engine/processor/processor.abstract'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +class FakeProcessor extends Processor { + execute = (candidates: Candidate[]): Candidate[] => { + return candidates; + }; +} + +describe('Processor', () => { + it('should create an extended class', () => { + expect(new FakeProcessor(matchQuery)).toBeDefined(); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/route.completer.processor.spec.ts b/src/modules/matcher/tests/unit/domain/engine/route.completer.processor.spec.ts new file mode 100644 index 0000000..4863945 --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/route.completer.processor.spec.ts @@ -0,0 +1,61 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { RouteCompleter } from '../../../../domain/entities/engine/processor/completer/route.completer.processor'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +describe('RouteCompleter', () => { + it('should be defined', () => { + expect(new RouteCompleter(matchQuery)).toBeDefined(); + }); + + it('should complete candidates', () => { + const candidates = [new Candidate(), new Candidate()]; + const routeCompleter: RouteCompleter = new RouteCompleter(matchQuery); + expect(routeCompleter.complete(candidates).length).toBe(2); + }); +}); diff --git a/src/modules/matcher/tests/unit/domain/engine/selector.abstract.spec.ts b/src/modules/matcher/tests/unit/domain/engine/selector.abstract.spec.ts new file mode 100644 index 0000000..01f9eb7 --- /dev/null +++ b/src/modules/matcher/tests/unit/domain/engine/selector.abstract.spec.ts @@ -0,0 +1,61 @@ +import { MatchRequest } from '../../../../domain/dtos/match.request'; +import { Candidate } from '../../../../domain/entities/engine/candidate'; +import { AlgorithmType } from '../../../../domain/types/algorithm.enum'; +import { IDefaultParams } from '../../../../domain/types/default-params.type'; +import { MatchQuery } from '../../../../queries/match.query'; +import { Selector } from '../../../../domain/entities/engine/selector/selector.abstract'; + +const mockGeorouterCreator = { + create: jest.fn().mockImplementation(), +}; + +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, + DEFAULT_TIMEZONE: 'Europe/Paris', + DEFAULT_SEATS: 3, + DEFAULT_ALGORITHM_SETTINGS: { + algorithm: AlgorithmType.CLASSIC, + strict: false, + remoteness: 15000, + useProportion: true, + proportion: 0.3, + useAzimuth: true, + azimuthMargin: 10, + maxDetourDistanceRatio: 0.3, + maxDetourDurationRatio: 0.3, + georouterType: 'graphhopper', + georouterUrl: 'http://localhost', + }, +}; + +const matchRequest: MatchRequest = new MatchRequest(); +matchRequest.departure = '2023-04-01 12:00'; +matchRequest.waypoints = [ + { + lat: 49.440041, + lon: 1.093912, + }, + { + lat: 50.630992, + lon: 3.045432, + }, +]; +const matchQuery: MatchQuery = new MatchQuery( + matchRequest, + defaultParams, + mockGeorouterCreator, +); + +class FakeSelector extends Selector { + select = (): Promise => { + return Promise.resolve([new Candidate()]); + }; +} + +describe('Selector', () => { + it('should create an extended class', () => { + expect(new FakeSelector(matchQuery)).toBeDefined(); + }); +});