Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
fix(viaIP-conflict): disable aroundLatLngViaIP when setting location (#…
Browse files Browse the repository at this point in the history
…554)

* fix(viaIP-conflict): remove aroundLatLngViaIP when places widget sets the geolocation

* fix(widget): allow creation without options

* fix(widget): never allow postion & IP at the same time
  • Loading branch information
JonathanMontane authored and raphi committed Sep 17, 2018
1 parent b413852 commit 29c2473
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/instantsearch/__snapshots__/widget.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SearchParameters {
"analytics": undefined,
"analyticsTags": undefined,
"aroundLatLng": "123,123",
"aroundLatLngViaIP": undefined,
"aroundLatLngViaIP": false,
"aroundPrecision": undefined,
"aroundRadius": undefined,
"attributesToHighlight": undefined,
Expand Down
42 changes: 36 additions & 6 deletions src/instantsearch/widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import places from '../places.js';
* The underlying structure for the Algolia Places instantsearch widget.
*/
class AlgoliaPlacesWidget {
constructor({ defaultPosition, ...placesOptions }) {
constructor({ defaultPosition, ...placesOptions } = {}) {
if (Array.isArray(defaultPosition) && defaultPosition.length === 2) {
this.defaultPosition = defaultPosition.join(',');
}
Expand All @@ -13,20 +13,32 @@ class AlgoliaPlacesWidget {
this.placesAutocomplete = places(this.placesOptions);

this.query = '';
this.initialLatLngViaIP = null;
}

getConfiguration() {
const configuration = {};

if (this.defaultPosition) {
configuration.aroundLatLng = this.defaultPosition;
configuration.insideBoundingBox = undefined;
configuration.aroundLatLngViaIP = false;
configuration.aroundLatLng = this.defaultPosition;
}

return configuration;
}

init({ helper }) {
// Get the initial value only when it's not already set via URLSync
// see: getWidgetSearchParameters
if (this.initialLatLngViaIP === null) {
// The value is retrieved in the `init` rather than `getConfiguration`
// because the widget that set `aroundLatLngViaIP` might be registered
// after this one. We wait until we have the full configuration to save
// the initial value.
this.initialLatLngViaIP = helper.getQueryParameter('aroundLatLngViaIP');
}

this.placesAutocomplete.on('change', opts => {
const {
suggestion: {
Expand All @@ -36,36 +48,54 @@ class AlgoliaPlacesWidget {
} = opts;

this.query = value;

helper
.setQueryParameter('insideBoundingBox')
.setQueryParameter('aroundLatLngViaIP', false)
.setQueryParameter('aroundLatLng', `${lat},${lng}`)
.search();
});

this.placesAutocomplete.on('clear', () => {
this.query = '';
helper
.setQueryParameter('insideBoundingBox')
.setQueryParameter('aroundLatLng', this.defaultPosition)
.search();

helper.setQueryParameter('insideBoundingBox');

if (this.defaultPosition) {
helper
.setQueryParameter('aroundLatLngViaIP', false)
.setQueryParameter('aroundLatLng', this.defaultPosition);
} else {
helper
.setQueryParameter('aroundLatLngViaIP', this.initialLatLngViaIP)
.setQueryParameter('aroundLatLng');
}

helper.search();
});
}

getWidgetSearchParameters(searchParameters, { uiState }) {
if (!uiState.places) {
this.placesAutocomplete.setVal('');
this.placesAutocomplete.close();

return searchParameters;
}

const { query, position } = uiState.places;

this.query = query;
this.initialLatLngViaIP = searchParameters.getQueryParameter(
'aroundLatLngViaIP'
);

this.placesAutocomplete.setVal(query || '');
this.placesAutocomplete.close();

return searchParameters
.setQueryParameter('insideBoundingBox')
.setQueryParameter('aroundLatLngViaIP', false)
.setQueryParameter('aroundLatLng', position);
}

Expand Down
116 changes: 115 additions & 1 deletion src/instantsearch/widget.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ describe('instantsearch widget', () => {
expect(places).toBeCalledWith({ places: 'option' });
});

it('creates a places instance without parameters', () => {
expect(() => algoliaPlacesWidget()).not.toThrow();
});

it('configures the helper', () => {
const client = createFakeClient();
const helper = createFakekHelper(client);
Expand Down Expand Up @@ -75,6 +79,7 @@ describe('instantsearch widget', () => {

expect(afterConfiguration).toEqual({
insideBoundingBox: undefined,
aroundLatLngViaIP: false,
aroundLatLng: '1,1',
});
});
Expand All @@ -90,6 +95,7 @@ describe('instantsearch widget', () => {

expect(afterConfiguration).toEqual({
insideBoundingBox: undefined,
aroundLatLngViaIP: false,
aroundLatLng: '1,1',
});
});
Expand Down Expand Up @@ -127,11 +133,37 @@ describe('instantsearch widget', () => {
});
});

it('configures aroundLatLng on clear event', () => {
it('removes aroundLatLngViaIP on change event', () => {
const client = createFakeClient();
const helper = createFakekHelper(client);
const widget = algoliaPlacesWidget(defaultOptions);

helper.setQueryParameter('aroundLatLngViaIP', true);

widget.init({ helper });

const eventName = places.__instance.on.mock.calls[0][0];
const eventListener = places.__instance.on.mock.calls[0][1];

expect(eventName).toEqual('change');

eventListener({ suggestion: { latlng: { lat: '123', lng: '456' } } });

expect(helper.search).toBeCalled();
expect(helper.getState()).toMatchObject({
insideBoundingBox: undefined,
aroundLatLng: '123,456',
aroundLatLngViaIP: false,
});
});

it('configures aroundLatLng with a default position on clear event', () => {
const client = createFakeClient();
const helper = createFakekHelper(client);
const widget = algoliaPlacesWidget({ defaultPosition: [2, 2] });

helper.setQueryParameter('aroundLatLngViaIP', true);

widget.init({ helper });

const eventName = places.__instance.on.mock.calls[1][0];
Expand All @@ -144,22 +176,104 @@ describe('instantsearch widget', () => {
expect(helper.search).toBeCalled();
expect(helper.getState()).toMatchObject({
insideBoundingBox: undefined,
aroundLatLngViaIP: false,
aroundLatLng: '2,2',
});
});

it('restores aroundLatLngViaIP without a default position on clear event', () => {
const client = createFakeClient();
const helper = createFakekHelper(client);
const widget = algoliaPlacesWidget();

helper.setQueryParameter('aroundLatLngViaIP', true);

widget.init({ helper });

const changeEventName = places.__instance.on.mock.calls[0][0];
const changeEventListener = places.__instance.on.mock.calls[0][1];

expect(changeEventName).toEqual('change');

changeEventListener({
suggestion: {
latlng: {
lat: '123',
lng: '456',
},
},
});

expect(helper.search).toBeCalled();
expect(helper.getState()).toMatchObject({
insideBoundingBox: undefined,
aroundLatLng: '123,456',
aroundLatLngViaIP: false,
});

const clearEventName = places.__instance.on.mock.calls[1][0];
const clearEventListener = places.__instance.on.mock.calls[1][1];

expect(clearEventName).toEqual('clear');

clearEventListener();

expect(helper.search).toBeCalled();
expect(helper.getState()).toMatchObject({
insideBoundingBox: undefined,
aroundLatLng: undefined,
aroundLatLngViaIP: true,
});
});

describe('routing', () => {
const getInitializedWidget = (
widgetOptions = { defaultPosition: [2, 2] }
) => {
const client = createFakeClient();
const helper = createFakekHelper(client);
const widget = algoliaPlacesWidget(widgetOptions);

widget.init({ helper, state: helper.state });

return [widget, helper];
};

it('restores aroundLatLngViaIP on clear event', () => {
const client = createFakeClient();
const helper = createFakekHelper(client);
const widget = algoliaPlacesWidget();

// Simulate the fact that a widget set `aroundLatLngViaIP` from the URLSync
const searchParametersBefore = SearchParameters.make({
aroundLatLngViaIP: true,
});

const uiState = {
places: {
position: '123,123',
query: 'Paris',
},
};

widget.getWidgetSearchParameters(searchParametersBefore, {
uiState,
});

widget.init({ helper });

const clearEventListener = places.__instance.on.mock.calls[1][1];

clearEventListener();

expect(helper.search).toBeCalled();
expect(helper.getState()).toMatchObject({
insideBoundingBox: undefined,
aroundLatLng: undefined,
aroundLatLngViaIP: true,
});
});

describe('getWidgetState', () => {
test('should give back the object unmodified if the default value is selected', () => {
const [widget, helper] = getInitializedWidget();
Expand Down

0 comments on commit 29c2473

Please sign in to comment.