Skip to content

Commit

Permalink
Fixup: Show error when Google Maps API key does not support Geocoding…
Browse files Browse the repository at this point in the history
… or Places APIs
  • Loading branch information
ianguerin committed Mar 22, 2024
1 parent 064bae5 commit c8c9199
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 73 deletions.
12 changes: 4 additions & 8 deletions src/js/models/geocoder/GoogleMapsAutocompleter.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,10 @@ define(
* user is looking for. Most often this comes in five or less results.
*/
async autocomplete(input) {
try {
const response = await this.autocompleter.getPlacePredictions({
input,
});
return this.getPredictionsFromResults(response.predictions);
} catch (e) {
return [];
}
const response = await this.autocompleter.getPlacePredictions({
input,
});
return this.getPredictionsFromResults(response.predictions);
}

/**
Expand Down
12 changes: 4 additions & 8 deletions src/js/models/geocoder/GoogleMapsGeocoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,10 @@ define(
* single value, but could potentially be many.
*/
async geocode(prediction) {
try {
const response = await this.geocoder.geocode({
placeId: prediction.get('googleMapsPlaceId')
});
return this.getGeocodedLocationsFromResults(response.results);
} catch (e) {
return [];
}
const response = await this.geocoder.geocode({
placeId: prediction.get('googleMapsPlaceId')
});
return this.getGeocodedLocationsFromResults(response.results);
}

/**
Expand Down
51 changes: 40 additions & 11 deletions src/js/models/maps/viewfinder/ViewfinderModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ define(
'models/maps/GeoPoint'],
(_, Backbone, Cesium, GeocoderSearch, GeoPoint) => {
const NO_RESULTS_MESSAGE = 'No search results found.';
const PLACES_API_ERROR = 'The Places API is not enabled for this Google Maps API key.';
const GEOCODING_API_ERROR = 'The Geocoding API is not enabled for this Google Maps API key.';

/**
* @class ViewfinderModel
* @classdes ViewfinderModel maintains state for the ViewfinderView and
Expand Down Expand Up @@ -61,10 +64,28 @@ define(
return;
}

// User is looking for autocompletions.
const predictions = await this.geocoderSearch.autocomplete(query);
const error = predictions.length === 0 ? NO_RESULTS_MESSAGE : '';
this.set({ error, focusIndex: -1, predictions, query, });
try {
// User is looking for autocompletions.
const predictions = await this.geocoderSearch.autocomplete(query);
const error = predictions.length === 0 ? NO_RESULTS_MESSAGE : '';
this.set({ error, focusIndex: -1, predictions, query, });
} catch (e) {
if (e.code === 'REQUEST_DENIED' && e.endpoint === 'PLACES_AUTOCOMPLETE') {
this.set({
error: PLACES_API_ERROR,
focusIndex: -1,
predictions: [],
query,
});
} else {
this.set({
error: NO_RESULTS_MESSAGE,
focusIndex: -1,
predictions: [],
query,
});
}
}
},

/**
Expand Down Expand Up @@ -125,15 +146,23 @@ define(
async selectPrediction(prediction) {
if (!prediction) return;

const geocodings = await this.geocoderSearch.geocode(prediction);
try {
const geocodings = await this.geocoderSearch.geocode(prediction);

if (geocodings.length === 0) {
this.set('error', NO_RESULTS_MESSAGE)
return;
}
if (geocodings.length === 0) {
this.set('error', NO_RESULTS_MESSAGE)
return;
}

this.trigger('selection-made', prediction.get('description'));
this.goToLocation(geocodings[0]);
this.trigger('selection-made', prediction.get('description'));
this.goToLocation(geocodings[0]);
} catch (e) {
if (e.code === 'REQUEST_DENIED' && e.endpoint === 'GEOCODER_GEOCODE') {
this.set({ error: GEOCODING_API_ERROR, focusIndex: -1, predictions: [] });
} else {
this.set('error', NO_RESULTS_MESSAGE)
}
}
},

/**
Expand Down
34 changes: 11 additions & 23 deletions test/js/specs/unit/models/geocoder/GoogleMapsAutocompleter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,16 @@ define(
expect(response[0].get('description')).to.equal('some result');
});

it('does not throw an error even if the Google Maps API throws',
async () => {
state.sandbox.restore();
state.sandbox.stub(
state.googleMapsAutocompleter.autocompleter,
'getPlacePredictions'
).rejects();

expect(async () => await state.googleMapsAutocompleter.autocomplete('some place')).not.to.throw;
});

it('returns an empty array if the Google Maps API throws',
async () => {
state.sandbox.restore();
state.sandbox.stub(
state.googleMapsAutocompleter.autocompleter,
'getPlacePredictions'
).rejects();

const response = await state.googleMapsAutocompleter.autocomplete('some place');

expect(response).to.deep.equal([]);
});
it('throws an error if the Google Maps API throws', async () => {
state.sandbox.restore();
state.sandbox.stub(
state.googleMapsAutocompleter.autocompleter,
'getPlacePredictions'
).rejects();

expect(
async () => await state.googleMapsAutocompleter.autocomplete('some place')
).to.throw;
});
});
});
33 changes: 10 additions & 23 deletions test/js/specs/unit/models/geocoder/GoogleMapsGeocoder.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,29 +52,16 @@ define(
expect(response[0].get('displayName')).to.equal('some result');
});

it('does not throw an error even if the Google Maps API throws',
async () => {
state.sandbox.restore();
state.sandbox.stub(
state.googleMapsGeocoder.geocoder,
'geocode'
).rejects();
it('throws an error if the Google Maps API throws', async () => {
state.sandbox.restore();
state.sandbox.stub(
state.googleMapsGeocoder.geocoder,
'geocode'
).rejects();

expect(
async () => state.googleMapsGeocoder.geocode(state.prediction)
).not.to.throw;
});

it('returns an empty array if the Google Maps API throws',
async () => {
state.sandbox.restore();
state.sandbox.stub(state.googleMapsGeocoder.geocoder, 'geocode')
.rejects();

const response = await state.googleMapsGeocoder
.geocode(state.prediction);

expect(response).to.deep.equal([]);
});
expect(
async () => state.googleMapsGeocoder.geocode(state.prediction)
).to.throw;
});
});
});
52 changes: 52 additions & 0 deletions test/js/specs/unit/models/maps/viewfinder/ViewfinderModel.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,32 @@ define(
expect(state.model.get('predictions')[0].get('description')).to.equal('Some Other Location');
});

it('shows permissions error if autocomplete search request is denied',
() => {
state.autocompleteSpy.callsFake(() => {
const error = new Error('Request error');
error.code = 'REQUEST_DENIED';
error.endpoint = 'PLACES_AUTOCOMPLETE';
throw error;
});

state.model.autocompleteSearch("somewhere else");

expect(state.model.get('error')).to.match(/The Places API is not enabled/);
});

it('shows \'no results\' message if autocomplete search throws some other error',
() => {
state.autocompleteSpy.callsFake(() => {
const error = new Error('Some other error');
throw error;
});

state.model.autocompleteSearch("somewhere else");

expect(state.model.get('error')).to.match(/No search results/);
});

it('shows \'no results\' message if predictions are empty', async () => {
state.autocompleteSpy.callsFake(() => ([]));

Expand Down Expand Up @@ -221,6 +247,32 @@ define(
expect(triggerSpy.callCount).to.equal(1);
});

it('shows permissions error if geocoder request is denied',
async () => {
state.geocodeSpy.callsFake(() => {
const error = new Error('Request error');
error.code = 'REQUEST_DENIED';
error.endpoint = 'GEOCODER_GEOCODE';
throw error;
});

await state.model.selectPrediction(state.predictions[0]);

expect(state.model.get('error')).to.match(/The Geocoding API is not enabled/);
});

it('shows \'no results\' message if geocoder throws some other error',
async () => {
state.geocodeSpy.callsFake(() => {
const error = new Error('Some other error');
throw error;
});

await state.model.selectPrediction(state.predictions[0]);

expect(state.model.get('error')).to.match(/No search results/);
});

it('navigates to the geocoded location', async () => {
state.geocodeSpy.returns([
new GeocodedLocation({
Expand Down

0 comments on commit c8c9199

Please sign in to comment.