From 2a84ee20d15c8d784df34e3aef2d132bf2a850e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chalifour?= Date: Tue, 28 May 2019 20:22:38 +0200 Subject: [PATCH] fix(connectSortBy): do not throw with wrong indexes (#3824) --- .../sort-by/__tests__/connectSortBy-test.js | 68 +++++++++++++++++++ src/connectors/sort-by/connectSortBy.js | 28 +++++--- src/widgets/sort-by/__tests__/sort-by-test.js | 29 ++------ 3 files changed, 91 insertions(+), 34 deletions(-) diff --git a/src/connectors/sort-by/__tests__/connectSortBy-test.js b/src/connectors/sort-by/__tests__/connectSortBy-test.js index e35eb4867c..3052058f95 100644 --- a/src/connectors/sort-by/__tests__/connectSortBy-test.js +++ b/src/connectors/sort-by/__tests__/connectSortBy-test.js @@ -218,6 +218,74 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/sort-by/js/ } }); + describe('options', () => { + describe('items', () => { + test('uses the helper index by default', () => { + const renderFn = jest.fn(); + const customSortBy = connectSortBy(renderFn); + const instantSearchInstance = instantSearch({ + indexName: '', + searchClient: { search() {} }, + }); + const helper = jsHelper({}, 'index_featured'); + helper.search = jest.fn(); + + const items = [ + { label: 'Featured', value: 'index_featured' }, + { label: 'Price asc.', value: 'index_price_asc' }, + { label: 'Price desc.', value: 'index_price_desc' }, + ]; + const widget = customSortBy({ items }); + + widget.init({ + helper, + state: helper.state, + createURL: () => '#', + instantSearchInstance, + }); + + expect(renderFn).toHaveBeenCalledTimes(1); + const [renderOptions] = renderFn.mock.calls[0]; + + expect(renderOptions.currentRefinement).toBe('index_featured'); + }); + + test('warns and falls back to the helper index if not present in the items', () => { + const renderFn = jest.fn(); + const customSortBy = connectSortBy(renderFn); + const instantSearchInstance = instantSearch({ + indexName: '', + searchClient: { search() {} }, + }); + const helper = jsHelper({}, 'index_initial'); + helper.search = jest.fn(); + + const items = [ + { label: 'Featured', value: 'index_featured' }, + { label: 'Price asc.', value: 'index_price_asc' }, + { label: 'Price desc.', value: 'index_price_desc' }, + ]; + const widget = customSortBy({ items }); + + expect(() => { + widget.init({ + helper, + state: helper.state, + createURL: () => '#', + instantSearchInstance, + }); + }).toWarnDev( + '[InstantSearch.js]: The index named "index_initial" is not listed in the `items` of `sortBy`.' + ); + + expect(renderFn).toHaveBeenCalledTimes(1); + const [firstRenderOptions] = renderFn.mock.calls[0]; + + expect(firstRenderOptions.currentRefinement).toBe('index_initial'); + }); + }); + }); + describe('routing', () => { const getInitializedWidget = (config = {}) => { const rendering = jest.fn(); diff --git a/src/connectors/sort-by/connectSortBy.js b/src/connectors/sort-by/connectSortBy.js index 271b5df18b..bcc796b174 100644 --- a/src/connectors/sort-by/connectSortBy.js +++ b/src/connectors/sort-by/connectSortBy.js @@ -2,6 +2,7 @@ import { checkRendering, createDocumentationMessageGenerator, find, + warning, } from '../../lib/utils'; const withUsage = createDocumentationMessageGenerator({ @@ -100,21 +101,25 @@ export default function connectSortBy(renderFn, unmountFn) { return { init({ helper, instantSearchInstance }) { - const currentIndex = helper.getIndex(); - const isIndexInList = find(items, item => item.value === currentIndex); + const initialIndex = helper.state.index; + const isInitialIndexInItems = find( + items, + item => item.value === initialIndex + ); - if (!isIndexInList) { - throw new Error( - `[sortBy]: Index ${currentIndex} not present in \`items\`` - ); - } + this.initialIndex = initialIndex; + this.setIndex = indexName => { + helper.setIndex(indexName).search(); + }; - this.initialIndex = instantSearchInstance.indexName; - this.setIndex = indexName => helper.setIndex(indexName).search(); + warning( + isInitialIndexInItems, + `The index named "${initialIndex}" is not listed in the \`items\` of \`sortBy\`.` + ); renderFn( { - currentRefinement: currentIndex, + currentRefinement: initialIndex, options: transformItems(items), refine: this.setIndex, hasNoResults: true, @@ -128,7 +133,7 @@ export default function connectSortBy(renderFn, unmountFn) { render({ helper, results, instantSearchInstance }) { renderFn( { - currentRefinement: helper.getIndex(), + currentRefinement: helper.state.index, options: transformItems(items), refine: this.setIndex, hasNoResults: results.nbHits === 0, @@ -141,6 +146,7 @@ export default function connectSortBy(renderFn, unmountFn) { dispose({ state }) { unmountFn(); + return state.setIndex(this.initialIndex); }, diff --git a/src/widgets/sort-by/__tests__/sort-by-test.js b/src/widgets/sort-by/__tests__/sort-by-test.js index 9289a9d5f7..34e372953b 100644 --- a/src/widgets/sort-by/__tests__/sort-by-test.js +++ b/src/widgets/sort-by/__tests__/sort-by-test.js @@ -1,4 +1,5 @@ import { render } from 'preact-compat'; +import algoliasearchHelper from 'algoliasearch-helper'; import sortBy from '../sort-by'; import instantSearch from '../../../lib/main'; @@ -34,7 +35,7 @@ describe('sortBy()', () => { render.mockClear(); const instantSearchInstance = instantSearch({ - indexName: 'defaultIndex', + indexName: '', searchClient: { search() {}, }, @@ -51,11 +52,10 @@ describe('sortBy()', () => { item: 'custom-item', }; widget = sortBy({ container, items, cssClasses }); - helper = { - getIndex: jest.fn().mockReturnValue('index-a'), - setIndex: jest.fn().mockReturnThis(), - search: jest.fn(), - }; + + helper = algoliasearchHelper({}, 'index-a'); + helper.setIndex = jest.fn().mockReturnThis(); + helper.search = jest.fn(); results = { hits: [], @@ -99,21 +99,4 @@ describe('sortBy()', () => { expect(helper.setIndex).toHaveBeenCalledTimes(1); expect(helper.search).toHaveBeenCalledTimes(1); }); - - it('should throw if there is no name attribute in a passed object', () => { - items.length = 0; - items.push({ label: 'Label without a name' }); - - expect(() => { - widget.init({ helper }); - }).toThrow(/Index index-a not present/); - }); - - it('must include the current index at initialization time', () => { - helper.getIndex = jest.fn().mockReturnValue('non-existing-index'); - - expect(() => { - widget.init({ helper }); - }).toThrow(/Index non-existing-index not present/); - }); });