diff --git a/src/directions.ts b/src/directions.ts index 91ddfc0..97d6e09 100644 --- a/src/directions.ts +++ b/src/directions.ts @@ -1,7 +1,12 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { CalculateRouteCommand, CalculateRouteRequest, LocationClient } from "@aws-sdk/client-location"; +import { + CalculateRouteCommand, + CalculateRouteCarModeOptions, + CalculateRouteRequest, + LocationClient, +} from "@aws-sdk/client-location"; import { AddListenerResponse, @@ -10,7 +15,6 @@ import { MigrationLatLng, MigrationLatLngBounds, PlacesServiceStatus, - TravelMode, } from "./googleCommon"; import { MigrationMap } from "./maps"; import { MigrationMarker } from "./markers"; @@ -75,11 +79,19 @@ interface DirectionsRoute { legs: DirectionsLeg[]; } -enum UnitSystem { +export enum UnitSystem { IMPERIAL = 0.0, METRIC = 1.0, } +export enum TravelMode { + DRIVING = "DRIVING", + WALKING = "WALKING", + BICYCLING = "BICYCLING", + TRANSIT = "TRANSIT", + TWO_WHEELER = "TWO_WHEELER", +} + interface DirectionsWaypoint { location?: string | MigrationLatLng | LatLngLiteral | Place; stopover?: boolean; @@ -138,10 +150,47 @@ class MigrationDirectionsService { CalculatorName: this._routeCalculatorName, // required DeparturePosition: departurePosition, // required DestinationPosition: destinationPosition, // required - TravelMode: "Car", // FIXME: Convert this from the input options IncludeLegGeometry: true, }; + if ("travelMode" in options) { + switch (options.travelMode) { + case TravelMode.DRIVING: { + input.TravelMode = "Car"; + break; + } + case TravelMode.WALKING: { + input.TravelMode = "Walking"; + break; + } + } + } + + if ("unitSystem" in options) { + if (options.unitSystem == UnitSystem.IMPERIAL) { + input.DistanceUnit = "Miles"; + } else if (options.unitSystem == UnitSystem.METRIC) { + input.DistanceUnit = "Kilometers"; + } + } + + // only pass in avoidFerries and avoidTolls options if travel mode is Driving, Amazon Location Client will error out + // if CarModeOptions is passed in and travel mode is not Driving + if ( + ("avoidFerries" in options || "avoidTolls" in options) && + "travelMode" in options && + options.travelMode == TravelMode.DRIVING + ) { + const carModeOptions: CalculateRouteCarModeOptions = {}; + if ("avoidFerries" in options) { + carModeOptions.AvoidFerries = options.avoidFerries; + } + if ("avoidTolls" in options) { + carModeOptions.AvoidTolls = options.avoidTolls; + } + input.CarModeOptions = carModeOptions; + } + const command = new CalculateRouteCommand(input); this._client diff --git a/src/googleCommon.ts b/src/googleCommon.ts index 01b8800..69c2c92 100644 --- a/src/googleCommon.ts +++ b/src/googleCommon.ts @@ -273,14 +273,6 @@ export const PlacesServiceStatus = { NOT_FOUND: "NOT_FOUND", }; -export enum TravelMode { - DRIVING = "DRIVING", - WALKING = "WALKING", - BICYCLING = "BICYCLING", - TRANSIT = "TRANSIT", - TWO_WHEELER = "TWO_WHEELER", -} - export enum DirectionsStatus { OK = "OK", UNKNOWN_ERROR = "UNKNOWN_ERROR", diff --git a/src/index.ts b/src/index.ts index 56263fb..12fe565 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,14 +4,13 @@ import { withAPIKey } from "@aws/amazon-location-utilities-auth-helper"; import { LocationClient } from "@aws-sdk/client-location"; -import { MigrationDirectionsRenderer, MigrationDirectionsService } from "./directions"; +import { MigrationDirectionsRenderer, MigrationDirectionsService, TravelMode, UnitSystem } from "./directions"; import { DirectionsStatus, MigrationControlPosition, MigrationLatLng, MigrationLatLngBounds, PlacesServiceStatus, - TravelMode, } from "./googleCommon"; import { MigrationMap } from "./maps"; import { MigrationMarker } from "./markers"; @@ -120,6 +119,7 @@ const migrationInit = async function () { DirectionsService: MigrationDirectionsService, DirectionsStatus: DirectionsStatus, TravelMode: TravelMode, + UnitSystem: UnitSystem, places: { Autocomplete: MigrationAutocomplete, diff --git a/test/directions.test.ts b/test/directions.test.ts index f21438a..e797b3b 100644 --- a/test/directions.test.ts +++ b/test/directions.test.ts @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 import { MigrationMap } from "../src/maps"; -import { MigrationDirectionsRenderer, MigrationDirectionsService } from "../src/directions"; +import { MigrationDirectionsRenderer, MigrationDirectionsService, TravelMode, UnitSystem } from "../src/directions"; import { MigrationPlacesService } from "../src/places"; -import { DirectionsStatus, MigrationLatLng, MigrationLatLngBounds, TravelMode } from "../src/googleCommon"; +import { DirectionsStatus, MigrationLatLng, MigrationLatLngBounds } from "../src/googleCommon"; const mockAddControl = jest.fn(); const mockFitBounds = jest.fn(); @@ -1015,6 +1015,97 @@ test("should return route with origin as Place.placeId and destination as Place. }); }); +test("should call route with options travel mode set to walking and unit system set to imperial", (done) => { + const request = { + origin: { + placeId: "KEEP_AUSTIN_WEIRD", + }, + destination: { + query: "another cool place", + }, + travelMode: TravelMode.WALKING, + unitSystem: UnitSystem.IMPERIAL, + }; + + directionsService.route(request).then(() => { + expect(mockedClientSend).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + CalculatorName: undefined, + DeparturePosition: [4, 3], + DestinationPosition: [8, 7], + DistanceUnit: "Miles", + IncludeLegGeometry: true, + TravelMode: "Walking", + }, + }), + ); + + done(); + }); +}); + +test("should call route with options travel mode set to driving and unit system set to metric", (done) => { + const request = { + origin: { + placeId: "KEEP_AUSTIN_WEIRD", + }, + destination: { + query: "another cool place", + }, + travelMode: TravelMode.DRIVING, + unitSystem: UnitSystem.METRIC, + }; + + directionsService.route(request).then(() => { + expect(mockedClientSend).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + CalculatorName: undefined, + DeparturePosition: [4, 3], + DestinationPosition: [8, 7], + DistanceUnit: "Kilometers", + IncludeLegGeometry: true, + TravelMode: "Car", + }, + }), + ); + + done(); + }); +}); + +test("should call route with options travel mode set to driving and unit system set to metric", (done) => { + const request = { + origin: { + placeId: "KEEP_AUSTIN_WEIRD", + }, + destination: { + query: "another cool place", + }, + travelMode: TravelMode.DRIVING, + avoidFerries: true, + avoidTolls: true, + }; + + directionsService.route(request).then(() => { + expect(mockedClientSend).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + CalculatorName: undefined, + CarModeOptions: { AvoidFerries: true, AvoidTolls: true }, + DeparturePosition: [4, 3], + DestinationPosition: [8, 7], + IncludeLegGeometry: true, + TravelMode: "Car", + }, + }), + ); + + done(); + }); +}); + test("route should handle client error", (done) => { const origin = new MigrationLatLng(1, 2); const destination = new MigrationLatLng(-1, -1); // The mock will throw an error for this position @@ -1027,7 +1118,7 @@ test("route should handle client error", (done) => { directionsService .route(request) - .then((response) => {}) + .then(() => {}) .catch((error) => { expect(error.status).toStrictEqual(DirectionsStatus.UNKNOWN_ERROR); expect(console.error).toHaveBeenCalledTimes(1); @@ -1048,7 +1139,7 @@ test("route should handle client error when performing findPlaceFromQuery origin directionsService .route(request) - .then((response) => {}) + .then(() => {}) .catch((error) => { expect(error.status).toStrictEqual(DirectionsStatus.UNKNOWN_ERROR); expect(console.error).toHaveBeenCalledTimes(2); @@ -1067,7 +1158,7 @@ test("route should handle client error when performing findPlaceFromQuery destin directionsService .route(request) - .then((response) => {}) + .then(() => {}) .catch((error) => { expect(error.status).toStrictEqual(DirectionsStatus.UNKNOWN_ERROR); expect(console.error).toHaveBeenCalledTimes(2); @@ -1088,7 +1179,7 @@ test("route should handle client error when performing getDetails destination re directionsService .route(request) - .then((response) => {}) + .then(() => {}) .catch((error) => { expect(error.status).toStrictEqual(DirectionsStatus.UNKNOWN_ERROR); expect(console.error).toHaveBeenCalledTimes(2);