457 lines
11 KiB
TypeScript
457 lines
11 KiB
TypeScript
|
import { Test, TestingModule } from '@nestjs/testing';
|
||
|
import { HttpService } from '@nestjs/axios';
|
||
|
import { of } from 'rxjs';
|
||
|
import { AxiosError } from 'axios';
|
||
|
import { GeorouterCreator } from '../../adapters/secondaries/georouter-creator';
|
||
|
import { IGeorouter } from '../../domain/interfaces/georouter.interface';
|
||
|
import { Geodesic } from '../../adapters/secondaries/geodesic';
|
||
|
|
||
|
const mockHttpService = {
|
||
|
get: jest
|
||
|
.fn()
|
||
|
.mockImplementationOnce(() => {
|
||
|
throw new AxiosError('Axios error !');
|
||
|
})
|
||
|
.mockImplementationOnce(() => {
|
||
|
return of({
|
||
|
status: 200,
|
||
|
data: {
|
||
|
paths: [
|
||
|
{
|
||
|
distance: 50000,
|
||
|
time: 1800000,
|
||
|
snapped_waypoints: {
|
||
|
coordinates: [
|
||
|
[0, 0],
|
||
|
[10, 10],
|
||
|
],
|
||
|
},
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
});
|
||
|
})
|
||
|
.mockImplementationOnce(() => {
|
||
|
return of({
|
||
|
status: 200,
|
||
|
data: {
|
||
|
paths: [
|
||
|
{
|
||
|
distance: 50000,
|
||
|
time: 1800000,
|
||
|
points: {
|
||
|
coordinates: [
|
||
|
[0, 0],
|
||
|
[1, 1],
|
||
|
[2, 2],
|
||
|
[3, 3],
|
||
|
[4, 4],
|
||
|
[5, 5],
|
||
|
[6, 6],
|
||
|
[7, 7],
|
||
|
[8, 8],
|
||
|
[9, 9],
|
||
|
[10, 10],
|
||
|
],
|
||
|
},
|
||
|
snapped_waypoints: {
|
||
|
coordinates: [
|
||
|
[0, 0],
|
||
|
[10, 10],
|
||
|
],
|
||
|
},
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
});
|
||
|
})
|
||
|
.mockImplementationOnce(() => {
|
||
|
return of({
|
||
|
status: 200,
|
||
|
data: {
|
||
|
paths: [
|
||
|
{
|
||
|
distance: 50000,
|
||
|
time: 1800000,
|
||
|
points: {
|
||
|
coordinates: [
|
||
|
[0, 0],
|
||
|
[1, 1],
|
||
|
[2, 2],
|
||
|
[3, 3],
|
||
|
[4, 4],
|
||
|
[5, 5],
|
||
|
[6, 6],
|
||
|
[7, 7],
|
||
|
[8, 8],
|
||
|
[9, 9],
|
||
|
[10, 10],
|
||
|
],
|
||
|
},
|
||
|
details: {
|
||
|
time: [
|
||
|
[0, 1, 180000],
|
||
|
[1, 2, 180000],
|
||
|
[2, 3, 180000],
|
||
|
[3, 4, 180000],
|
||
|
[4, 5, 180000],
|
||
|
[5, 6, 180000],
|
||
|
[6, 7, 180000],
|
||
|
[7, 9, 360000],
|
||
|
[9, 10, 180000],
|
||
|
],
|
||
|
},
|
||
|
snapped_waypoints: {
|
||
|
coordinates: [
|
||
|
[0, 0],
|
||
|
[10, 10],
|
||
|
],
|
||
|
},
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
});
|
||
|
})
|
||
|
.mockImplementationOnce(() => {
|
||
|
return of({
|
||
|
status: 200,
|
||
|
data: {
|
||
|
paths: [
|
||
|
{
|
||
|
distance: 50000,
|
||
|
time: 1800000,
|
||
|
points: {
|
||
|
coordinates: [
|
||
|
[0, 0],
|
||
|
[1, 1],
|
||
|
[2, 2],
|
||
|
[3, 3],
|
||
|
[4, 4],
|
||
|
[7, 7],
|
||
|
[8, 8],
|
||
|
[9, 9],
|
||
|
[10, 10],
|
||
|
],
|
||
|
},
|
||
|
snapped_waypoints: {
|
||
|
coordinates: [
|
||
|
[0, 0],
|
||
|
[5, 5],
|
||
|
[10, 10],
|
||
|
],
|
||
|
},
|
||
|
details: {
|
||
|
time: [
|
||
|
[0, 1, 180000],
|
||
|
[1, 2, 180000],
|
||
|
[2, 3, 180000],
|
||
|
[3, 4, 180000],
|
||
|
[4, 7, 540000],
|
||
|
[7, 9, 360000],
|
||
|
[9, 10, 180000],
|
||
|
],
|
||
|
},
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
});
|
||
|
})
|
||
|
.mockImplementationOnce(() => {
|
||
|
return of({
|
||
|
status: 200,
|
||
|
data: {
|
||
|
paths: [
|
||
|
{
|
||
|
distance: 50000,
|
||
|
time: 1800000,
|
||
|
points: {
|
||
|
coordinates: [
|
||
|
[0, 0],
|
||
|
[1, 1],
|
||
|
[2, 2],
|
||
|
[3, 3],
|
||
|
[4, 4],
|
||
|
[5, 5],
|
||
|
[6, 6],
|
||
|
[7, 7],
|
||
|
[8, 8],
|
||
|
[9, 9],
|
||
|
[10, 10],
|
||
|
],
|
||
|
},
|
||
|
snapped_waypoints: {
|
||
|
coordinates: [
|
||
|
[0, 0],
|
||
|
[5, 5],
|
||
|
[10, 10],
|
||
|
],
|
||
|
},
|
||
|
details: {
|
||
|
time: [
|
||
|
[0, 1, 180000],
|
||
|
[1, 2, 180000],
|
||
|
[2, 3, 180000],
|
||
|
[3, 4, 180000],
|
||
|
[4, 7, 540000],
|
||
|
[7, 9, 360000],
|
||
|
[9, 10, 180000],
|
||
|
],
|
||
|
},
|
||
|
instructions: [
|
||
|
{
|
||
|
distance: 25000,
|
||
|
sign: 0,
|
||
|
interval: [0, 5],
|
||
|
text: 'Some instructions',
|
||
|
time: 900000,
|
||
|
},
|
||
|
{
|
||
|
distance: 0,
|
||
|
sign: 5,
|
||
|
interval: [5, 5],
|
||
|
text: 'Waypoint 1',
|
||
|
time: 0,
|
||
|
},
|
||
|
{
|
||
|
distance: 25000,
|
||
|
sign: 2,
|
||
|
interval: [5, 10],
|
||
|
text: 'Some instructions',
|
||
|
time: 900000,
|
||
|
},
|
||
|
{
|
||
|
distance: 0.0,
|
||
|
sign: 4,
|
||
|
interval: [10, 10],
|
||
|
text: 'Arrive at destination',
|
||
|
time: 0,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
});
|
||
|
}),
|
||
|
};
|
||
|
|
||
|
const mockGeodesic = {
|
||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||
|
inverse: jest.fn().mockImplementation(() => ({
|
||
|
azimuth: 45,
|
||
|
distance: 50000,
|
||
|
})),
|
||
|
};
|
||
|
|
||
|
describe('Graphhopper Georouter', () => {
|
||
|
let georouterCreator: GeorouterCreator;
|
||
|
let graphhopperGeorouter: IGeorouter;
|
||
|
|
||
|
beforeAll(async () => {
|
||
|
const module: TestingModule = await Test.createTestingModule({
|
||
|
imports: [],
|
||
|
providers: [
|
||
|
GeorouterCreator,
|
||
|
{
|
||
|
provide: HttpService,
|
||
|
useValue: mockHttpService,
|
||
|
},
|
||
|
{
|
||
|
provide: Geodesic,
|
||
|
useValue: mockGeodesic,
|
||
|
},
|
||
|
],
|
||
|
}).compile();
|
||
|
|
||
|
georouterCreator = module.get<GeorouterCreator>(GeorouterCreator);
|
||
|
graphhopperGeorouter = georouterCreator.create(
|
||
|
'graphhopper',
|
||
|
'http://localhost',
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('should be defined', () => {
|
||
|
expect(graphhopperGeorouter).toBeDefined();
|
||
|
});
|
||
|
|
||
|
describe('route function', () => {
|
||
|
it('should fail on axios error', async () => {
|
||
|
await expect(
|
||
|
graphhopperGeorouter.route(
|
||
|
[
|
||
|
{
|
||
|
key: 'route1',
|
||
|
points: [
|
||
|
{
|
||
|
lat: 0,
|
||
|
lon: 0,
|
||
|
},
|
||
|
{
|
||
|
lat: 1,
|
||
|
lon: 1,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
{
|
||
|
withDistance: false,
|
||
|
withPoints: false,
|
||
|
withTime: false,
|
||
|
},
|
||
|
),
|
||
|
).rejects.toBeInstanceOf(Error);
|
||
|
});
|
||
|
|
||
|
it('should create one route with all settings to false', async () => {
|
||
|
const routes = await graphhopperGeorouter.route(
|
||
|
[
|
||
|
{
|
||
|
key: 'route1',
|
||
|
points: [
|
||
|
{
|
||
|
lat: 0,
|
||
|
lon: 0,
|
||
|
},
|
||
|
{
|
||
|
lat: 10,
|
||
|
lon: 10,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
{
|
||
|
withDistance: false,
|
||
|
withPoints: false,
|
||
|
withTime: false,
|
||
|
},
|
||
|
);
|
||
|
expect(routes).toHaveLength(1);
|
||
|
expect(routes[0].route.distance).toBe(50000);
|
||
|
});
|
||
|
|
||
|
it('should create one route with points', async () => {
|
||
|
const routes = await graphhopperGeorouter.route(
|
||
|
[
|
||
|
{
|
||
|
key: 'route1',
|
||
|
points: [
|
||
|
{
|
||
|
lat: 0,
|
||
|
lon: 0,
|
||
|
},
|
||
|
{
|
||
|
lat: 10,
|
||
|
lon: 10,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
{
|
||
|
withDistance: false,
|
||
|
withPoints: true,
|
||
|
withTime: false,
|
||
|
},
|
||
|
);
|
||
|
expect(routes).toHaveLength(1);
|
||
|
expect(routes[0].route.distance).toBe(50000);
|
||
|
expect(routes[0].route.duration).toBe(1800);
|
||
|
expect(routes[0].route.fwdAzimuth).toBe(45);
|
||
|
expect(routes[0].route.backAzimuth).toBe(225);
|
||
|
expect(routes[0].route.points.length).toBe(11);
|
||
|
});
|
||
|
|
||
|
it('should create one route with points and time', async () => {
|
||
|
const routes = await graphhopperGeorouter.route(
|
||
|
[
|
||
|
{
|
||
|
key: 'route1',
|
||
|
points: [
|
||
|
{
|
||
|
lat: 0,
|
||
|
lon: 0,
|
||
|
},
|
||
|
{
|
||
|
lat: 10,
|
||
|
lon: 10,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
{
|
||
|
withDistance: false,
|
||
|
withPoints: true,
|
||
|
withTime: true,
|
||
|
},
|
||
|
);
|
||
|
expect(routes).toHaveLength(1);
|
||
|
expect(routes[0].route.spacetimePoints.length).toBe(2);
|
||
|
expect(routes[0].route.spacetimePoints[1].duration).toBe(1800);
|
||
|
expect(routes[0].route.spacetimePoints[1].distance).toBeUndefined();
|
||
|
});
|
||
|
|
||
|
it('should create one route with points and missed waypoints extrapolations', async () => {
|
||
|
const routes = await graphhopperGeorouter.route(
|
||
|
[
|
||
|
{
|
||
|
key: 'route1',
|
||
|
points: [
|
||
|
{
|
||
|
lat: 0,
|
||
|
lon: 0,
|
||
|
},
|
||
|
{
|
||
|
lat: 5,
|
||
|
lon: 5,
|
||
|
},
|
||
|
{
|
||
|
lat: 10,
|
||
|
lon: 10,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
{
|
||
|
withDistance: false,
|
||
|
withPoints: true,
|
||
|
withTime: true,
|
||
|
},
|
||
|
);
|
||
|
expect(routes).toHaveLength(1);
|
||
|
expect(routes[0].route.spacetimePoints.length).toBe(3);
|
||
|
expect(routes[0].route.distance).toBe(50000);
|
||
|
expect(routes[0].route.duration).toBe(1800);
|
||
|
expect(routes[0].route.fwdAzimuth).toBe(45);
|
||
|
expect(routes[0].route.backAzimuth).toBe(225);
|
||
|
expect(routes[0].route.points.length).toBe(9);
|
||
|
});
|
||
|
|
||
|
it('should create one route with points, time and distance', async () => {
|
||
|
const routes = await graphhopperGeorouter.route(
|
||
|
[
|
||
|
{
|
||
|
key: 'route1',
|
||
|
points: [
|
||
|
{
|
||
|
lat: 0,
|
||
|
lon: 0,
|
||
|
},
|
||
|
{
|
||
|
lat: 10,
|
||
|
lon: 10,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
{
|
||
|
withDistance: true,
|
||
|
withPoints: true,
|
||
|
withTime: true,
|
||
|
},
|
||
|
);
|
||
|
expect(routes).toHaveLength(1);
|
||
|
expect(routes[0].route.spacetimePoints.length).toBe(3);
|
||
|
expect(routes[0].route.spacetimePoints[1].duration).toBe(990);
|
||
|
expect(routes[0].route.spacetimePoints[1].distance).toBe(25000);
|
||
|
});
|
||
|
});
|
||
|
});
|