Skip to content

Commit

Permalink
core(instantsearch-manager): provide a fn for setting SearchParameters (
Browse files Browse the repository at this point in the history
#1471)

* core(instantsearch-manager): provide a fn for setting SearchParameters

FIX #1342

* core(InstantSearch): accept an optional setting object to send with the request
  • Loading branch information
bobylito authored and vvo committed Oct 26, 2016
1 parent 005d1f0 commit 4b0cd8f
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 11 deletions.
7 changes: 7 additions & 0 deletions packages/react-instantsearch/src/core/InstantSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ function validateNextProps(props, nextProps) {
* @propType {string} appId - The Algolia application id.
* @propType {string} apiKey - Your Algolia Search-Only API key.
* @propType {string} indexName - The index in which to search.
* @propType {object} [searchParameters] - Object containing query parameters to be sent to Algolia.
* It will be overriden by the search parameters resolved via the widgets. Typical use case:
* setting the distinct setting is done by providing an object like: `{distinct: 1}`. For more information
* about the kind of object that can be provided on the [official API documentation](https://www.algolia.com/doc/rest-api/search#full-text-search-parameters).
* @propType {bool=true} urlSync - Enables automatic synchronization of widgets state to the URL. See [URL Synchronization](#url-synchronization).
* @propType {object} history - A custom [history](https://github.com/ReactTraining/history) to push location to. Useful for quick integration with [React Router](https://github.com/reactjs/react-router). Takes precedence over urlSync. See [Custom History](#custom-history).
* @propType {number=700} threshold - Threshold in milliseconds above which new locations will be pushed to the history, instead of replacing the previous one. See [Location Debouncing](#location-debouncing).
Expand Down Expand Up @@ -118,6 +122,7 @@ class InstantSearch extends Component {
appId: props.appId,
apiKey: props.apiKey,
indexName: props.indexName,
searchParameters: props.searchParameters,

initialState,
});
Expand Down Expand Up @@ -208,6 +213,8 @@ InstantSearch.propTypes = {
apiKey: PropTypes.string.isRequired,
indexName: PropTypes.string.isRequired,

searchParameters: PropTypes.object,

history: PropTypes.object,
urlSync: PropTypes.bool,
threshold: PropTypes.number,
Expand Down
13 changes: 13 additions & 0 deletions packages/react-instantsearch/src/core/createConnector.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ import {omit, has} from 'lodash';

import {shallowEqual, getDisplayName} from './utils';

/**
* @typedef {object} ConnectorDescription
* @property {string} displayName - the displayName used by the wrapper
* @property {function} refine - a function to filter the local state
* @property {function} getSearchParameters - function transforming the local state to a SearchParameters
* @property {function} getMetadata - metadata of the widget
* @property {function} transitionState - hook after the state has changed
* @property {function} getProps - transform the state into props passed to the wrapped component.
* Receives (props, widgetStates, searchState, metadata) and returns the local state.
* @property {object} propTypes - PropTypes forwarded to the wrapped component.
* @property {object} defaultProps - default values for the props
*/

/**
* Connectors are the HOC used to transform React components
* into InstantSearch widgets.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,22 @@ import algoliasearchHelper, {SearchParameters} from 'algoliasearch-helper';
import createWidgetsManager from './createWidgetsManager';
import createStore from './createStore';

/**
* Creates a new instance of the InstantSearchManager which controls the widgets and
* trigger the search when the widgets are updated.
* @param {string} appId - the application ID
* @param {string} apiKey - the api key
* @param {string} indexName - the main index name
* @param {object} initialState - initial widget state
* @param {object} SearchParameters - optional additional parameters to send to the algolia API
* @return {InstantSearchManager} a new instance of InstantSearchManager
*/
export default function createInstantSearchManager({
appId,
apiKey,
indexName,
initialState,
searchParameters = {},
}) {
const client = algoliasearch(appId, apiKey);
const helper = algoliasearchHelper(client);
Expand All @@ -29,23 +40,24 @@ export default function createInstantSearchManager({
.map(widget => widget.getMetadata(state));
}

function getSearchParameters(searchParameters) {
function getSearchParameters(initialSearchParameters) {
return widgetsManager.getWidgets()
.filter(widget => Boolean(widget.getSearchParameters))
.reduce(
(res, widget) => widget.getSearchParameters(res),
searchParameters
initialSearchParameters
);
}

function search() {
const baseSP = new SearchParameters({index: indexName});
// @TODO: Provide a way to configure base SearchParameters.
// We previously had a `configureSearchParameters : SP -> SP` option.
// We could also just have a `baseSearchParameters : SP` option.
const searchParameters = getSearchParameters(baseSP);
const baseSP = new SearchParameters({
...searchParameters,
index: indexName,
});
const widgetSearchParameters = getSearchParameters(baseSP);

helper.searchOnce(searchParameters)
helper
.searchOnce(widgetSearchParameters)
.then(({content}) => {
store.setState({
...store.getState(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('createInstantSearchManager', () => {
let initialState;
let ism;

function init() {
function init(otherISMParameters = {}) {
createHrefForState = jest.fn(a => a);
onInternalStateUpdate = jest.fn();
initialState = {
Expand All @@ -46,6 +46,7 @@ describe('createInstantSearchManager', () => {
initialState,
createHrefForState,
onInternalStateUpdate,
...otherISMParameters,
});
}

Expand Down Expand Up @@ -133,7 +134,7 @@ describe('createInstantSearchManager', () => {
});
});

function testSearch(promise) {
function testSearch(promise, searchParameters = undefined) {
const helper = {
searchOnce: jest.fn(() => promise),
};
Expand All @@ -153,7 +154,7 @@ describe('createInstantSearchManager', () => {
},
],
}));
init();
init({searchParameters});
return helper.searchOnce;
}

Expand Down Expand Up @@ -182,6 +183,16 @@ describe('createInstantSearchManager', () => {
expect(params.query).toBe('hello');
expect(params.page).toBe(20);
});

it('when searching it adds the searchParameters if any', () => {
const searchOnce = testSearch(new Promise(() => null), {distinct: 1});
const onUpdate = createWidgetsManager.mock.calls[0][0];
onUpdate();
const params = searchOnce.mock.calls[0][0];
expect(params.query).toBe('hello');
expect(params.page).toBe(20);
expect(params.distinct).toBe(1);
});
});

describe('onExternalStateUpdate', () => {
Expand Down

0 comments on commit 4b0cd8f

Please sign in to comment.