Skip to content

Commit

Permalink
fix(connectInfiniteHits): fix #2928 (#2939)
Browse files Browse the repository at this point in the history
* refactor(connectInfiniteHits): use jest instead of sinon in tests
* test(connectInfiniteHits): confirm #2928
* test(connectInfiniteHits): remove unsupported option from test
* fix(connectInfiniteHits): fix #2928
* refactor(connectInfiniteHits-test): review from @samouss
  • Loading branch information
bobylito authored and Alex S committed May 28, 2018
1 parent e782ab8 commit 0293a31
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 31 deletions.
145 changes: 115 additions & 30 deletions src/connectors/infinite-hits/__tests__/connectInfiniteHits-test.js
@@ -1,5 +1,3 @@
import sinon from 'sinon';

import jsHelper from 'algoliasearch-helper';
const SearchResults = jsHelper.SearchResults;

Expand All @@ -9,11 +7,10 @@ describe('connectInfiniteHits', () => {
it('Renders during init and render', () => {
// test that the dummyRendering is called with the isFirstRendering
// flag set accordingly
const rendering = sinon.stub();
const rendering = jest.fn();
const makeWidget = connectInfiniteHits(rendering);
const widget = makeWidget({
escapeHits: true,
hitsPerPage: 10,
});

expect(widget.getConfiguration()).toEqual({
Expand All @@ -22,10 +19,10 @@ describe('connectInfiniteHits', () => {
});

// test if widget is not rendered yet at this point
expect(rendering.callCount).toBe(0);
expect(rendering).toHaveBeenCalledTimes(0);

const helper = jsHelper({}, '');
helper.search = sinon.stub();
helper.search = jest.fn();

widget.init({
helper,
Expand All @@ -35,13 +32,21 @@ describe('connectInfiniteHits', () => {
});

// test that rendering has been called during init with isFirstRendering = true
expect(rendering.callCount).toBe(1);
expect(rendering).toHaveBeenCalledTimes(1);
// test if isFirstRendering is true during init
expect(rendering.lastCall.args[1]).toBe(true);
expect(rendering.lastCall.args[0].widgetParams).toEqual({
escapeHits: true,
hitsPerPage: 10,
});
expect(rendering).toHaveBeenLastCalledWith(
expect.objectContaining({
hits: [],
showMore: expect.any(Function),
results: undefined,
isLastPage: true,
instantSearchInstance: undefined,
widgetParams: {
escapeHits: true,
},
}),
true
);

widget.render({
results: new SearchResults(helper.state, [
Expand All @@ -54,22 +59,29 @@ describe('connectInfiniteHits', () => {
createURL: () => '#',
});

// test that rendering has been called during init with isFirstRendering = false
expect(rendering.callCount).toBe(2);
expect(rendering.lastCall.args[1]).toBe(false);
expect(rendering.lastCall.args[0].widgetParams).toEqual({
escapeHits: true,
hitsPerPage: 10,
});
expect(rendering).toHaveBeenCalledTimes(2);
expect(rendering).toHaveBeenLastCalledWith(
expect.objectContaining({
hits: [],
showMore: expect.any(Function),
results: expect.any(Object),
isLastPage: false,
instantSearchInstance: undefined,
widgetParams: {
escapeHits: true,
},
}),
false
);
});

it('Provides the hits and the whole results', () => {
const rendering = sinon.stub();
const rendering = jest.fn();
const makeWidget = connectInfiniteHits(rendering);
const widget = makeWidget();

const helper = jsHelper({}, '', {});
helper.search = sinon.stub();
helper.search = jest.fn();

widget.init({
helper,
Expand All @@ -78,7 +90,7 @@ describe('connectInfiniteHits', () => {
onHistoryChange: () => {},
});

const firstRenderingOptions = rendering.lastCall.args[0];
const firstRenderingOptions = rendering.mock.calls[0][0];
expect(firstRenderingOptions.hits).toEqual([]);
expect(firstRenderingOptions.results).toBe(undefined);

Expand All @@ -91,12 +103,12 @@ describe('connectInfiniteHits', () => {
createURL: () => '#',
});

const secondRenderingOptions = rendering.lastCall.args[0];
const secondRenderingOptions = rendering.mock.calls[1][0];
const { showMore } = secondRenderingOptions;
expect(secondRenderingOptions.hits).toEqual(hits);
expect(secondRenderingOptions.results).toEqual(results);
showMore();
expect(helper.search.callCount).toBe(1);
expect(helper.search).toHaveBeenCalledTimes(1);

// the results should accumulate if there is an increment in page
const otherHits = [{ fake: 'data 2' }, { sample: 'infos 2' }];
Expand All @@ -112,7 +124,7 @@ describe('connectInfiniteHits', () => {
createURL: () => '#',
});

const thirdRenderingOptions = rendering.lastCall.args[0];
const thirdRenderingOptions = rendering.mock.calls[2][0];
expect(thirdRenderingOptions.hits).toEqual([...hits, ...otherHits]);
expect(thirdRenderingOptions.results).toEqual(otherResults);

Expand All @@ -133,18 +145,18 @@ describe('connectInfiniteHits', () => {
createURL: () => '#',
});

const fourthRenderingOptions = rendering.lastCall.args[0];
const fourthRenderingOptions = rendering.mock.calls[3][0];
expect(fourthRenderingOptions.hits).toEqual(thirdHits);
expect(fourthRenderingOptions.results).toEqual(thirdResults);
});

it('escape highlight properties if requested', () => {
const rendering = sinon.stub();
const rendering = jest.fn();
const makeWidget = connectInfiniteHits(rendering);
const widget = makeWidget({ escapeHits: true });

const helper = jsHelper({}, '', {});
helper.search = sinon.stub();
helper.search = jest.fn();

widget.init({
helper,
Expand All @@ -153,7 +165,7 @@ describe('connectInfiniteHits', () => {
onHistoryChange: () => {},
});

const firstRenderingOptions = rendering.lastCall.args[0];
const firstRenderingOptions = rendering.mock.calls[0][0];
expect(firstRenderingOptions.hits).toEqual([]);
expect(firstRenderingOptions.results).toBe(undefined);

Expand Down Expand Up @@ -185,8 +197,81 @@ describe('connectInfiniteHits', () => {
},
];

const secondRenderingOptions = rendering.lastCall.args[0];
const secondRenderingOptions = rendering.mock.calls[1][0];
expect(secondRenderingOptions.hits).toEqual(escapedHits);
expect(secondRenderingOptions.results).toEqual(results);
});

it('does not render the same page twice', () => {
const rendering = jest.fn();
const makeWidget = connectInfiniteHits(rendering);
const widget = makeWidget({});

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

widget.init({
helper,
state: helper.state,
createURL: () => '#',
onHistoryChange: () => {},
});

widget.render({
results: new SearchResults(helper.state, [
{
hits: [{ objectID: 'a' }],
page: 0,
nbPages: 4,
},
]),
state: helper.state,
helper,
createURL: () => '#',
});

helper.setPage(1);

widget.render({
results: new SearchResults(helper.state, [
{
hits: [{ objectID: 'b' }],
page: 1,
nbPages: 4,
},
]),
state: helper.state,
helper,
createURL: () => '#',
});

expect(rendering).toHaveBeenCalledTimes(3);
expect(rendering).toHaveBeenLastCalledWith(
expect.objectContaining({
hits: [{ objectID: 'a' }, { objectID: 'b' }],
}),
false
);

widget.render({
results: new SearchResults(helper.state, [
{
hits: [{ objectID: 'b' }],
page: 1,
nbPages: 4,
},
]),
state: helper.state,
helper,
createURL: () => '#',
});

expect(rendering).toHaveBeenCalledTimes(4);
expect(rendering).toHaveBeenLastCalledWith(
expect.objectContaining({
hits: [{ objectID: 'a' }, { objectID: 'b' }],
}),
false
);
});
});
8 changes: 7 additions & 1 deletion src/connectors/infinite-hits/connectInfiniteHits.js
Expand Up @@ -79,6 +79,8 @@ export default function connectInfiniteHits(renderFn, unmountFn) {

return (widgetParams = {}) => {
let hitsCache = [];
let lastReceivedPage = -1;

const getShowMore = helper => () => helper.nextPage().search();

return {
Expand All @@ -105,6 +107,7 @@ export default function connectInfiniteHits(renderFn, unmountFn) {
render({ results, state, instantSearchInstance }) {
if (state.page === 0) {
hitsCache = [];
lastReceivedPage = -1;
}

if (
Expand All @@ -115,7 +118,10 @@ export default function connectInfiniteHits(renderFn, unmountFn) {
results.hits = escapeHits(results.hits);
}

hitsCache = [...hitsCache, ...results.hits];
if (lastReceivedPage < state.page) {
hitsCache = [...hitsCache, ...results.hits];
lastReceivedPage = state.page;
}

const isLastPage = results.nbPages <= results.page + 1;

Expand Down

0 comments on commit 0293a31

Please sign in to comment.