Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completed getQueryPredictions implementation #45

Merged
merged 3 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions src/places.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,18 +229,24 @@ class MigrationAutocompleteService {
getQueryPredictions(request, callback) {
const query = request.input;
const locationBias = request.locationBias; // optional
const bounds = request.bounds; // optional

const input: SearchPlaceIndexForSuggestionsRequest = {
IndexName: this._placeIndexName,
Text: query, // required
};

// TODO: Create helper methods for converting to/from LatLng concrete and literal
if (locationBias) {
if (typeof locationBias.lat === "function") {
input.BiasPosition = [locationBias.lng(), locationBias.lat()];
} else {
input.BiasPosition = [locationBias.lng, locationBias.lat];
// If bounds is specified, then location bias is ignored
if (bounds) {
const latLngBounds = new MigrationLatLngBounds(bounds);
const southWest = latLngBounds.getSouthWest();
const northEast = latLngBounds.getNorthEast();

input.FilterBBox = [southWest.lng(), southWest.lat(), northEast.lng(), northEast.lat()];
} else if (locationBias) {
const lngLat = LatLngToLngLat(locationBias);
if (lngLat) {
input.BiasPosition = lngLat;
}
}

Expand All @@ -254,10 +260,6 @@ class MigrationAutocompleteService {
const results = response.Results;
if (results && results.length !== 0) {
results.forEach(function (result) {
if (!result.Text) {
return;
}

const prediction: QueryAutocompletePrediction = {
description: result.Text,
};
Expand Down
154 changes: 148 additions & 6 deletions test/places.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { MigrationPlacesService } from "../src/places";
import { MigrationAutocompleteService, MigrationPlacesService } from "../src/places";
import { MigrationLatLng, MigrationLatLngBounds, PlacesServiceStatus } from "../src/googleCommon";

// Spy on console.error so we can verify it gets called in error cases
Expand Down Expand Up @@ -57,6 +57,23 @@ const mockedClientSend = jest.fn((command) => {
},
});
}
} else if (command instanceof SearchPlaceIndexForSuggestionsCommand) {
if (command.input.Text == clientErrorQuery) {
// Return an empty object that will throw an error
resolve({});
} else {
resolve({
Results: [
{
Text: "cool places near austin",
},
{
PlaceId: "COOL_PLACE_1",
Text: "123 cool place way, austin, tx",
},
],
});
}
} else {
reject();
}
Expand All @@ -71,8 +88,15 @@ jest.mock("@aws-sdk/client-location", () => ({
};
}),
}));
import { GetPlaceCommand, LocationClient, SearchPlaceIndexForTextCommand } from "@aws-sdk/client-location";

import {
GetPlaceCommand,
LocationClient,
SearchPlaceIndexForSuggestionsCommand,
SearchPlaceIndexForTextCommand,
} from "@aws-sdk/client-location";

const autocompleteService = new MigrationAutocompleteService();
autocompleteService._client = new LocationClient();
const placesService = new MigrationPlacesService();
placesService._client = new LocationClient();

Expand Down Expand Up @@ -250,14 +274,14 @@ test("getDetails should handle client error", (done) => {
});
});

test("textSearch should only use bounds if location was also specified", (done) => {
test("textSearch should ignore location if bounds was also specified", (done) => {
const east = 0;
const north = 1;
const south = 2;
const west = 3;
const request = {
query: "cool places in austin",
bounds: new MigrationLatLngBounds(new MigrationLatLng(south, west), new MigrationLatLng(east, north)),
bounds: new MigrationLatLngBounds(new MigrationLatLng(south, west), new MigrationLatLng(north, east)),
location: new MigrationLatLng(4, 5),
};

Expand All @@ -269,7 +293,7 @@ test("textSearch should only use bounds if location was also specified", (done)
expect(mockedClientSend).toHaveBeenCalledWith(expect.any(SearchPlaceIndexForTextCommand));
const clientInput = mockedClientSend.mock.calls[0][0].input;

expect(clientInput.FilterBBox).toStrictEqual([west, south, north, east]);
expect(clientInput.FilterBBox).toStrictEqual([west, south, east, north]);
expect(clientInput.BiasPosition).toBeUndefined();

expect(firstResult.name).toStrictEqual("Austin");
Expand Down Expand Up @@ -401,3 +425,121 @@ test("textSearch should handle client error", (done) => {
done();
});
});

test("getQueryPredictions should ignore location if bounds was also specified", (done) => {
const east = 0;
const north = 1;
const south = 2;
const west = 3;
const request = {
input: "cool place",
bounds: new MigrationLatLngBounds(new MigrationLatLng(south, west), new MigrationLatLng(north, east)),
locationBias: new MigrationLatLng(4, 5),
};

autocompleteService.getQueryPredictions(request, (results, status) => {
expect(mockedClientSend).toHaveBeenCalledTimes(1);
expect(mockedClientSend).toHaveBeenCalledWith(expect.any(SearchPlaceIndexForSuggestionsCommand));
const clientInput = mockedClientSend.mock.calls[0][0].input;

expect(clientInput.FilterBBox).toStrictEqual([west, south, east, north]);
expect(clientInput.BiasPosition).toBeUndefined();

expect(results.length).toStrictEqual(2);

const firstResult = results[0];
expect(firstResult.description).toStrictEqual("cool places near austin");
expect(firstResult.place_id).toBeUndefined();

const secondResult = results[1];
expect(secondResult.description).toStrictEqual("123 cool place way, austin, tx");
expect(secondResult.place_id).toStrictEqual("COOL_PLACE_1");

expect(status).toStrictEqual(PlacesServiceStatus.OK);

// Signal the unit test is complete
done();
});
});

test("getQueryPredictions should accept bounds as a literal", (done) => {
const east = 0;
const north = 1;
const south = 2;
const west = 3;
const request = {
input: "cool place",
bounds: { east: east, north: north, south: south, west: west },
};

autocompleteService.getQueryPredictions(request, (results, status) => {
expect(mockedClientSend).toHaveBeenCalledTimes(1);
expect(mockedClientSend).toHaveBeenCalledWith(expect.any(SearchPlaceIndexForSuggestionsCommand));
const clientInput = mockedClientSend.mock.calls[0][0].input;

expect(clientInput.FilterBBox).toStrictEqual([west, south, east, north]);
expect(clientInput.BiasPosition).toBeUndefined();

expect(results.length).toStrictEqual(2);

const firstResult = results[0];
expect(firstResult.description).toStrictEqual("cool places near austin");
expect(firstResult.place_id).toBeUndefined();

const secondResult = results[1];
expect(secondResult.description).toStrictEqual("123 cool place way, austin, tx");
expect(secondResult.place_id).toStrictEqual("COOL_PLACE_1");

expect(status).toStrictEqual(PlacesServiceStatus.OK);

// Signal the unit test is complete
done();
});
});

test("getQueryPredictions should accept location bias if there is no bounds specified", (done) => {
const request = {
input: "cool place",
locationBias: new MigrationLatLng(testLat, testLng),
};

autocompleteService.getQueryPredictions(request, (results, status) => {
expect(mockedClientSend).toHaveBeenCalledTimes(1);
expect(mockedClientSend).toHaveBeenCalledWith(expect.any(SearchPlaceIndexForSuggestionsCommand));
const clientInput = mockedClientSend.mock.calls[0][0].input;

expect(clientInput.BiasPosition).toStrictEqual([testLng, testLat]);
expect(clientInput.FilterBBox).toBeUndefined();

expect(results.length).toStrictEqual(2);

const firstResult = results[0];
expect(firstResult.description).toStrictEqual("cool places near austin");
expect(firstResult.place_id).toBeUndefined();

const secondResult = results[1];
expect(secondResult.description).toStrictEqual("123 cool place way, austin, tx");
expect(secondResult.place_id).toStrictEqual("COOL_PLACE_1");

expect(status).toStrictEqual(PlacesServiceStatus.OK);

// Signal the unit test is complete
done();
});
});

test("getQueryPredictions should handle client error", (done) => {
const request = {
input: clientErrorQuery,
};

autocompleteService.getQueryPredictions(request, (results, status) => {
expect(results).toHaveLength(0);
expect(status).toStrictEqual(PlacesServiceStatus.UNKNOWN_ERROR);

expect(console.error).toHaveBeenCalledTimes(1);

// Signal the unit test is complete
done();
});
});
Loading