Skip to content

Commit

Permalink
feat(connectSearchBox): clear the state on dispose (#3822)
Browse files Browse the repository at this point in the history
* test(connectSearchBox): calls the unmount function

* feat(connectSearchBox): use noop for unmount

* feat(connectSearchBox): remove query on dispose

* test(connectSearchBox): rename jsHelper -> algoliasearchHelper

* test(connectSearchBox): consistent names for render/unmount function
  • Loading branch information
samouss authored and Haroenv committed Oct 23, 2019
1 parent 5b8ef49 commit 940522c
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 69 deletions.
151 changes: 83 additions & 68 deletions src/connectors/search-box/__tests__/connectSearchBox-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import jsHelper, {
import algoliasearchHelper, {
SearchResults,
SearchParameters,
} from 'algoliasearch-helper';
Expand All @@ -18,18 +18,15 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
});

it('Renders during init and render', () => {
// test that the dummyRendering is called with the isFirstRendering
// flag set accordingly
const rendering = jest.fn();
const makeWidget = connectSearchBox(rendering);

const renderFn = jest.fn();
const makeWidget = connectSearchBox(renderFn);
const widget = makeWidget({
foo: 'bar', // dummy param passed to `renderFn`
foo: 'bar',
});

expect(widget.getConfiguration).toBe(undefined);

const helper = jsHelper({});
const helper = algoliasearchHelper({});
helper.search = () => {};

widget.init({
Expand All @@ -39,10 +36,8 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
onHistoryChange: () => {},
});

// should call the rendering once with isFirstRendering to true
expect(rendering).toHaveBeenCalledTimes(1);
// should provide good values for the first rendering
expect(rendering).toHaveBeenLastCalledWith(
expect(renderFn).toHaveBeenCalledTimes(1);
expect(renderFn).toHaveBeenLastCalledWith(
expect.objectContaining({
query: '',
widgetParams: { foo: 'bar' },
Expand All @@ -58,10 +53,8 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
searchMetadata: { isSearchStalled: false },
});

// Should call the rendering a second time, with isFirstRendering to false
expect(rendering).toHaveBeenCalledTimes(2);
// should provide good values after the first search
expect(rendering).toHaveBeenLastCalledWith(
expect(renderFn).toHaveBeenCalledTimes(2);
expect(renderFn).toHaveBeenLastCalledWith(
expect.objectContaining({
query: '',
widgetParams: { foo: 'bar' },
Expand All @@ -70,21 +63,12 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
);
});

it('does not throw without the unmount function', () => {
const rendering = () => {};
const makeWidget = connectSearchBox(rendering);
const widget = makeWidget({});
const helper = jsHelper({});
expect(() => widget.dispose({ helper, state: helper.state })).not.toThrow();
});

it('Provides a function to update the refinements at each step', () => {
const rendering = jest.fn();
const makeWidget = connectSearchBox(rendering);

const renderFn = jest.fn();
const makeWidget = connectSearchBox(renderFn);
const widget = makeWidget();

const helper = jsHelper({});
const helper = algoliasearchHelper({});
helper.search = jest.fn();

widget.init({
Expand All @@ -95,8 +79,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
});

{
// first rendering
const { refine, query } = rendering.mock.calls[0][0];
const { refine, query } = renderFn.mock.calls[0][0];
expect(helper.state.query).toBeUndefined();
expect(query).toBe('');
refine('bip');
Expand All @@ -113,8 +96,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
});

{
// Second rendering
const { refine, query } = rendering.mock.calls[1][0];
const { refine, query } = renderFn.mock.calls[1][0];
expect(helper.state.query).toBe('bip');
expect(query).toBe('bip');
refine('bop');
Expand All @@ -124,12 +106,11 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
});

it('provides a function to clear the query and perform new search', () => {
const rendering = jest.fn();
const makeWidget = connectSearchBox(rendering);

const renderFn = jest.fn();
const makeWidget = connectSearchBox(renderFn);
const widget = makeWidget();

const helper = jsHelper({}, '', {
const helper = algoliasearchHelper({}, '', {
query: 'bup',
});
helper.search = jest.fn();
Expand All @@ -142,9 +123,8 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
});

{
// first rendering
expect(helper.state.query).toBe('bup');
const { refine, clear } = rendering.mock.calls[0][0];
const { refine, clear } = renderFn.mock.calls[0][0];
clear(); // triggers a search
expect(helper.state.query).toBe('');
expect(helper.search).toHaveBeenCalledTimes(1);
Expand All @@ -160,31 +140,27 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
});

{
// Second rendering
expect(helper.state.query).toBe('bip');
const { clear } = rendering.mock.calls[1][0];
clear(); // triggers a search
const { clear } = renderFn.mock.calls[1][0];
clear();
expect(helper.state.query).toBe('');
// refine and clear functions trigger searches. clear + refine + clear
expect(helper.search).toHaveBeenCalledTimes(3);
}
});

it('queryHook parameter let the dev control the behavior of the search', () => {
const rendering = jest.fn();
const makeWidget = connectSearchBox(rendering);

// letSearchThrough will control if the provided function should be called
let letSearchThrough = false;
const queryHook = jest.fn((q, search) => {
if (letSearchThrough) search(q);
});

const renderFn = jest.fn();
const makeWidget = connectSearchBox(renderFn);
const widget = makeWidget({
queryHook,
});

const helper = jsHelper({});
const helper = algoliasearchHelper({});
helper.search = jest.fn();

widget.init({
Expand All @@ -195,8 +171,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
});

{
// first rendering
const { refine } = rendering.mock.calls[0][0];
const { refine } = renderFn.mock.calls[0][0];

refine('bip');
expect(queryHook).toHaveBeenCalledTimes(1);
Expand All @@ -211,7 +186,6 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
expect(helper.search).toHaveBeenCalledTimes(1);
}

// reset the hook behavior
letSearchThrough = false;

widget.render({
Expand All @@ -223,8 +197,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
});

{
// Second rendering
const { refine } = rendering.mock.calls[1][0];
const { refine } = renderFn.mock.calls[1][0];

refine('bop');
expect(queryHook).toHaveBeenCalledTimes(3);
Expand All @@ -240,12 +213,11 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
});

it('should always provide the same refine() and clear() function reference', () => {
const rendering = jest.fn();
const makeWidget = connectSearchBox(rendering);

const renderFn = jest.fn();
const makeWidget = connectSearchBox(renderFn);
const widget = makeWidget();

const helper = jsHelper({});
const helper = algoliasearchHelper({});
helper.search = () => {};

widget.init({
Expand All @@ -263,7 +235,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
searchMetadata: { isSearchStalled: false },
});

const firstRenderOptions = rendering.mock.calls[0][0];
const firstRenderOptions = renderFn.mock.calls[0][0];

widget.render({
results: new SearchResults(helper.state, [{}]),
Expand All @@ -273,19 +245,18 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
searchMetadata: { isSearchStalled: false },
});

const secondRenderOptions = rendering.mock.calls[1][0];
const secondRenderOptions = renderFn.mock.calls[1][0];

expect(firstRenderOptions.clear).toBe(secondRenderOptions.clear);
expect(firstRenderOptions.refine).toBe(secondRenderOptions.refine);
});

it('should clear on init as well', () => {
const rendering = jest.fn();
const makeWidget = connectSearchBox(rendering);

const renderFn = jest.fn();
const makeWidget = connectSearchBox(renderFn);
const widget = makeWidget();

const helper = jsHelper({});
const helper = algoliasearchHelper({});
helper.search = jest.fn();
helper.setQuery('foobar');

Expand All @@ -298,24 +269,68 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
onHistoryChange: () => {},
});

const { clear } = rendering.mock.calls[0][0];
const { clear } = renderFn.mock.calls[0][0];
clear();

expect(helper.state.query).toBe('');
expect(helper.search).toHaveBeenCalledTimes(1);
});

describe('dispose', () => {
it('calls the unmount function', () => {
const helper = algoliasearchHelper({}, '');

const renderFn = () => {};
const unmountFn = jest.fn();
const makeWidget = connectSearchBox(renderFn, unmountFn);
const widget = makeWidget();

expect(unmountFn).toHaveBeenCalledTimes(0);

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

expect(unmountFn).toHaveBeenCalledTimes(1);
});

it('does not throw without the unmount function', () => {
const helper = algoliasearchHelper({}, '');

const renderFn = () => {};
const makeWidget = connectSearchBox(renderFn);
const widget = makeWidget();

expect(() =>
widget.dispose({ helper, state: helper.state })
).not.toThrow();
});

it('removes the `query` from the `SearchParameters`', () => {
const helper = algoliasearchHelper({}, '', {
query: 'Apple',
});

const renderFn = () => {};
const makeWidget = connectSearchBox(renderFn);
const widget = makeWidget();

expect(helper.state.query).toBe('Apple');

const nextState = widget.dispose({ helper, state: helper.state });

expect(nextState.query).toBeUndefined();
});
});

describe('routing', () => {
const getInitializedWidget = (config = {}) => {
const rendering = jest.fn();
const makeWidget = connectSearchBox(rendering);

const renderFn = jest.fn();
const makeWidget = connectSearchBox(renderFn);
const widget = makeWidget({
...config,
});

const initialConfig = {};
const helper = jsHelper({}, '', initialConfig);
const helper = algoliasearchHelper({}, '', initialConfig);
helper.search = jest.fn();

widget.init({
Expand All @@ -325,7 +340,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/
onHistoryChange: () => {},
});

const { refine } = rendering.mock.calls[0][0];
const { refine } = renderFn.mock.calls[0][0];

return [widget, helper, refine];
};
Expand Down
2 changes: 1 addition & 1 deletion src/connectors/search-box/connectSearchBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export default function connectSearchBox(renderFn, unmountFn = noop) {
dispose({ state }) {
unmountFn();

return state.setQuery('');
return state.setQueryParameter('query', undefined);
},

getWidgetState(uiState, { searchParameters }) {
Expand Down

0 comments on commit 940522c

Please sign in to comment.