diff --git a/packages/instantsearch-core/src/__tests__/RoutingManager.test.ts b/packages/instantsearch-core/src/__tests__/RoutingManager.test.ts index df91c4c5bb..5a81740036 100644 --- a/packages/instantsearch-core/src/__tests__/RoutingManager.test.ts +++ b/packages/instantsearch-core/src/__tests__/RoutingManager.test.ts @@ -4,6 +4,7 @@ import { createSearchClient } from '@instantsearch/mocks'; import { wait } from '@instantsearch/testutils/wait'; +import { createWidget } from 'instantsearch-core/test/createWidget'; import qs from 'qs'; import { @@ -12,7 +13,6 @@ import { connectHitsPerPage, connectSearchBox, } from '..'; -import { createWidget } from '../../test/createWidget'; import type { Router, UiState, StateMapping, IndexUiState } from '../types'; import type { JSDOM } from 'jsdom'; diff --git a/packages/instantsearch-core/src/__tests__/instantsearch-integration.test.ts b/packages/instantsearch-core/src/__tests__/instantsearch-integration.test.ts index d32cc8b082..033dd128a7 100644 --- a/packages/instantsearch-core/src/__tests__/instantsearch-integration.test.ts +++ b/packages/instantsearch-core/src/__tests__/instantsearch-integration.test.ts @@ -6,60 +6,15 @@ import { createSearchClient } from '@instantsearch/mocks'; import { createRecommendSearchClient } from '@instantsearch/mocks/fixtures'; import { castToJestMock } from '@instantsearch/testutils'; import { wait } from '@instantsearch/testutils/wait'; -import { getByText, fireEvent } from '@testing-library/dom'; import { instantsearch, - connectConfigure, connectSearchBox, connectFrequentlyBoughtTogether, } from '..'; import type { MiddlewareDefinition } from '../types'; -describe('configure', () => { - it('provides up-to-date uiState to onStateChange', () => { - const container = document.createElement('div'); - const onStateChange = jest.fn(); - const search = instantsearch({ - indexName: 'instant_search', - searchClient: createSearchClient(), - onStateChange({ uiState, setUiState }) { - onStateChange(uiState); - setUiState(uiState); - }, - }); - const customComp = connectConfigure(({ refine }, isFirstRendering) => { - if (isFirstRendering) { - const button = document.createElement('button'); - button.setAttribute('type', 'button'); - button.textContent = 'click me'; - container.appendChild(button); - container.querySelector('button')!.addEventListener('click', () => { - refine({ hitsPerPage: 4 }); - }); - } - }); - search.addWidgets([ - connectConfigure(() => {})({ - searchParameters: { - hitsPerPage: 10, - }, - }), - customComp({ searchParameters: {} }), - ]); - - search.start(); - expect(onStateChange).not.toHaveBeenCalled(); - - fireEvent.click(getByText(container, 'click me')); - expect(onStateChange).toHaveBeenCalledTimes(1); - expect(onStateChange).toHaveBeenCalledWith({ - instant_search: { configure: { hitsPerPage: 4 } }, - }); - }); -}); - describe('middleware', () => { it("runs middlewares' onStateChange when uiState changes", async () => { const search = instantsearch({ diff --git a/packages/instantsearch-core/src/__tests__/instantsearch.test.tsx b/packages/instantsearch-core/src/__tests__/instantsearch.test.tsx index 89786f6b9a..edfd09d23e 100644 --- a/packages/instantsearch-core/src/__tests__/instantsearch.test.tsx +++ b/packages/instantsearch-core/src/__tests__/instantsearch.test.tsx @@ -12,6 +12,10 @@ import { import { castToJestMock } from '@instantsearch/testutils/castToJestMock'; import { wait } from '@instantsearch/testutils/wait'; import originalHelper from 'algoliasearch-helper'; +import { + createRenderOptions, + createWidget, +} from 'instantsearch-core/test/createWidget'; import { h, render, createRef } from 'preact'; import { @@ -21,7 +25,6 @@ import { connectSearchBox, connectPagination, } from '..'; -import { createRenderOptions, createWidget } from '../../test/createWidget'; import version from '../version'; import type { diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectAutocomplete.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectAutocomplete.test.ts index c7c636608e..5f0ce561f5 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectAutocomplete.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectAutocomplete.test.ts @@ -8,13 +8,13 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectAutocomplete, instantsearch, TAG_PLACEHOLDER } from '../..'; import { createInitOptions, createRenderOptions, createDisposeOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectAutocomplete, instantsearch, TAG_PLACEHOLDER } from '../..'; import type { AutocompleteRenderState } from '../..'; import type { SearchClient, SearchResponse } from '../../types'; @@ -336,112 +336,21 @@ search.addWidgets([ }); describe('dispose', () => { - it('calls the unmount function', () => { - const searchClient = createSearchClient(); - const helper = algoliasearchHelper(searchClient, ''); - + it('calls unmount function', () => { const render = jest.fn(); const unmount = jest.fn(); - const makeWidget = connectAutocomplete(render, unmount); - const widget = makeWidget({}); - widget.init!(createInitOptions({ helper })); + const widget = connectAutocomplete(render, unmount)({}); - expect(unmount).toHaveBeenCalledTimes(0); + widget.dispose!(createDisposeOptions()); - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); - - expect(unmount).toHaveBeenCalledTimes(1); + expect(unmount).toHaveBeenCalled(); }); it('does not throw without the unmount function', () => { - const searchClient = createSearchClient(); - const helper = algoliasearchHelper(searchClient, ''); - - const render = jest.fn(); - const makeWidget = connectAutocomplete(render); - const widget = makeWidget({}); - - widget.init!(createInitOptions({ helper })); - - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - it('removes the `query` from the `SearchParameters`', () => { - const searchClient = createSearchClient(); - const helper = algoliasearchHelper(searchClient, '', { - query: 'Apple', - }); - - const render = jest.fn(); - const makeWidget = connectAutocomplete(render); - const widget = makeWidget({}); - - widget.init!(createInitOptions({ helper })); - - expect(helper.state.query).toBe('Apple'); - - const nextState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ) as SearchParameters; - - expect(nextState.query).toBeUndefined(); - }); - - it('removes the TAG_PLACEHOLDER from the `SearchParameters`', () => { - const searchClient = createSearchClient(); - const helper = algoliasearchHelper(searchClient, '', { - ...TAG_PLACEHOLDER, - }); - - const render = jest.fn(); - const makeWidget = connectAutocomplete(render); - const widget = makeWidget({}); - - expect(helper.state.highlightPreTag).toBe( - TAG_PLACEHOLDER.highlightPreTag - ); - - expect(helper.state.highlightPostTag).toBe( - TAG_PLACEHOLDER.highlightPostTag - ); - - widget.init!(createInitOptions({ helper })); - - const nextState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ) as SearchParameters; - - expect(nextState.highlightPreTag).toBeUndefined(); - expect(nextState.highlightPostTag).toBeUndefined(); - }); - - it('does not remove the TAG_PLACEHOLDER from the `SearchParameters` with `escapeHTML` disabled', () => { - const searchClient = createSearchClient(); - const helper = algoliasearchHelper(searchClient, '', { - highlightPreTag: '', - highlightPostTag: '', - }); - - const render = jest.fn(); - const makeWidget = connectAutocomplete(render); - const widget = makeWidget({ - escapeHTML: false, - }); - - expect(helper.state.highlightPreTag).toBe(''); - expect(helper.state.highlightPostTag).toBe(''); - - widget.init!(createInitOptions({ helper })); - - const nextState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ) as SearchParameters; - - expect(nextState.highlightPreTag).toBe(''); - expect(nextState.highlightPostTag).toBe(''); + const render = () => {}; + const widget = connectAutocomplete(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectBreadcrumb.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectBreadcrumb.test.ts index 111b74c851..26660db7eb 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectBreadcrumb.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectBreadcrumb.test.ts @@ -6,13 +6,13 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectBreadcrumb, warnCache } from '../..'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectBreadcrumb, warnCache } from '../..'; describe('connectBreadcrumb', () => { describe('Usage', () => { @@ -1243,42 +1243,24 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/ }); describe('dispose', () => { - it('does not throw without the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), ''); + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - const renderFn = () => {}; - const makeWidget = connectBreadcrumb(renderFn); - const widget = makeWidget({ attributes: ['category'] }); + const widget = connectBreadcrumb( + render, + unmount + )({ attributes: ['cat'] }); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - it('does not remove refinement', () => { - const renderFn = () => {}; - const makeWidget = connectBreadcrumb(renderFn); - const widget = makeWidget({ attributes: ['category'] }); + widget.dispose!(createDisposeOptions()); - const helper = algoliasearchHelper(createSearchClient(), '', { - hierarchicalFacetsRefinements: { - category: ['boxes'], - }, - }); - helper.search = jest.fn(); - - widget.init!( - createInitOptions({ - helper, - state: helper.state, - }) - ); - - const newState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ); + expect(unmount).toHaveBeenCalled(); + }); - expect(newState).toBeUndefined(); + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectBreadcrumb(render)({ attributes: ['cat'] }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectClearRefinements.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectClearRefinements.test.ts index df58df05e7..450e326856 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectClearRefinements.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectClearRefinements.test.ts @@ -3,13 +3,13 @@ import { createSearchClient, } from '@instantsearch/mocks'; import algoliasearchHelper, { SearchResults } from 'algoliasearch-helper'; - -import { connectClearRefinements } from '../..'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectClearRefinements } from '../..'; describe('connectClearRefinements', () => { describe('Usage', () => { @@ -125,15 +125,23 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/clear-refin expect(secondRenderingOptions.canRefine).toBe(false); }); - it('does not throw without the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), 'indexName'); - const rendering = () => {}; - const makeWidget = connectClearRefinements(rendering); - const widget = makeWidget({}); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectClearRefinements(render, unmount)({}); + + widget.dispose!(createDisposeOptions()); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectClearRefinements(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); }); describe('getRenderState', () => { diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectConfigure.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectConfigure.test.ts index eeeb9064ea..379dcbbdac 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectConfigure.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectConfigure.test.ts @@ -1,12 +1,12 @@ import { createSearchClient } from '@instantsearch/mocks'; +import { wait } from '@instantsearch/testutils'; import algoliasearchHelper, { SearchParameters } from 'algoliasearch-helper'; - -import { connectConfigure, noop } from '../..'; import { createInitOptions, createRenderOptions, - createDisposeOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectConfigure, instantsearch, noop } from '../..'; import type { AlgoliaSearchHelper } from 'algoliasearch-helper'; @@ -88,7 +88,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j }); expect( - widget.getWidgetSearchParameters(new SearchParameters({}), { + widget.getWidgetSearchParameters!(new SearchParameters({}), { uiState: {}, }) ).toEqual( @@ -107,11 +107,11 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j }); expect( - widget.getWidgetSearchParameters( + widget.getWidgetSearchParameters!( new SearchParameters({ analytics: false, }), - { uiState: { configure: { analytics: true } } } + { uiState: {} } ) ).toEqual( new SearchParameters({ @@ -120,12 +120,12 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j ); expect( - widget.getWidgetSearchParameters( + widget.getWidgetSearchParameters!( new SearchParameters({ analytics: false, clickAnalytics: true, }), - { uiState: { configure: { analytics: true } } } + { uiState: {} } ) ).toEqual( new SearchParameters({ @@ -135,7 +135,13 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j ); }); - it('should apply new searchParameters on refine()', () => { + it('should apply new searchParameters on refine()', async () => { + const searchClient = createSearchClient(); + const search = instantsearch({ + searchClient, + indexName: 'indexName', + }); + search.start(); const renderFn = jest.fn(); const makeWidget = connectConfigure(renderFn, jest.fn()); const widget = makeWidget({ @@ -144,41 +150,45 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j }, }); - helper.setState( - widget.getWidgetSearchParameters( + search.addWidgets([widget]); + + search.helper!.setState( + widget.getWidgetSearchParameters!( new SearchParameters({ // This facet is added outside of the widget params // so it shouldn't be overridden when calling `refine`. facets: ['brand'], }), - { uiState: { configure: { analytics: true } } } + { uiState: {} } ) ); - widget.init!(createInitOptions({ helper })); expect( - widget.getWidgetSearchParameters(new SearchParameters({}), { - uiState: { configure: { analytics: true } }, + widget.getWidgetSearchParameters!(new SearchParameters({}), { + uiState: {}, }) ).toEqual( new SearchParameters({ analytics: true, }) ); - expect(helper.state).toEqual( - new SearchParameters({ - analytics: true, - facets: ['brand'], - }) - ); + + await wait(100); + expect(searchClient.search).toHaveBeenCalledTimes(1); + expect(searchClient.search).toHaveBeenLastCalledWith([ + { + indexName: 'indexName', + params: { analytics: true, facets: ['brand'] }, + }, + ]); const { refine } = renderFn.mock.calls[0][0]; refine({ hitsPerPage: 3, facets: ['rating'] }); expect( - widget.getWidgetSearchParameters(new SearchParameters({}), { - uiState: { configure: { hitsPerPage: 3, facets: ['rating'] } }, + widget.getWidgetSearchParameters!(new SearchParameters({}), { + uiState: {}, }) ).toEqual( new SearchParameters({ @@ -186,57 +196,57 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j facets: ['rating'], }) ); - expect(helper.state).toEqual( - new SearchParameters({ - hitsPerPage: 3, - facets: ['brand', 'rating'], - }) - ); + await wait(100); + expect(searchClient.search).toHaveBeenCalledTimes(2); + expect(searchClient.search).toHaveBeenLastCalledWith([ + { + indexName: 'indexName', + params: { + hitsPerPage: 3, + analytics: true, + facets: ['brand', 'rating'], + }, + }, + ]); }); - it('should dispose only the state set by configure', () => { - const makeWidget = connectConfigure(noop); - const widget = makeWidget({ - searchParameters: { - analytics: true, - }, + it('should dispose only the state set by configure', async () => { + const search = instantsearch({ + searchClient: createSearchClient(), + indexName: 'indexName', }); + search.start(); - helper.setState( - widget.getWidgetSearchParameters( - new SearchParameters({ - clickAnalytics: true, - }), - { uiState: { configure: { analytics: true } } } - ) - ); - widget.init!(createInitOptions({ helper })); + const analytics = connectConfigure(noop)({ + searchParameters: { analytics: true }, + }); + const clickAnalytics = connectConfigure(noop)({ + searchParameters: { clickAnalytics: true }, + }); - expect( - widget.getWidgetSearchParameters(new SearchParameters({}), { - uiState: { configure: { analytics: true } }, - }) - ).toEqual( - new SearchParameters({ - analytics: true, - }) - ); - expect(helper.state).toEqual( - new SearchParameters({ - analytics: true, - clickAnalytics: true, - }) - ); + search.addWidgets([analytics]); - const nextState = widget.dispose!( - createDisposeOptions({ state: helper.state }) - ); + await wait(100); + expect(search.client.search).toHaveBeenCalledWith([ + { indexName: 'indexName', params: { analytics: true } }, + ]); - expect(nextState).toEqual( - new SearchParameters({ - clickAnalytics: true, - }) - ); + search.addWidgets([clickAnalytics]); + + await wait(100); + expect(search.client.search).toHaveBeenCalledWith([ + { + indexName: 'indexName', + params: { analytics: true, clickAnalytics: true }, + }, + ]); + + search.removeWidgets([analytics]); + + await wait(100); + expect(search.client.search).toHaveBeenCalledWith([ + { indexName: 'indexName', params: { clickAnalytics: true } }, + ]); }); describe('getRenderState', () => { @@ -364,101 +374,6 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j }); }); - describe('getWidgetUiState', () => { - it('adds default parameters', () => { - const makeWidget = connectConfigure(noop); - const widget = makeWidget({ - searchParameters: { - analytics: true, - }, - }); - - expect( - widget.getWidgetUiState({}, { helper, searchParameters: helper.state }) - ).toEqual({ - configure: { analytics: true }, - }); - }); - - it('adds refined parameters', () => { - const renderFn = jest.fn(); - const makeWidget = connectConfigure(renderFn); - const widget = makeWidget({ - searchParameters: { - analytics: true, - }, - }); - - widget.init!(createInitOptions({ helper })); - const { refine } = renderFn.mock.calls[0][0]; - - refine({ analytics: false }); - - expect( - widget.getWidgetUiState({}, { helper, searchParameters: helper.state }) - ).toEqual({ - configure: { analytics: false }, - }); - }); - - it('adds refined (new) parameters', () => { - const renderFn = jest.fn(); - const makeWidget = connectConfigure(renderFn); - const widget = makeWidget({ - searchParameters: { - analytics: true, - }, - }); - - widget.init!(createInitOptions({ helper })); - const { refine } = renderFn.mock.calls[0][0]; - - refine({ query: 'unsafe toys' }); - - expect( - widget.getWidgetUiState({}, { helper, searchParameters: helper.state }) - ).toEqual({ - configure: { query: 'unsafe toys' }, - }); - }); - - it('merges with existing configuration', () => { - const makeWidget = connectConfigure(noop); - const widget = makeWidget({ - searchParameters: { - analytics: true, - }, - }); - - expect( - widget.getWidgetUiState( - { configure: { queryType: 'prefixAll' } }, - { helper, searchParameters: helper.state } - ) - ).toEqual({ - configure: { analytics: true, queryType: 'prefixAll' }, - }); - }); - - it('overwrites existing configuration', () => { - const makeWidget = connectConfigure(noop); - const widget = makeWidget({ - searchParameters: { - analytics: true, - }, - }); - - expect( - widget.getWidgetUiState( - { configure: { analytics: false } }, - { helper, searchParameters: helper.state } - ) - ).toEqual({ - configure: { analytics: true }, - }); - }); - }); - describe('getWidgetSearchParameters', () => { it('returns parameters set by default', () => { const makeWidget = connectConfigure(noop); @@ -468,71 +383,13 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j }, }); - const sp = widget.getWidgetSearchParameters(new SearchParameters(), { + const sp = widget.getWidgetSearchParameters!(new SearchParameters(), { uiState: {}, }); expect(sp).toEqual(new SearchParameters({ analytics: true })); }); - it('returns parameters set by uiState', () => { - const makeWidget = connectConfigure(noop); - const widget = makeWidget({ searchParameters: {} }); - - const sp = widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: { - configure: { - analytics: false, - }, - }, - }); - - expect(sp).toEqual(new SearchParameters({ analytics: false })); - }); - - it('overrides parameters set by uiState', () => { - const makeWidget = connectConfigure(noop); - const widget = makeWidget({ - searchParameters: { - analytics: true, - }, - }); - - const sp = widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: { - configure: { - analytics: false, - }, - }, - }); - - expect(sp).toEqual(new SearchParameters({ analytics: true })); - }); - - it('merges parameters set by uiState', () => { - const makeWidget = connectConfigure(noop); - const widget = makeWidget({ - searchParameters: { - analyticsTags: ['best-website-in-the-world'], - }, - }); - - const sp = widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: { - configure: { - analytics: false, - }, - }, - }); - - expect(sp).toEqual( - new SearchParameters({ - analytics: false, - analyticsTags: ['best-website-in-the-world'], - }) - ); - }); - it('merges with the previous parameters', () => { const makeWidget = connectConfigure(noop); const widget = makeWidget({ @@ -544,7 +401,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j }, }); - const sp = widget.getWidgetSearchParameters( + const sp = widget.getWidgetSearchParameters!( new SearchParameters({ disjunctiveFacets: ['categories'], disjunctiveFacetsRefinements: { @@ -581,7 +438,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/configure/j refine({ analyticsTags: ['worst-site-now'] }); - const sp = widget.getWidgetSearchParameters(new SearchParameters(), { + const sp = widget.getWidgetSearchParameters!(new SearchParameters(), { uiState: {}, }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectCurrentRefinements.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectCurrentRefinements.test.ts index e57289e6cb..b1eb110f64 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectCurrentRefinements.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectCurrentRefinements.test.ts @@ -6,13 +6,13 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectCurrentRefinements } from '../..'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectCurrentRefinements } from '../..'; import type { CurrentRefinementsConnectorParamsItem } from '../connectCurrentRefinements'; import type { AlgoliaSearchHelper } from 'algoliasearch-helper'; @@ -116,15 +116,23 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/current-ref }); }); - it('does not throw without the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), 'indexName', {}); - const rendering = () => {}; - const customCurrentRefinements = connectCurrentRefinements(rendering); - const widget = customCurrentRefinements({}); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectCurrentRefinements(render, unmount)({}); + + widget.dispose!(createDisposeOptions()); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectCurrentRefinements(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); }); describe('getRenderState', () => { diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectDynamicWidgets.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectDynamicWidgets.test.ts index 00db3fc488..e2f06f8fbd 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectDynamicWidgets.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectDynamicWidgets.test.ts @@ -9,6 +9,11 @@ import algoliasearchHelper, { SearchParameters, SearchResults, } from 'algoliasearch-helper'; +import { + createDisposeOptions, + createInitOptions, + createRenderOptions, +} from 'instantsearch-core/test/createWidget'; import { connectHierarchicalMenu, @@ -17,11 +22,6 @@ import { connectDynamicWidgets, index, } from '../..'; -import { - createDisposeOptions, - createInitOptions, - createRenderOptions, -} from '../../../test/createWidget'; import type { SearchResponse } from '../../types'; import type { DynamicWidgetsConnectorParams } from '../connectDynamicWidgets'; diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectFrequentlyBoughtTogether.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectFrequentlyBoughtTogether.test.ts index 0d6fce2cbe..21dd32a46a 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectFrequentlyBoughtTogether.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectFrequentlyBoughtTogether.test.ts @@ -4,12 +4,13 @@ import { createSearchClient } from '@instantsearch/mocks'; import algoliasearchHelper, { RecommendParameters } from 'algoliasearch-helper'; - -import { connectFrequentlyBoughtTogether } from '../..'; import { + createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectFrequentlyBoughtTogether } from '../..'; describe('connectFrequentlyBoughtTogether', () => { it('throws without render function', () => { @@ -92,6 +93,30 @@ describe('connectFrequentlyBoughtTogether', () => { ); }); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectFrequentlyBoughtTogether( + render, + unmount + )({ objectIDs: ['1'] }); + + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectFrequentlyBoughtTogether(render)({ + objectIDs: ['1'], + }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); + }); + describe('getWidgetParameters', () => { it('forwards widgetParams to the recommend state', () => { const render = () => {}; diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectGeoSearch.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectGeoSearch.test.ts index 6c072d1109..6a41ad6cb9 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectGeoSearch.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectGeoSearch.test.ts @@ -8,14 +8,14 @@ import algoliasearchHelper, { SearchParameters, SearchResults, } from 'algoliasearch-helper'; - -import { connectGeoSearch, instantsearch } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectGeoSearch, instantsearch } from '../..'; import type { SearchResponse } from '../../types'; @@ -1379,31 +1379,20 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/geo-search/ }); describe('dispose', () => { - it('expect reset insideBoundingBox', () => { + it('calls unmount function', () => { const render = jest.fn(); const unmount = jest.fn(); - const customGeoSearch = connectGeoSearch(render, unmount); - const widget = customGeoSearch({}); - const helper = createFakeHelper(); + const widget = connectGeoSearch(render, unmount)({}); - // @ts-ignore - helper.setQueryParameter('insideBoundingBox', '10,12,12,14'); - - const expectation = new SearchParameters({ index: '' }); - - const actual = widget.dispose!( - createDisposeOptions({ state: helper.state }) - ); + widget.dispose!(createDisposeOptions()); expect(unmount).toHaveBeenCalled(); - expect(actual).toEqual(expectation); }); it('does not throw without the unmount function', () => { const render = () => {}; - const customGeoSearch = connectGeoSearch(render); - const widget = customGeoSearch({}); + const widget = connectGeoSearch(render)({}); expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectHierarchicalMenu.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectHierarchicalMenu.test.ts index 839b726d93..577fb53c3a 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectHierarchicalMenu.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectHierarchicalMenu.test.ts @@ -6,14 +6,14 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectHierarchicalMenu, warnCache } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectHierarchicalMenu, warnCache } from '../..'; describe('connectHierarchicalMenu', () => { describe('Usage', () => { @@ -513,78 +513,24 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica }); describe('dispose', () => { - it('does not throw without the unmount function', () => { - const rendering = jest.fn(); - const makeWidget = connectHierarchicalMenu(rendering); - const widget = makeWidget({ - attributes: ['category'], - }); - const helper = algoliasearchHelper( - createSearchClient(), - '', - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - it('unsets maxValuesPerFacet fully', () => { - const rendering = jest.fn(); - const makeWidget = connectHierarchicalMenu(rendering); - const indexName = ''; - const widget = makeWidget({ - attributes: ['category'], - }); - const helper = algoliasearchHelper( - createSearchClient(), - indexName, - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - - expect( - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).toEqual(new SearchParameters({ index: indexName })); - }); - - it('unsets refinement', () => { - const rendering = jest.fn(); - const makeWidget = connectHierarchicalMenu(rendering); - const indexName = ''; - const widget = makeWidget({ - attributes: ['category'], - }); - const helper = algoliasearchHelper( - createSearchClient(), - indexName, - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - helper.search = jest.fn(); + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - widget.init!( - createInitOptions({ - helper, - state: helper.state, - }) - ); + const widget = connectHierarchicalMenu( + render, + unmount + )({ attributes: ['cat'] }); - const firstRenderingOptions = rendering.mock.calls[0][0]; - const { refine } = firstRenderingOptions; - refine('zombo.com'); + widget.dispose!(createDisposeOptions()); - expect(helper.state.hierarchicalFacetsRefinements).toEqual({ - category: ['zombo.com'], - }); + expect(unmount).toHaveBeenCalled(); + }); - expect( - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).toEqual(new SearchParameters({ index: indexName })); + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectHierarchicalMenu(render)({ attributes: ['cat'] }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectHits.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectHits.test.ts index b0973c7154..270f7e9f2e 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectHits.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectHits.test.ts @@ -12,14 +12,14 @@ import algoliasearchHelper, { SearchParameters, SearchResults, } from 'algoliasearch-helper'; - -import { connectHits, instantsearch, TAG_PLACEHOLDER } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectHits, instantsearch, TAG_PLACEHOLDER } from '../..'; import type { EscapedHits, @@ -638,85 +638,21 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hits/js/#co }); describe('dispose', () => { - it('calls the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), ''); + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - const renderFn = () => {}; - const unmountFn = jest.fn(); - const makeWidget = connectHits(renderFn, unmountFn); - const widget = makeWidget({}); + const widget = connectHits(render, unmount)({}); - expect(unmountFn).toHaveBeenCalledTimes(0); + widget.dispose!(createDisposeOptions()); - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); - - expect(unmountFn).toHaveBeenCalledTimes(1); + expect(unmount).toHaveBeenCalled(); }); it('does not throw without the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), ''); - - const renderFn = () => {}; - const makeWidget = connectHits(renderFn); - const widget = makeWidget({}); - - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - it('removes the TAG_PLACEHOLDER from the `SearchParameters`', () => { - const helper = algoliasearchHelper(createSearchClient(), '', { - ...TAG_PLACEHOLDER, - }); - - const renderFn = () => {}; - const makeWidget = connectHits(renderFn); - const widget = makeWidget({}); - - expect(helper.state.highlightPreTag).toBe( - TAG_PLACEHOLDER.highlightPreTag - ); - - expect(helper.state.highlightPostTag).toBe( - TAG_PLACEHOLDER.highlightPostTag - ); - - const nextState = widget.dispose!( - createDisposeOptions({ - helper, - state: helper.state, - }) - ); - - expect((nextState as SearchParameters).highlightPreTag).toBeUndefined(); - expect((nextState as SearchParameters).highlightPostTag).toBeUndefined(); - }); - - it('does not remove the TAG_PLACEHOLDER from the `SearchParameters` with `escapeHTML` disabled', () => { - const helper = algoliasearchHelper(createSearchClient(), '', { - highlightPreTag: '', - highlightPostTag: '', - }); - - const renderFn = () => {}; - const makeWidget = connectHits(renderFn); - const widget = makeWidget({ - escapeHTML: false, - }); - - expect(helper.state.highlightPreTag).toBe(''); - expect(helper.state.highlightPostTag).toBe(''); - - const nextState = widget.dispose!( - createDisposeOptions({ - helper, - state: helper.state, - }) - ); - - expect((nextState as SearchParameters).highlightPreTag).toBe(''); - expect((nextState as SearchParameters).highlightPostTag).toBe(''); + const render = () => {}; + const widget = connectHits(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectHitsPerPage.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectHitsPerPage.test.ts index 3b2bc06ef5..b0afb98bb0 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectHitsPerPage.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectHitsPerPage.test.ts @@ -6,13 +6,13 @@ import algoliasearchHelper, { SearchParameters, SearchResults, } from 'algoliasearch-helper'; - -import { connectHitsPerPage } from '../..'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectHitsPerPage } from '../..'; import type { HitsPerPageConnectorParams } from '../connectHitsPerPage'; @@ -662,74 +662,28 @@ You may want to add another entry to the \`items\` option with this value.`); }); describe('dispose', () => { - it('calls the unmount function', () => { - const searchClient = createSearchClient(); - const helper = algoliasearchHelper(searchClient, ''); - - const renderFn = () => {}; - const unmountFn = jest.fn(); - const makeWidget = connectHitsPerPage(renderFn, unmountFn); - const widget = makeWidget({ - items: [ - { value: 3, label: '3 items per page', default: true }, - { value: 10, label: '10 items per page' }, - ], - }); + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - expect(unmountFn).toHaveBeenCalledTimes(0); + const widget = connectHitsPerPage( + render, + unmount + )({ items: [{ label: '10 items per page', value: 10, default: true }] }); - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); + widget.dispose!(createDisposeOptions()); - expect(unmountFn).toHaveBeenCalledTimes(1); + expect(unmount).toHaveBeenCalled(); }); it('does not throw without the unmount function', () => { - const searchClient = createSearchClient(); - const helper = algoliasearchHelper(searchClient, ''); - - const renderFn = () => {}; - const makeWidget = connectHitsPerPage(renderFn); - const widget = makeWidget({ - items: [ - { value: 3, label: '3 items per page', default: true }, - { value: 10, label: '10 items per page' }, - ], - }); - - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - it('removes `hitsPerPage` from the `SearchParameters`', () => { - const searchClient = createSearchClient(); - const helper = algoliasearchHelper(searchClient, '', { - hitsPerPage: 5, - }); - - const renderFn = () => {}; - const unmountFn = jest.fn(); - const makeWidget = connectHitsPerPage(renderFn, unmountFn); - const widget = makeWidget({ - items: [ - { value: 3, label: '3 items per page', default: true }, - { value: 10, label: '10 items per page' }, - ], + const render = () => {}; + const widget = connectHitsPerPage(render)({ + items: [{ label: '10 items per page', value: 10, default: true }], }); - - expect(helper.state.hitsPerPage).toBe(5); - - const nextState = widget.dispose!( - createDisposeOptions({ - helper, - state: helper.state, - }) - ) as SearchParameters; - - expect(nextState.hitsPerPage).toBeUndefined(); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); - describe('getRenderState', () => { test('returns the render state', () => { const renderFn = jest.fn(); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectInfiniteHits.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectInfiniteHits.test.ts index 261d89ff69..2b7378fb25 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectInfiniteHits.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectInfiniteHits.test.ts @@ -9,14 +9,14 @@ import { } from '@instantsearch/mocks'; import { wait } from '@instantsearch/testutils/wait'; import algoliasearchHelper, { SearchResults } from 'algoliasearch-helper'; - -import { connectInfiniteHits, instantsearch, TAG_PLACEHOLDER } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectInfiniteHits, instantsearch, TAG_PLACEHOLDER } from '../..'; import { createInfiniteHitsSessionStorageCache } from '../../lib/infiniteHitsCache'; import type { @@ -26,7 +26,6 @@ import type { EscapedHits, SearchResponse, } from '../../types'; -import type { SearchParameters } from 'algoliasearch-helper'; jest.mock('../../lib/utils/addAbsolutePosition', () => ({ // The real implementation creates a new array instance, which can cause bugs, @@ -1127,106 +1126,21 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/infinite-hi }); describe('dispose', () => { - it('calls the unmount function', () => { - const helper = algoliasearchHelper({} as SearchClient, '', {}); - - const renderFn = (): void => {}; - const unmountFn = jest.fn(); - const makeWidget = connectInfiniteHits(renderFn, unmountFn); - const widget = makeWidget({}); + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - expect(unmountFn).toHaveBeenCalledTimes(0); + const widget = connectInfiniteHits(render, unmount)({}); - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); + widget.dispose!(createDisposeOptions()); - expect(unmountFn).toHaveBeenCalledTimes(1); + expect(unmount).toHaveBeenCalled(); }); it('does not throw without the unmount function', () => { - const helper = algoliasearchHelper({} as SearchClient, '', {}); - - const renderFn = (): void => {}; - const makeWidget = connectInfiniteHits(renderFn); - const widget = makeWidget({}); - - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - it('removes the TAG_PLACEHOLDER from the `SearchParameters`', () => { - const helper = algoliasearchHelper({} as SearchClient, '', { - ...TAG_PLACEHOLDER, - }); - - const renderFn = (): void => {}; - const makeWidget = connectInfiniteHits(renderFn); - const widget = makeWidget({}); - - expect(helper.state.highlightPreTag).toBe( - TAG_PLACEHOLDER.highlightPreTag - ); - - expect(helper.state.highlightPostTag).toBe( - TAG_PLACEHOLDER.highlightPostTag - ); - - const nextState = widget.dispose!( - createDisposeOptions({ - helper, - state: helper.state, - }) - ); - - expect((nextState as SearchParameters).highlightPreTag).toBeUndefined(); - expect((nextState as SearchParameters).highlightPostTag).toBeUndefined(); - }); - - it('does not remove the TAG_PLACEHOLDER from the `SearchParameters` with `escapeHTML` disabled', () => { - const helper = algoliasearchHelper({} as SearchClient, '', { - highlightPreTag: '', - highlightPostTag: '', - }); - - const renderFn = (): void => {}; - const makeWidget = connectInfiniteHits(renderFn); - const widget = makeWidget({ - escapeHTML: false, - }); - - expect(helper.state.highlightPreTag).toBe(''); - expect(helper.state.highlightPostTag).toBe(''); - - const nextState = widget.dispose!( - createDisposeOptions({ - helper, - state: helper.state, - }) - ); - - expect((nextState as SearchParameters).highlightPreTag).toBe(''); - expect((nextState as SearchParameters).highlightPostTag).toBe(''); - }); - - it('removes the `page` from the `SearchParameters`', () => { - const helper = algoliasearchHelper({} as SearchClient, '', { - page: 5, - }); - - const renderFn = (): void => {}; - const makeWidget = connectInfiniteHits(renderFn); - const widget = makeWidget({}); - - expect(helper.state.page).toBe(5); - - const nextState = widget.dispose!( - createDisposeOptions({ - helper, - state: helper.state, - }) - ); - - expect((nextState as SearchParameters).page).toBeUndefined(); + const render = () => {}; + const widget = connectInfiniteHits(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectLookingSimilar.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectLookingSimilar.test.ts index 80eae3c1d8..c9e5eeed97 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectLookingSimilar.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectLookingSimilar.test.ts @@ -4,12 +4,13 @@ import { createSearchClient } from '@instantsearch/mocks'; import algoliasearchHelper, { RecommendParameters } from 'algoliasearch-helper'; - -import { connectLookingSimilar } from '../..'; import { + createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectLookingSimilar } from '../..'; describe('connectLookingSimilar', () => { it('throws without render function', () => { @@ -92,6 +93,28 @@ describe('connectLookingSimilar', () => { ); }); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectLookingSimilar( + render, + unmount + )({ objectIDs: ['1'] }); + + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectLookingSimilar(render)({ objectIDs: ['1'] }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); + }); + describe('getWidgetParameters', () => { it('forwards widgetParams to the recommend state', () => { const render = () => {}; diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectMenu.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectMenu.test.ts index 70785e60f6..62a143d210 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectMenu.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectMenu.test.ts @@ -6,14 +6,14 @@ import jsHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectMenu, warnCache } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectMenu, warnCache } from '../..'; import type { MenuRenderState, MenuConnector } from '../..'; @@ -576,20 +576,23 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co ); }); - it('does not throw without the unmount function', () => { - const widget = connectMenu(() => {})({ - attribute: 'category', + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectMenu(render, unmount)({ attribute: 's' }); + + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectMenu(render)({ attribute: 's' }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); - const helper = jsHelper( - createSearchClient(), - '', - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); }); describe('getRenderState', () => { @@ -1455,171 +1458,6 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co }); }); - describe('dispose', () => { - it('removes hierarchical refinements', () => { - const widget = makeWidget({ - attribute: 'myFacet', - limit: 10, - showMore: true, - }); - const indexName = 'instant_search'; - - const helper = jsHelper( - createSearchClient(), - indexName, - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - helper.search = jest.fn(); - - expect(helper.state).toEqual( - new SearchParameters({ - hierarchicalFacets: [ - { - attributes: ['myFacet'], - name: 'myFacet', - }, - ], - hierarchicalFacetsRefinements: { - myFacet: [], - }, - maxValuesPerFacet: 20, - index: indexName, - }) - ); - - widget.init!( - createInitOptions({ - helper, - state: helper.state, - createURL: () => '#', - instantSearchInstance: createInstantSearch(), - }) - ); - - widget.render!( - createRenderOptions({ - results: new SearchResults(helper.state, [ - createSingleSearchResponse({ - hits: [], - facets: { - myFacet: { - Decoration: 880, - }, - }, - }), - createSingleSearchResponse({ - facets: { - myFacet: { - Decoration: 880, - Outdoor: 47, - }, - }, - }), - ]), - state: helper.state, - helper, - createURL: () => '#', - }) - ); - - const { refine } = rendering.mock.calls[0][0]; - - refine('Decoration'); - - expect(helper.state).toEqual( - new SearchParameters({ - hierarchicalFacets: [ - { - attributes: ['myFacet'], - name: 'myFacet', - }, - ], - hierarchicalFacetsRefinements: { - myFacet: ['Decoration'], - }, - index: indexName, - maxValuesPerFacet: 20, - }) - ); - - const newState = widget.dispose!( - createDisposeOptions({ state: helper.state, helper }) - ); - - expect(newState).toEqual( - new SearchParameters({ - index: indexName, - }) - ); - }); - - it('removes unrefined state', () => { - const widget = makeWidget({ - attribute: 'myFacet', - limit: 10, - showMore: true, - }); - const indexName = 'instant_search'; - - const helper = jsHelper( - createSearchClient(), - indexName, - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - helper.search = jest.fn(); - - expect(helper.state).toEqual( - new SearchParameters({ - hierarchicalFacets: [ - { - attributes: ['myFacet'], - name: 'myFacet', - }, - ], - hierarchicalFacetsRefinements: { - myFacet: [], - }, - maxValuesPerFacet: 20, - index: indexName, - }) - ); - - const newState = widget.dispose!( - createDisposeOptions({ state: helper.state, helper }) - ); - - expect(newState).toEqual( - new SearchParameters({ - index: indexName, - }) - ); - }); - - it('leaves empty state intact', () => { - const state = new SearchParameters(); - const widget = makeWidget({ - attribute: 'myFacet', - limit: 10, - showMore: true, - }); - const helper = jsHelper( - createSearchClient(), - 'test', - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - helper.search = jest.fn(); - const newState = widget.dispose!(createDisposeOptions({ state, helper })); - - expect(newState).toEqual(new SearchParameters()); - }); - }); - describe('insights', () => { const createInitializedWidget = () => { const widget = makeWidget({ diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectNumericMenu.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectNumericMenu.test.ts index 5a72026e1c..fde3caf05e 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectNumericMenu.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectNumericMenu.test.ts @@ -10,13 +10,13 @@ import jsHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectNumericMenu } from '../..'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectNumericMenu } from '../..'; import type { NumericMenuConnectorParamsItem, @@ -828,26 +828,40 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/numeric-men expect(helper.state.page).toBeUndefined(); }); - it('does not throw without the unmount function', () => { - const rendering = () => {}; - const makeWidget = connectNumericMenu(rendering); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - const widget = makeWidget({ - attribute: 'numerics', - items: [ - { label: 'below 10', end: 10 }, - { label: '10 - 20', start: 10, end: 20 }, - { label: 'more than 20', start: 20 }, - { label: '42', start: 42, end: 42 }, - { label: 'void' }, - ], - }); + const widget = connectNumericMenu( + render, + unmount + )({ + attribute: 'a', + items: [ + { label: 'below 10', end: 10 }, + { label: '10 - 20', start: 10, end: 20 }, + { label: 'more than 20', start: 20 }, + ], + }); - const helper = jsHelper(createSearchClient(), ''); + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectNumericMenu(render)({ + attribute: 'a', + items: [ + { label: 'below 10', end: 10 }, + { label: '10 - 20', start: 10, end: 20 }, + { label: 'more than 20', start: 20 }, + ], + }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); }); describe('getWidgetUiState', () => { diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectPagination.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectPagination.test.ts index e6dbd384b1..e3cd4cab8b 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectPagination.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectPagination.test.ts @@ -6,13 +6,13 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectPagination } from '../..'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectPagination } from '../..'; import type { PaginationConnectorParams, @@ -303,54 +303,21 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/pagination/ }); describe('dispose', () => { - it('calls the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), ''); - - const renderFn = () => {}; - const unmountFn = jest.fn(); - const makeWidget = connectPagination(renderFn, unmountFn); - const widget = makeWidget({}); + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - expect(unmountFn).toHaveBeenCalledTimes(0); + const widget = connectPagination(render, unmount)({}); - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); + widget.dispose!(createDisposeOptions()); - expect(unmountFn).toHaveBeenCalledTimes(1); + expect(unmount).toHaveBeenCalled(); }); it('does not throw without the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), ''); - - const renderFn = () => {}; - const makeWidget = connectPagination(renderFn); - const widget = makeWidget({}); - - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - it('removes the `page` from the `SearchParameters`', () => { - const helper = algoliasearchHelper(createSearchClient(), '', { - page: 5, - }); - - const renderFn = () => {}; - const makeWidget = connectPagination(renderFn); - const widget = makeWidget({}); - - expect(helper.state.page).toBe(5); - - const nextState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ); - - // error used for typescript - if (!nextState) { - throw new Error('expect state to be returned'); - } - - expect((nextState as SearchParameters).page).toBeUndefined(); + const render = () => {}; + const widget = connectPagination(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectPoweredBy.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectPoweredBy.test.ts index cdf1ef1ce2..6868f4e0f5 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectPoweredBy.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectPoweredBy.test.ts @@ -2,15 +2,13 @@ * @jest-environment jsdom */ -import { createSearchClient } from '@instantsearch/mocks'; -import jsHelper from 'algoliasearch-helper'; - -import { connectPoweredBy } from '../..'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectPoweredBy } from '../..'; describe('connectPoweredBy', () => { it('throws without rendering function', () => { @@ -117,14 +115,23 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/powered-by/ ); }); - it('does not throw without the unmount function', () => { - const rendering = () => {}; - const makeWidget = connectPoweredBy(rendering); - const widget = makeWidget({}); - const helper = jsHelper(createSearchClient(), ''); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectPoweredBy(render, unmount)({}); + + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectPoweredBy(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); }); describe('getWidgetRenderState', () => { diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectQueryRules.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectQueryRules.test.ts index 6a4a5867f2..1975c5803e 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectQueryRules.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectQueryRules.test.ts @@ -6,14 +6,14 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectQueryRules } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectQueryRules } from '../..'; import type { TransformItems } from '../../types'; import type { AlgoliaSearchHelper as Helper } from 'algoliasearch-helper'; @@ -183,40 +183,24 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/query-rules expect(widgetParams).toEqual({}); } }); + }); - test('calls the unmount function on dispose', () => { - const helper = createFakeHelper(); - const { makeWidget, unmountFn } = createWidget(); - const widget = makeWidget({}); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - widget.init!( - createInitOptions({ - helper, - state: helper.state, - }) - ); + const widget = connectQueryRules(render, unmount)({}); - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); + widget.dispose!(createDisposeOptions()); - expect(unmountFn).toHaveBeenCalledTimes(1); + expect(unmount).toHaveBeenCalled(); }); - test('does not throw without the unmount function', () => { - const helper = createFakeHelper(); - const rendering = () => {}; - const makeWidget = connectQueryRules(rendering); - const widget = makeWidget({}); - - widget.init!( - createInitOptions({ - state: helper.state, - helper, - }) - ); - - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectQueryRules(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); @@ -920,104 +904,6 @@ Consider using \`transformRuleContexts\` to minimize the number of rules sent to 'ais-brand-Speck', ]); }); - - test('reinitializes the rule contexts on dispose', () => { - const helper = createFakeHelper({ - disjunctiveFacets: ['brand'], - ruleContexts: ['initial-rule'], - }); - const { makeWidget } = createWidget(); - const widget = makeWidget({ - trackedFilters: { - brand: (values) => values, - }, - }); - - widget.init!( - createInitOptions({ - helper, - state: helper.state, - }) - ); - - helper.setState({ - disjunctiveFacetsRefinements: { - brand: ['Samsung', 'Apple'], - }, - }); - - widget.render!( - createRenderOptions({ - helper, - state: helper.state, - results: new SearchResults(helper.state, [ - createSingleSearchResponse(), - createSingleSearchResponse({ - facets: { - brand: { - Samsung: 100, - Apple: 100, - }, - }, - }), - ]), - }) - ); - - expect(helper.state.ruleContexts).toEqual([ - 'initial-rule', - 'ais-brand-Samsung', - 'ais-brand-Apple', - ]); - - const nextState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ); - - expect((nextState as SearchParameters).ruleContexts).toEqual([ - 'initial-rule', - ]); - }); - - test('stops tracking filters after dispose', () => { - const helper = createFakeHelper({ - disjunctiveFacets: ['brand'], - disjunctiveFacetsRefinements: { - brand: ['Samsung'], - }, - }); - const brandFilterSpy = jest.fn((values) => values); - const { makeWidget } = createWidget(); - const widget = makeWidget({ - trackedFilters: { - brand: brandFilterSpy, - }, - }); - - expect(helper.state.ruleContexts).toEqual(undefined); - - widget.init!( - createInitOptions({ - helper, - state: helper.state, - }) - ); - - expect(helper.state.ruleContexts).toEqual(['ais-brand-Samsung']); - expect(brandFilterSpy).toHaveBeenCalledTimes(1); - expect(brandFilterSpy).toHaveBeenCalledWith(['Samsung']); - - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); - - helper.setState({ - disjunctiveFacetsRefinements: { - brand: ['Samsung', 'Apple'], - }, - }); - - expect(helper.state.ruleContexts).toEqual(undefined); - expect(brandFilterSpy).toHaveBeenCalledTimes(1); - }); }); describe('transformRuleContexts', () => { diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectRange.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectRange.test.ts index ec8701b910..2c8985dedc 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectRange.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectRange.test.ts @@ -6,14 +6,14 @@ import jsHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectRange, instantsearch } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectRange, instantsearch } from '../..'; import type { AlgoliaSearchHelper } from 'algoliasearch-helper'; @@ -1266,88 +1266,21 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/range-input }); describe('dispose', () => { - it('does not throw without the unmount function', () => { - const rendering = () => {}; - const makeWidget = connectRange(rendering); - const attribute = 'price'; - const widget = makeWidget({ attribute }); - const helper = jsHelper( - createSearchClient(), - '', - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - it('removes empty refinement', () => { - const rendering = () => {}; - const makeWidget = connectRange(rendering); - const attribute = 'price'; - const indexName = ''; - const widget = makeWidget({ attribute }); - const helper = jsHelper( - createSearchClient(), - indexName, - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - - const newState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ); - - expect(newState).toEqual(new SearchParameters({ index: indexName })); - }); - - it('removes active refinement', () => { - const rendering = jest.fn(); - const makeWidget = connectRange(rendering); - const attribute = 'price'; - const indexName = ''; - const widget = makeWidget({ attribute }); - const helper = jsHelper( - createSearchClient(), - indexName, - widget.getWidgetSearchParameters(new SearchParameters(), { - uiState: {}, - }) - ); - helper.search = jest.fn(); - - widget.init!( - createInitOptions({ - helper, - }) - ); - - const renderOptions = rendering.mock.calls[0][0]; - const { refine } = renderOptions; + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - refine([100, 1000]); + const widget = connectRange(render, unmount)({ attribute: 's' }); - expect(helper.state).toEqual( - new SearchParameters({ - index: indexName, - disjunctiveFacets: ['price'], - numericRefinements: { - price: { - '<=': [1000], - '>=': [100], - }, - }, - }) - ); + widget.dispose!(createDisposeOptions()); - const newState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ); + expect(unmount).toHaveBeenCalled(); + }); - expect(newState).toEqual(new SearchParameters({ index: indexName })); + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectRange(render)({ attribute: 's' }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectRatingMenu.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectRatingMenu.test.ts index 0e95d40c58..b3543d0124 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectRatingMenu.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectRatingMenu.test.ts @@ -6,14 +6,14 @@ import jsHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectRatingMenu } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectRatingMenu } from '../..'; describe('connectRatingMenu', () => { const getInitializedWidget = (config = {}, unmount = () => {}) => { @@ -311,69 +311,21 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/rating-menu }); describe('dispose', () => { - it('does not throw without the unmount function', () => { - const { widget, helper } = getInitializedWidget(); - - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - test('calls the unmount function', () => { - const unmount = jest.fn(); - const { widget, helper } = getInitializedWidget({}, unmount); - - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); - - expect(unmount).toHaveBeenCalledTimes(1); - }); - - test('resets the state', () => { + it('calls unmount function', () => { const render = jest.fn(); - const makeWidget = connectRatingMenu(render); - const indexName = 'indexName'; - const attribute = 'grade'; - const helper = jsHelper(createSearchClient(), indexName, { - disjunctiveFacets: [attribute], - numericRefinements: { - [attribute]: { - '>=': [4], - }, - }, - }); - helper.search = jest.fn(); + const unmount = jest.fn(); - const widget = makeWidget({ - attribute, - }); + const widget = connectRatingMenu(render, unmount)({ attribute: 's' }); - expect(helper.state).toEqual( - new SearchParameters({ - index: indexName, - disjunctiveFacets: [attribute], - numericRefinements: { - grade: { - '>=': [4], - }, - }, - }) - ); + widget.dispose!(createDisposeOptions()); - const nextState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ); + expect(unmount).toHaveBeenCalled(); + }); - expect(nextState).toEqual( - new SearchParameters({ - index: indexName, - disjunctiveFacets: [attribute], - numericRefinements: { - grade: { - '>=': [], - }, - }, - }) - ); + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectRatingMenu(render)({ attribute: 's' }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectRefinementList.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectRefinementList.test.ts index 8c442e5e16..42e30db62f 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectRefinementList.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectRefinementList.test.ts @@ -9,14 +9,14 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectRefinementList, TAG_PLACEHOLDER, warnCache } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectRefinementList, TAG_PLACEHOLDER, warnCache } from '../..'; describe('connectRefinementList', () => { const createWidgetFactory = () => { @@ -2057,208 +2057,26 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- const widget = makeWidget({ attribute: 'myFacet', }); - const helper = algoliasearchHelper( - createSearchClient(), - '', - widget.getWidgetSearchParameters(new SearchParameters({}), { - uiState: {}, - }) - ); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); describe('dispose', () => { - it('removes refinements completely on dispose (and)', () => { - const rendering = jest.fn(); - const makeWidget = connectRefinementList(rendering); - const instantSearchInstance = createInstantSearch(); - - const widget = makeWidget({ - attribute: 'category', - operator: 'and', - }); - - const indexName = 'my-index'; - const helper = algoliasearchHelper( - createSearchClient(), - indexName, - widget.getWidgetSearchParameters(new SearchParameters({}), { - uiState: {}, - }) - ); - helper.search = jest.fn(); - - widget.init!( - createInitOptions({ - helper, - state: helper.state, - createURL: () => '#', - instantSearchInstance, - }) - ); - - widget.render!( - createRenderOptions({ - results: new SearchResults(helper.state, [ - createSingleSearchResponse({ - hits: [], - facets: { - category: { - c1: 880, - c2: 47, - }, - }, - }), - createSingleSearchResponse({ - facets: { - category: { - c1: 880, - c2: 47, - }, - }, - }), - ]), - state: helper.state, - helper, - }) - ); - - const { refine } = rendering.mock.calls[0][0]; - - expect(helper.state).toEqual( - new SearchParameters({ - facets: ['category'], - facetsRefinements: { - category: [], - }, - index: indexName, - maxValuesPerFacet: 10, - }) - ); + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - refine('zimbo'); + const widget = connectRefinementList(render, unmount)({ attribute: 's' }); - expect(helper.state).toEqual( - new SearchParameters({ - facets: ['category'], - facetsRefinements: { - category: ['zimbo'], - }, - index: indexName, - maxValuesPerFacet: 10, - }) - ); + widget.dispose!(createDisposeOptions()); - const newState = widget.dispose!( - createDisposeOptions({ - state: helper.state, - helper, - }) - ); - - expect(newState).toEqual( - new SearchParameters({ - index: indexName, - }) - ); + expect(unmount).toHaveBeenCalled(); }); - it('removes refinements completely on dispose (or)', () => { - const rendering = jest.fn(); - const makeWidget = connectRefinementList(rendering); - const instantSearchInstance = createInstantSearch(); - - const widget = makeWidget({ - attribute: 'category', - operator: 'or', - }); - - const indexName = 'my-index'; - const helper = algoliasearchHelper( - createSearchClient(), - indexName, - widget.getWidgetSearchParameters(new SearchParameters({}), { - uiState: {}, - }) - ); - helper.search = jest.fn(); - - widget.init!( - createInitOptions({ - helper, - state: helper.state, - createURL: () => '#', - instantSearchInstance, - }) - ); - - widget.render!( - createRenderOptions({ - results: new SearchResults(helper.state, [ - createSingleSearchResponse({ - hits: [], - facets: { - category: { - c1: 880, - c2: 47, - }, - }, - }), - createSingleSearchResponse({ - facets: { - category: { - c1: 880, - c2: 47, - }, - }, - }), - ]), - state: helper.state, - helper, - }) - ); - - const { refine } = rendering.mock.calls[0][0]; - - expect(helper.state).toEqual( - new SearchParameters({ - disjunctiveFacets: ['category'], - disjunctiveFacetsRefinements: { - category: [], - }, - index: indexName, - maxValuesPerFacet: 10, - }) - ); - - refine('zimbo'); - - expect(helper.state).toEqual( - new SearchParameters({ - disjunctiveFacets: ['category'], - disjunctiveFacetsRefinements: { - category: ['zimbo'], - }, - index: indexName, - maxValuesPerFacet: 10, - }) - ); - - const newState = widget.dispose!( - createDisposeOptions({ - state: helper.state, - helper, - }) - ); - - expect(newState).toEqual( - new SearchParameters({ - index: indexName, - }) - ); + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectRefinementList(render)({ attribute: 's' }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectRelatedProducts.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectRelatedProducts.test.ts index 87dafe09eb..e28c804972 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectRelatedProducts.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectRelatedProducts.test.ts @@ -4,12 +4,13 @@ import { createSearchClient } from '@instantsearch/mocks'; import algoliasearchHelper, { RecommendParameters } from 'algoliasearch-helper'; - -import { connectRelatedProducts } from '../..'; import { + createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectRelatedProducts } from '../..'; describe('connectRelatedProducts', () => { it('throws without render function', () => { @@ -92,6 +93,28 @@ describe('connectRelatedProducts', () => { ); }); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectRelatedProducts( + render, + unmount + )({ objectIDs: ['1'] }); + + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectRelatedProducts(render)({ objectIDs: ['1'] }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); + }); + describe('getWidgetParameters', () => { it('forwards widgetParams to the recommend state', () => { const render = () => {}; diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectRelevantSort.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectRelevantSort.test.ts index bc0d1ba947..26f6213a5e 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectRelevantSort.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectRelevantSort.test.ts @@ -6,13 +6,13 @@ import algoliasearchHelper, { SearchParameters, SearchResults, } from 'algoliasearch-helper'; - -import { connectRelevantSort, noop } from '../..'; import { createInitOptions, createRenderOptions, createDisposeOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectRelevantSort, noop } from '../..'; const createHelper = () => { return algoliasearchHelper(createSearchClient(), '', {}); @@ -36,27 +36,23 @@ describe('connectRelevantSort', () => { ); }); - it('dispose relevancyStrictness set by the widget', () => { - const helper = createHelper(); - const makeWidget = connectRelevantSort(noop); - const widget = makeWidget({}); - widget.init!(createInitOptions({ helper })); - const { refine } = widget.getWidgetRenderState( - createRenderOptions({ - helper, - }) - ); - refine(10); - expect( - widget.getWidgetSearchParameters(helper.state, { - uiState: {}, - }).relevancyStrictness - ).toEqual(10); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectRelevantSort(render, unmount)({}); - const nextState = widget.dispose!( - createDisposeOptions({ state: helper.state }) - ) as SearchParameters; - expect(nextState.relevancyStrictness).toBeUndefined(); + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectRelevantSort(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); }); it('apply relevancyStrictness to helper on refine()', () => { diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectSearchBox.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectSearchBox.test.ts index 7a2f8def7a..851903458a 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectSearchBox.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectSearchBox.test.ts @@ -6,13 +6,13 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectSearchBox, instantsearch } from '../..'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectSearchBox, instantsearch } from '../..'; describe('connectSearchBox', () => { const getInitializedWidget = (config = {}) => { @@ -543,52 +543,21 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/search-box/ }); describe('dispose', () => { - it('calls the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), ''); - - const renderFn = () => {}; - const unmountFn = jest.fn(); - const makeWidget = connectSearchBox(renderFn, unmountFn); - const widget = makeWidget({}); + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - expect(unmountFn).toHaveBeenCalledTimes(0); + const widget = connectSearchBox(render, unmount)({}); - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); + widget.dispose!(createDisposeOptions()); - expect(unmountFn).toHaveBeenCalledTimes(1); + expect(unmount).toHaveBeenCalled(); }); it('does not throw without the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), ''); - - const renderFn = () => {}; - const makeWidget = connectSearchBox(renderFn); - const widget = makeWidget({}); - - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - - it('removes the `query` from the `SearchParameters`', () => { - const helper = algoliasearchHelper(createSearchClient(), '', { - query: 'Apple', - }); - - const renderFn = () => {}; - const makeWidget = connectSearchBox(renderFn); - const widget = makeWidget({}); - - expect(helper.state.query).toBe('Apple'); - - const nextState = widget.dispose!( - createDisposeOptions({ - helper, - state: helper.state, - }) - ) as SearchParameters; - - expect(nextState.query).toBeUndefined(); + const render = () => {}; + const widget = connectSearchBox(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectSortBy.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectSortBy.test.ts index 6424fdaad1..a3dbe941f5 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectSortBy.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectSortBy.test.ts @@ -6,14 +6,14 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectSortBy, index } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectSortBy, index } from '../..'; import type { SortByRenderState } from '../connectSortBy'; @@ -137,19 +137,40 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/sort-by/js/ ); }); - it('does not throw without the unmount function', () => { - const rendering = jest.fn(); - const makeWidget = connectSortBy(rendering); - const items = [ - { label: 'Sort products by relevance', value: 'relevance' }, - { label: 'Sort products by price', value: 'priceASC' }, - ]; - const widget = makeWidget({ items }); - const helper = algoliasearchHelper(createSearchClient(), items[0].value); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); + const widget = connectSortBy( + render, + unmount + )({ + items: [ + { + label: 'Sort products by relevance', + value: 'relevance', + }, + ], + }); + + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectSortBy(render)({ + items: [ + { + label: 'Sort products by relevance', + value: 'relevance', + }, + ], + }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); }); it('Renders with transformed items', () => { diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectStats.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectStats.test.ts index 129a42bc60..9785a972b9 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectStats.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectStats.test.ts @@ -2,15 +2,14 @@ import { createSearchClient, createSingleSearchResponse, } from '@instantsearch/mocks'; -import jsHelper from 'algoliasearch-helper'; -const SearchResults = jsHelper.SearchResults; - -import { connectStats } from '../..'; +import jsHelper, { SearchResults } from 'algoliasearch-helper'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectStats } from '../..'; import type { StatsRenderState } from '../connectStats'; @@ -420,13 +419,22 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/stats/js/#c } }); - it('does not throw without the unmount function', () => { - const rendering = () => {}; - const makeWidget = connectStats(rendering); - const widget = makeWidget({}); - const helper = jsHelper(createSearchClient(), ''); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectStats(render, unmount)({}); + + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectStats(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectToggleRefinement.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectToggleRefinement.test.ts index 3e5dca78a8..a9c4aee201 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectToggleRefinement.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectToggleRefinement.test.ts @@ -6,14 +6,14 @@ import jsHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; - -import { connectToggleRefinement, warnCache } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectToggleRefinement, warnCache } from '../..'; import type { ToggleRefinementRenderState } from '../connectToggleRefinement'; @@ -310,22 +310,6 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/toggle-refi } }); - it('does not throw without the unmount function', () => { - const rendering = () => {}; - const makeWidget = connectToggleRefinement(rendering); - const attribute = 'isShippingFree'; - const widget = makeWidget({ - attribute, - }); - const config = widget.getWidgetSearchParameters(new SearchParameters({}), { - uiState: {}, - }); - const helper = jsHelper(createSearchClient(), '', config); - expect(() => - widget.dispose!(createDisposeOptions({ helper, state: helper.state })) - ).not.toThrow(); - }); - it('Provides a function to add/remove a facet value', () => { const rendering = jest.fn(); const makeWidget = connectToggleRefinement(rendering); @@ -836,59 +820,24 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/toggle-refi }); describe('dispose', () => { - test('calls the unmount function', () => { + it('calls unmount function', () => { const render = jest.fn(); const unmount = jest.fn(); - const makeWidget = connectToggleRefinement(render, unmount); - const helper = jsHelper(createSearchClient(), '', {}); - helper.search = jest.fn(); - const attribute = 'freeShipping'; - const widget = makeWidget({ - attribute, - }); + const widget = connectToggleRefinement( + render, + unmount + )({ attribute: 's' }); - widget.dispose!(createDisposeOptions({ state: helper.state })); + widget.dispose!(createDisposeOptions()); - expect(unmount).toHaveBeenCalledTimes(1); + expect(unmount).toHaveBeenCalled(); }); - test('resets the state', () => { - const render = jest.fn(); - const makeWidget = connectToggleRefinement(render); - const indexName = 'indexName'; - const helper = jsHelper(createSearchClient(), indexName, { - disjunctiveFacets: ['freeShipping'], - disjunctiveFacetsRefinements: { - freeShipping: ['true'], - }, - }); - helper.search = jest.fn(); - - const attribute = 'freeShipping'; - const widget = makeWidget({ - attribute, - }); - - expect(helper.state).toEqual( - new SearchParameters({ - index: indexName, - disjunctiveFacets: ['freeShipping'], - disjunctiveFacetsRefinements: { - freeShipping: ['true'], - }, - }) - ); - - const nextState = widget.dispose!( - createDisposeOptions({ state: helper.state }) - ); - - expect(nextState).toEqual( - new SearchParameters({ - index: indexName, - }) - ); + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectToggleRefinement(render)({ attribute: 's' }); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectTrendingItems.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectTrendingItems.test.ts index 9e89ec8085..04cbe95cd1 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectTrendingItems.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectTrendingItems.test.ts @@ -4,12 +4,13 @@ import { createSearchClient } from '@instantsearch/mocks'; import algoliasearchHelper, { RecommendParameters } from 'algoliasearch-helper'; - -import { connectTrendingItems } from '../..'; import { + createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectTrendingItems } from '../..'; describe('connectTrendingItems', () => { it('throws without render function', () => { @@ -170,4 +171,23 @@ describe('connectTrendingItems', () => { ); }); }); + + describe('dispose', () => { + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); + + const widget = connectTrendingItems(render, unmount)({}); + + widget.dispose!(createDisposeOptions()); + + expect(unmount).toHaveBeenCalled(); + }); + + it('does not throw without the unmount function', () => { + const render = () => {}; + const widget = connectTrendingItems(render)({}); + expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); + }); + }); }); diff --git a/packages/instantsearch-core/src/connectors/__tests__/connectVoiceSearch.test.ts b/packages/instantsearch-core/src/connectors/__tests__/connectVoiceSearch.test.ts index 7a2c146742..24435d3393 100644 --- a/packages/instantsearch-core/src/connectors/__tests__/connectVoiceSearch.test.ts +++ b/packages/instantsearch-core/src/connectors/__tests__/connectVoiceSearch.test.ts @@ -1,17 +1,18 @@ import { createSearchClient } from '@instantsearch/mocks'; import algoliasearchHelper, { SearchParameters } from 'algoliasearch-helper'; - -import { connectVoiceSearch } from '../..'; import { createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { connectSearchBox, connectVoiceSearch, instantsearch } from '../..'; import type { VoiceSearchHelperParams, VoiceSearchHelper, } from '../../lib/voiceSearchHelper/types'; +import { wait } from '@instantsearch/testutils'; jest.mock('../../lib/voiceSearchHelper', () => { const createVoiceHelper = ({ @@ -185,30 +186,20 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/voice-searc }); describe('dispose', () => { - it('calls the unmount function', () => { - const helper = algoliasearchHelper(createSearchClient(), ''); - - const renderFn = () => {}; - const unmountFn = jest.fn(); - const makeWidget = connectVoiceSearch(renderFn, unmountFn); - const widget = makeWidget({}); - - widget.init!(createInitOptions({ helper })); + it('calls unmount function', () => { + const render = jest.fn(); + const unmount = jest.fn(); - expect(unmountFn).toHaveBeenCalledTimes(0); + const widget = connectVoiceSearch(render, unmount)({}); - widget.dispose!(createDisposeOptions({ helper, state: helper.state })); + widget.dispose!(createDisposeOptions()); - expect(unmountFn).toHaveBeenCalledTimes(1); + expect(unmount).toHaveBeenCalled(); }); it('does not throw without the unmount function', () => { - const renderFn = () => {}; - const makeWidget = connectVoiceSearch(renderFn); - const widget = makeWidget({}); - - widget.init!(createInitOptions()); - + const render = () => {}; + const widget = connectVoiceSearch(render)({}); expect(() => widget.dispose!(createDisposeOptions())).not.toThrow(); }); @@ -231,26 +222,6 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/voice-searc 1 ); }); - - it('removes the `query` from the `SearchParameters`', () => { - const helper = algoliasearchHelper(createSearchClient(), '', { - query: 'Apple', - }); - - const renderFn = () => {}; - const makeWidget = connectVoiceSearch(renderFn); - const widget = makeWidget({}); - - widget.init!(createInitOptions({ helper })); - - expect(helper.state.query).toBe('Apple'); - - const nextState = widget.dispose!( - createDisposeOptions({ helper, state: helper.state }) - ) as SearchParameters; - - expect(nextState.query).toBeUndefined(); - }); }); describe('getWidgetUiState', () => { @@ -527,51 +498,68 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/voice-searc }) ); }); + }); - it('removes additional parameters when disposed', () => { - const { widget, helper, refine } = getInitializedWidget({ - widgetParams: { - additionalQueryParameters: () => {}, - }, + describe('interaction with searchbox', () => { + it('sets voice parameters only for voice queries', async () => { + const searchClient = createSearchClient(); + const search = instantsearch({ searchClient, indexName: 'indexName' }); + search.start(); + + const voice = connectVoiceSearch(() => {})({ + additionalQueryParameters: () => ({ exactOnSingleWordQuery: 'word' }), }); + const searchBox = connectSearchBox(() => {})({}); + search.addWidgets([voice, searchBox]); - refine('query'); - const newState = widget.dispose!( - createDisposeOptions({ state: helper.state }) - ); - expect(newState).toEqual( - new SearchParameters({ - ignorePlurals: undefined, - removeStopWords: undefined, - optionalWords: undefined, - queryLanguages: undefined, - index: '', - }) - ); - }); + await wait(100); + expect(search.client.search).toHaveBeenCalledTimes(1); + expect(search.client.search).toHaveBeenLastCalledWith([ + { + indexName: 'indexName', + params: { query: '' }, + }, + ]); - it('removes additional parameters and extra parameters when disposed', () => { - const { widget, helper, refine } = getInitializedWidget({ - widgetParams: { - additionalQueryParameters: () => ({ - distinct: true, - }), + search.renderState.indexName.searchBox?.refine('query'); + + await wait(100); + expect(search.client.search).toHaveBeenCalledTimes(2); + expect(search.client.search).toHaveBeenLastCalledWith([ + { + indexName: 'indexName', + params: { query: 'query' }, }, - }); + ]); - refine('query'); - const newState = widget.dispose!( - createDisposeOptions({ state: helper.state }) - ); - expect(newState).toEqual( - new SearchParameters({ - ignorePlurals: undefined, - removeStopWords: undefined, - optionalWords: undefined, - queryLanguages: undefined, - index: '', - }) - ); + // not testing the browser API here + (voice as any)._refine('voice query'); + + await wait(100); + expect(search.client.search).toHaveBeenCalledTimes(3); + expect(search.client.search).toHaveBeenLastCalledWith([ + { + indexName: 'indexName', + params: { + query: 'voice query', + ignorePlurals: true, + removeStopWords: true, + optionalWords: 'voice query', + exactOnSingleWordQuery: 'word', + }, + }, + ]); + + search.removeWidgets([voice]); + + await wait(100); + expect(search.client.search).toHaveBeenCalledTimes(4); + expect(search.client.search).toHaveBeenLastCalledWith([ + { + indexName: 'indexName', + params: { query: 'voice query' }, + }, + ]); }); }); }); diff --git a/packages/instantsearch-core/src/connectors/connectAutocomplete.ts b/packages/instantsearch-core/src/connectors/connectAutocomplete.ts index e358191e0f..4a61a1913c 100644 --- a/packages/instantsearch-core/src/connectors/connectAutocomplete.ts +++ b/packages/instantsearch-core/src/connectors/connectAutocomplete.ts @@ -241,24 +241,8 @@ search.addWidgets([ }); }, - dispose({ state }) { + dispose() { unmountFn(); - - const stateWithoutQuery = state.setQueryParameter('query', undefined); - - if (!escapeHTML) { - return stateWithoutQuery; - } - - return stateWithoutQuery.setQueryParameters( - Object.keys(TAG_PLACEHOLDER).reduce( - (acc, key) => ({ - ...acc, - [key]: undefined, - }), - {} - ) - ); }, }; }; diff --git a/packages/instantsearch-core/src/connectors/connectConfigure.ts b/packages/instantsearch-core/src/connectors/connectConfigure.ts index 0c9ea29c6f..066584009d 100644 --- a/packages/instantsearch-core/src/connectors/connectConfigure.ts +++ b/packages/instantsearch-core/src/connectors/connectConfigure.ts @@ -7,12 +7,9 @@ import { } from '../lib/public'; import { mergeSearchParameters } from '../lib/utils'; +import type { InstantSearch } from '../instantsearch'; import type { Connector, WidgetRenderState } from '../types'; -import type { - SearchParameters, - PlainSearchParameters, - AlgoliaSearchHelper, -} from 'algoliasearch-helper'; +import type { PlainSearchParameters } from 'algoliasearch-helper'; /** * Refine the given search parameters. @@ -39,24 +36,6 @@ const withUsage = createDocumentationMessageGenerator({ connector: true, }); -function getInitialSearchParameters( - state: SearchParameters, - widgetParams: ConfigureConnectorParams -): SearchParameters { - // We leverage the helper internals to remove the `widgetParams` from - // the state. The function `setQueryParameters` omits the values that - // are `undefined` on the next state. - return state.setQueryParameters( - Object.keys(widgetParams.searchParameters).reduce( - (acc, key) => ({ - ...acc, - [key]: undefined, - }), - {} - ) - ); -} - export type ConfigureWidgetDescription = { $$type: 'ais.configure'; renderState: ConfigureRenderState; @@ -66,9 +45,6 @@ export type ConfigureWidgetDescription = { ConfigureConnectorParams >; }; - indexUiState: { - configure: PlainSearchParameters; - }; }; export type ConfigureConnector = Connector< @@ -93,23 +69,12 @@ export const connectConfigure: ConfigureConnector = function connectConfigure( const connectorState: ConnectorState = {}; - function refine(helper: AlgoliaSearchHelper): Refine { + function refine(search: InstantSearch): Refine { return (searchParameters: PlainSearchParameters) => { - // Merge new `searchParameters` with the ones set from other widgets - const actualState = getInitialSearchParameters( - helper.state, - widgetParams - ); - const nextSearchParameters = mergeSearchParameters( - actualState, - new algoliasearchHelper.SearchParameters(searchParameters) - ); - // Update original `widgetParams.searchParameters` to the new refined one widgetParams.searchParameters = searchParameters; - - // Trigger a search with the resolved search parameters - helper.setState(nextSearchParameters).search(); + // Trigger a search with the new parameters + search.setUiState((prev) => prev); }; } @@ -139,10 +104,8 @@ export const connectConfigure: ConfigureConnector = function connectConfigure( ); }, - dispose({ state }) { + dispose() { unmountFn(); - - return getInitialSearchParameters(state, widgetParams); }, getRenderState(renderState, renderOptions) { @@ -166,9 +129,9 @@ export const connectConfigure: ConfigureConnector = function connectConfigure( }; }, - getWidgetRenderState({ helper }) { + getWidgetRenderState({ instantSearchInstance }) { if (!connectorState.refine) { - connectorState.refine = refine(helper); + connectorState.refine = refine(instantSearchInstance); } return { @@ -177,24 +140,19 @@ export const connectConfigure: ConfigureConnector = function connectConfigure( }; }, - getWidgetSearchParameters(state, { uiState }) { + getWidgetSearchParameters(state) { return mergeSearchParameters( state, - new algoliasearchHelper.SearchParameters({ - ...uiState.configure, - ...widgetParams.searchParameters, - }) + new algoliasearchHelper.SearchParameters( + widgetParams.searchParameters + ) ); }, getWidgetUiState(uiState) { - return { - ...uiState, - configure: { - ...uiState.configure, - ...widgetParams.searchParameters, - }, - }; + // Configure is not part of the UI state, its internal state is what applies + // the parameters to the search. These are not synced with the routing. + return uiState; }, }; }; diff --git a/packages/instantsearch-core/src/connectors/connectFrequentlyBoughtTogether.ts b/packages/instantsearch-core/src/connectors/connectFrequentlyBoughtTogether.ts index 892b26fccb..1ba36a3d21 100644 --- a/packages/instantsearch-core/src/connectors/connectFrequentlyBoughtTogether.ts +++ b/packages/instantsearch-core/src/connectors/connectFrequentlyBoughtTogether.ts @@ -176,9 +176,8 @@ export const connectFrequentlyBoughtTogether = return { items: transformedItems, widgetParams }; }, - dispose({ recommendState }) { + dispose() { unmountFn(); - return recommendState.removeParams(this.$$id!); }, getWidgetParameters(state) { diff --git a/packages/instantsearch-core/src/connectors/connectGeoSearch.ts b/packages/instantsearch-core/src/connectors/connectGeoSearch.ts index 0bf37cbcee..5d1adcb5eb 100644 --- a/packages/instantsearch-core/src/connectors/connectGeoSearch.ts +++ b/packages/instantsearch-core/src/connectors/connectGeoSearch.ts @@ -382,10 +382,8 @@ export const connectGeoSearch = function connectGeoSearch< }; }, - dispose({ state }) { + dispose() { unmountFn(); - - return state.setQueryParameter('insideBoundingBox', undefined); }, getWidgetUiState(uiState, { searchParameters }) { diff --git a/packages/instantsearch-core/src/connectors/connectHierarchicalMenu.ts b/packages/instantsearch-core/src/connectors/connectHierarchicalMenu.ts index 37b50b62f8..3aaa6a1315 100644 --- a/packages/instantsearch-core/src/connectors/connectHierarchicalMenu.ts +++ b/packages/instantsearch-core/src/connectors/connectHierarchicalMenu.ts @@ -287,12 +287,8 @@ export const connectHierarchicalMenu: HierarchicalMenuConnector = ); }, - dispose({ state }) { + dispose() { unmountFn(); - - return state - .removeHierarchicalFacet(hierarchicalFacetName) - .setQueryParameter('maxValuesPerFacet', undefined); }, getRenderState(renderState, renderOptions) { diff --git a/packages/instantsearch-core/src/connectors/connectHits.ts b/packages/instantsearch-core/src/connectors/connectHits.ts index fd2970f1d5..5998fa401d 100644 --- a/packages/instantsearch-core/src/connectors/connectHits.ts +++ b/packages/instantsearch-core/src/connectors/connectHits.ts @@ -186,22 +186,8 @@ export const connectHits = function connectHits( }; }, - dispose({ state }) { + dispose() { unmountFn(); - - if (!escapeHTML) { - return state; - } - - return state.setQueryParameters( - Object.keys(TAG_PLACEHOLDER).reduce( - (acc, key) => ({ - ...acc, - [key]: undefined, - }), - {} - ) - ); }, getWidgetSearchParameters(state, _uiState) { diff --git a/packages/instantsearch-core/src/connectors/connectHitsPerPage.ts b/packages/instantsearch-core/src/connectors/connectHitsPerPage.ts index 7eebe8a8d2..ae338daf28 100644 --- a/packages/instantsearch-core/src/connectors/connectHitsPerPage.ts +++ b/packages/instantsearch-core/src/connectors/connectHitsPerPage.ts @@ -253,10 +253,8 @@ You may want to add another entry to the \`items\` option with this value.` ); }, - dispose({ state }) { + dispose() { unmountFn(); - - return state.setQueryParameter('hitsPerPage', undefined); }, getRenderState(renderState, renderOptions) { diff --git a/packages/instantsearch-core/src/connectors/connectInfiniteHits.ts b/packages/instantsearch-core/src/connectors/connectInfiniteHits.ts index c72105f760..f61443ae95 100644 --- a/packages/instantsearch-core/src/connectors/connectInfiniteHits.ts +++ b/packages/instantsearch-core/src/connectors/connectInfiniteHits.ts @@ -430,24 +430,8 @@ export const connectInfiniteHits = function connectInfiniteHits< }; }, - dispose({ state }) { + dispose() { unmountFn(); - - const stateWithoutPage = state.setQueryParameter('page', undefined); - - if (!escapeHTML) { - return stateWithoutPage; - } - - return stateWithoutPage.setQueryParameters( - Object.keys(TAG_PLACEHOLDER).reduce( - (acc, key) => ({ - ...acc, - [key]: undefined, - }), - {} - ) - ); }, getWidgetUiState(uiState, { searchParameters }) { diff --git a/packages/instantsearch-core/src/connectors/connectLookingSimilar.ts b/packages/instantsearch-core/src/connectors/connectLookingSimilar.ts index 1bb84ff049..e47b076e7f 100644 --- a/packages/instantsearch-core/src/connectors/connectLookingSimilar.ts +++ b/packages/instantsearch-core/src/connectors/connectLookingSimilar.ts @@ -175,9 +175,8 @@ export const connectLookingSimilar = function connectLookingSimilar< }; }, - dispose({ recommendState }) { + dispose() { unmountFn(); - return recommendState.removeParams(this.$$id!); }, getWidgetParameters(state) { diff --git a/packages/instantsearch-core/src/connectors/connectMenu.ts b/packages/instantsearch-core/src/connectors/connectMenu.ts index 2a0c2fd54e..d0d9c5f4bd 100644 --- a/packages/instantsearch-core/src/connectors/connectMenu.ts +++ b/packages/instantsearch-core/src/connectors/connectMenu.ts @@ -227,12 +227,8 @@ export const connectMenu: MenuConnector = function connectMenu( ); }, - dispose({ state }) { + dispose() { unmountFn(); - - return state - .removeHierarchicalFacet(attribute) - .setQueryParameter('maxValuesPerFacet', undefined); }, getRenderState(renderState, renderOptions) { diff --git a/packages/instantsearch-core/src/connectors/connectNumericMenu.ts b/packages/instantsearch-core/src/connectors/connectNumericMenu.ts index a44d6d0e60..fb3c0cbe35 100644 --- a/packages/instantsearch-core/src/connectors/connectNumericMenu.ts +++ b/packages/instantsearch-core/src/connectors/connectNumericMenu.ts @@ -206,9 +206,8 @@ export const connectNumericMenu: NumericMenuConnector = ); }, - dispose({ state }) { + dispose() { unmountFn(); - return state.removeNumericRefinement(attribute); }, getWidgetUiState(uiState, { searchParameters }) { diff --git a/packages/instantsearch-core/src/connectors/connectPagination.ts b/packages/instantsearch-core/src/connectors/connectPagination.ts index 6c278a3dcc..881368854c 100644 --- a/packages/instantsearch-core/src/connectors/connectPagination.ts +++ b/packages/instantsearch-core/src/connectors/connectPagination.ts @@ -130,10 +130,8 @@ export const connectPagination: PaginationConnector = ); }, - dispose({ state }) { + dispose() { unmountFn(); - - return state.setQueryParameter('page', undefined); }, getWidgetUiState(uiState, { searchParameters }) { diff --git a/packages/instantsearch-core/src/connectors/connectQueryRules.ts b/packages/instantsearch-core/src/connectors/connectQueryRules.ts index 9a05a73a80..1bc7c5a8a3 100644 --- a/packages/instantsearch-core/src/connectors/connectQueryRules.ts +++ b/packages/instantsearch-core/src/connectors/connectQueryRules.ts @@ -158,8 +158,8 @@ export type QueryRulesConnector = Connector< >; export const connectQueryRules: QueryRulesConnector = - function connectQueryRules(render, unmount = noop) { - checkRendering(render, withUsage()); + function connectQueryRules(renderFn, unmountFn = noop) { + checkRendering(renderFn, withUsage()); return (widgetParams) => { const { @@ -219,7 +219,7 @@ export const connectQueryRules: QueryRulesConnector = helper.on('change', onHelperChange); } - render( + renderFn( { ...this.getWidgetRenderState(initOptions), instantSearchInstance, @@ -231,7 +231,7 @@ export const connectQueryRules: QueryRulesConnector = render(renderOptions) { const { instantSearchInstance } = renderOptions; - render( + renderFn( { ...this.getWidgetRenderState(renderOptions), instantSearchInstance, @@ -257,16 +257,8 @@ export const connectQueryRules: QueryRulesConnector = }; }, - dispose({ helper, state }) { - unmount(); - - if (hasTrackedFilters) { - helper.removeListener('change', onHelperChange); - - return state.setQueryParameter('ruleContexts', initialRuleContexts); - } - - return state; + dispose() { + unmountFn(); }, }; }; diff --git a/packages/instantsearch-core/src/connectors/connectRange.ts b/packages/instantsearch-core/src/connectors/connectRange.ts index 314108070f..bcaec84f05 100644 --- a/packages/instantsearch-core/src/connectors/connectRange.ts +++ b/packages/instantsearch-core/src/connectors/connectRange.ts @@ -390,12 +390,8 @@ export const connectRange: RangeConnector = function connectRange( }; }, - dispose({ state }) { + dispose() { unmountFn(); - - return state - .removeDisjunctiveFacet(attribute) - .removeNumericRefinement(attribute); }, getWidgetUiState(uiState, { searchParameters }) { diff --git a/packages/instantsearch-core/src/connectors/connectRatingMenu.ts b/packages/instantsearch-core/src/connectors/connectRatingMenu.ts index 1a354dea7a..dbf48e497d 100644 --- a/packages/instantsearch-core/src/connectors/connectRatingMenu.ts +++ b/packages/instantsearch-core/src/connectors/connectRatingMenu.ts @@ -429,10 +429,8 @@ export const connectRatingMenu: RatingMenuConnector = }; }, - dispose({ state }) { + dispose() { unmountFn(); - - return state.removeNumericRefinement(attribute); }, getWidgetUiState(uiState, { searchParameters }) { diff --git a/packages/instantsearch-core/src/connectors/connectRefinementList.ts b/packages/instantsearch-core/src/connectors/connectRefinementList.ts index 8be83bd411..5cafa9282d 100644 --- a/packages/instantsearch-core/src/connectors/connectRefinementList.ts +++ b/packages/instantsearch-core/src/connectors/connectRefinementList.ts @@ -458,17 +458,8 @@ export const connectRefinementList: RefinementListConnector = }; }, - dispose({ state }) { + dispose() { unmountFn(); - - const withoutMaxValuesPerFacet = state.setQueryParameter( - 'maxValuesPerFacet', - undefined - ); - if (operator === 'and') { - return withoutMaxValuesPerFacet.removeFacet(attribute); - } - return withoutMaxValuesPerFacet.removeDisjunctiveFacet(attribute); }, getWidgetUiState(uiState, { searchParameters }) { diff --git a/packages/instantsearch-core/src/connectors/connectRelatedProducts.ts b/packages/instantsearch-core/src/connectors/connectRelatedProducts.ts index 84ca24aff2..634fd29537 100644 --- a/packages/instantsearch-core/src/connectors/connectRelatedProducts.ts +++ b/packages/instantsearch-core/src/connectors/connectRelatedProducts.ts @@ -175,9 +175,8 @@ export const connectRelatedProducts = function connectRelatedProducts< }; }, - dispose({ recommendState }) { + dispose() { unmountFn(); - return recommendState.removeParams(this.$$id!); }, getWidgetParameters(state) { diff --git a/packages/instantsearch-core/src/connectors/connectRelevantSort.ts b/packages/instantsearch-core/src/connectors/connectRelevantSort.ts index d0ab509ea0..fce5d6cb3c 100644 --- a/packages/instantsearch-core/src/connectors/connectRelevantSort.ts +++ b/packages/instantsearch-core/src/connectors/connectRelevantSort.ts @@ -82,10 +82,8 @@ export const connectRelevantSort: RelevantSortConnector = ); }, - dispose({ state }) { + dispose() { unmountFn(); - - return state.setQueryParameter('relevancyStrictness', undefined); }, getRenderState(renderState, renderOptions) { diff --git a/packages/instantsearch-core/src/connectors/connectSearchBox.ts b/packages/instantsearch-core/src/connectors/connectSearchBox.ts index ea12129320..c66387860d 100644 --- a/packages/instantsearch-core/src/connectors/connectSearchBox.ts +++ b/packages/instantsearch-core/src/connectors/connectSearchBox.ts @@ -115,10 +115,8 @@ export const connectSearchBox: SearchBoxConnector = function connectSearchBox( ); }, - dispose({ state }) { + dispose() { unmountFn(); - - return state.setQueryParameter('query', undefined); }, getRenderState(renderState, renderOptions) { diff --git a/packages/instantsearch-core/src/connectors/connectSortBy.ts b/packages/instantsearch-core/src/connectors/connectSortBy.ts index e27b8ce846..4ab9d7d198 100644 --- a/packages/instantsearch-core/src/connectors/connectSortBy.ts +++ b/packages/instantsearch-core/src/connectors/connectSortBy.ts @@ -148,12 +148,8 @@ export const connectSortBy: SortByConnector = function connectSortBy( ); }, - dispose({ state }) { + dispose() { unmountFn(); - - return connectorState.initialIndex - ? state.setIndex(connectorState.initialIndex) - : state; }, getRenderState(renderState, renderOptions) { diff --git a/packages/instantsearch-core/src/connectors/connectToggleRefinement.ts b/packages/instantsearch-core/src/connectors/connectToggleRefinement.ts index ae67f32ce8..1c5491295e 100644 --- a/packages/instantsearch-core/src/connectors/connectToggleRefinement.ts +++ b/packages/instantsearch-core/src/connectors/connectToggleRefinement.ts @@ -304,10 +304,8 @@ export const connectToggleRefinement: ToggleRefinementConnector = ); }, - dispose({ state }) { + dispose() { unmountFn(); - - return state.removeDisjunctiveFacet(attribute); }, getRenderState(renderState, renderOptions) { diff --git a/packages/instantsearch-core/src/connectors/connectTrendingItems.ts b/packages/instantsearch-core/src/connectors/connectTrendingItems.ts index f4a6e2f0b3..3455296848 100644 --- a/packages/instantsearch-core/src/connectors/connectTrendingItems.ts +++ b/packages/instantsearch-core/src/connectors/connectTrendingItems.ts @@ -195,9 +195,8 @@ export const connectTrendingItems = function connectTrendingItems< }; }, - dispose({ recommendState }) { + dispose() { unmountFn(); - return recommendState.removeParams(this.$$id!); }, getWidgetParameters(state) { diff --git a/packages/instantsearch-core/src/connectors/connectVoiceSearch.ts b/packages/instantsearch-core/src/connectors/connectVoiceSearch.ts index f22fb5d165..e66321e40b 100644 --- a/packages/instantsearch-core/src/connectors/connectVoiceSearch.ts +++ b/packages/instantsearch-core/src/connectors/connectVoiceSearch.ts @@ -108,6 +108,8 @@ export const connectVoiceSearch: VoiceSearchConnector = if (typeof additionalQueryParameters === 'function') { helper.setState( + // These parameters are only set with a refine, so they are not persisted. + // If a searchbox query happens, the parameters are reset. helper.state.setQueryParameters({ ignorePlurals: true, removeStopWords: true, @@ -166,34 +168,10 @@ export const connectVoiceSearch: VoiceSearchConnector = }; }, - dispose({ state }) { - (this as any)._voiceSearchHelper.dispose(); + dispose() { + (this as any)._voiceSearchHelper?.dispose(); unmountFn(); - - let newState = state; - if (typeof additionalQueryParameters === 'function') { - const additional = additionalQueryParameters({ query: '' }); - const toReset = additional - ? ( - Object.keys(additional) as Array - ).reduce((acc, current) => { - // @ts-ignore search parameters is typed as readonly in v4 - acc[current] = undefined; - return acc; - }, {}) - : {}; - newState = state.setQueryParameters({ - // @ts-ignore (queryLanguages is not added to algoliasearch v3) - queryLanguages: undefined, - ignorePlurals: undefined, - removeStopWords: undefined, - optionalWords: undefined, - ...toReset, - }); - } - - return newState.setQueryParameter('query', undefined); }, getWidgetUiState(uiState, { searchParameters }) { diff --git a/packages/instantsearch-core/src/lib/public/__tests__/getWidgetAttribute.test.ts b/packages/instantsearch-core/src/lib/public/__tests__/getWidgetAttribute.test.ts index 37bd73b0e8..898879be06 100644 --- a/packages/instantsearch-core/src/lib/public/__tests__/getWidgetAttribute.test.ts +++ b/packages/instantsearch-core/src/lib/public/__tests__/getWidgetAttribute.test.ts @@ -2,6 +2,8 @@ * @jest-environment jsdom */ +import { createInitOptions } from 'instantsearch-core/test/createWidget'; + import { getWidgetAttribute } from '..'; import { connectHits, @@ -9,7 +11,6 @@ import { connectHierarchicalMenu, connectToggleRefinement, } from '../../..'; -import { createInitOptions } from '../../../../test/createWidget'; const hierarchicalMenu = connectHierarchicalMenu(() => {}); const hits = connectHits(() => {}); diff --git a/packages/instantsearch-core/src/lib/utils/__tests__/createSendEventForFacet.test.ts b/packages/instantsearch-core/src/lib/utils/__tests__/createSendEventForFacet.test.ts index e3c0785c97..e461d57966 100644 --- a/packages/instantsearch-core/src/lib/utils/__tests__/createSendEventForFacet.test.ts +++ b/packages/instantsearch-core/src/lib/utils/__tests__/createSendEventForFacet.test.ts @@ -1,7 +1,7 @@ import { castToJestMock } from '@instantsearch/testutils/castToJestMock'; import algoliasearchHelper from 'algoliasearch-helper'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; -import { createInstantSearch } from '../../../../test/createInstantSearch'; import { isFacetRefined } from '../../public/isFacetRefined'; import { createSendEventForFacet } from '../createSendEventForFacet'; diff --git a/packages/instantsearch-core/src/lib/utils/__tests__/createSendEventForHits.test.ts b/packages/instantsearch-core/src/lib/utils/__tests__/createSendEventForHits.test.ts index d0fa7c0e8e..498f5ea2b6 100644 --- a/packages/instantsearch-core/src/lib/utils/__tests__/createSendEventForHits.test.ts +++ b/packages/instantsearch-core/src/lib/utils/__tests__/createSendEventForHits.test.ts @@ -2,7 +2,8 @@ * @jest-environment jsdom */ -import { createInstantSearch } from '../../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; + import { createSendEventForHits } from '../createSendEventForHits'; import type { EscapedHits } from '../../../types'; diff --git a/packages/instantsearch-core/src/lib/utils/__tests__/resolveSearchParameters.test.ts b/packages/instantsearch-core/src/lib/utils/__tests__/resolveSearchParameters.test.ts index 3b1520fe69..2270867265 100644 --- a/packages/instantsearch-core/src/lib/utils/__tests__/resolveSearchParameters.test.ts +++ b/packages/instantsearch-core/src/lib/utils/__tests__/resolveSearchParameters.test.ts @@ -1,5 +1,6 @@ +import { createIndexInitOptions } from 'instantsearch-core/test/createWidget'; + import { resolveSearchParameters } from '..'; -import { createIndexInitOptions } from '../../../../test/createWidget'; import { index } from '../../../widgets'; describe('mergeSearchParameters', () => { diff --git a/packages/instantsearch-core/src/lib/utils/checkIndexUiState.ts b/packages/instantsearch-core/src/lib/utils/checkIndexUiState.ts index 385b819fd2..0a52d61b73 100644 --- a/packages/instantsearch-core/src/lib/utils/checkIndexUiState.ts +++ b/packages/instantsearch-core/src/lib/utils/checkIndexUiState.ts @@ -87,10 +87,6 @@ const stateToWidgetsMap: StateToWidgets = { connectors: ['connectHitsPerPage'], widgets: ['ais.hitsPerPage'], }, - configure: { - connectors: ['connectConfigure'], - widgets: ['ais.configure'], - }, }; type CheckIndexUiStateParams = { diff --git a/packages/instantsearch-core/src/middlewares/__tests__/createInsightsMiddleware.ts b/packages/instantsearch-core/src/middlewares/__tests__/createInsightsMiddleware.ts index afa82f0345..fd15e44f51 100644 --- a/packages/instantsearch-core/src/middlewares/__tests__/createInsightsMiddleware.ts +++ b/packages/instantsearch-core/src/middlewares/__tests__/createInsightsMiddleware.ts @@ -12,6 +12,7 @@ import { import { castToJestMock } from '@instantsearch/testutils'; import { wait } from '@instantsearch/testutils/wait'; import { fireEvent } from '@testing-library/dom'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createInsightsMiddleware, @@ -23,7 +24,6 @@ import { instantsearch, historyRouter, } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; import type { SearchClient, InsightsProps } from '../../types'; import type { PlainSearchParameters } from 'algoliasearch-helper'; diff --git a/packages/instantsearch-core/src/routing/__tests__/simpleStateMapping.test.ts b/packages/instantsearch-core/src/routing/__tests__/simpleStateMapping.test.ts index 8b0486ff1d..56d09d082a 100644 --- a/packages/instantsearch-core/src/routing/__tests__/simpleStateMapping.test.ts +++ b/packages/instantsearch-core/src/routing/__tests__/simpleStateMapping.test.ts @@ -25,30 +25,6 @@ describe('simpleStateMapping', () => { }); }); - it('removes configure', () => { - const stateMapping = simpleStateMapping(); - const actual = stateMapping.stateToRoute({ - indexName: { - query: 'zamboni', - refinementList: { - color: ['red'], - }, - configure: { - advancedSyntax: false, - }, - }, - }); - - expect(actual).toEqual({ - indexName: { - query: 'zamboni', - refinementList: { - color: ['red'], - }, - }, - }); - }); - it('passes non-UiState through', () => { const stateMapping = simpleStateMapping(); const actual = stateMapping.stateToRoute({ @@ -96,30 +72,6 @@ describe('simpleStateMapping', () => { }); }); - it('removes configure', () => { - const stateMapping = simpleStateMapping(); - const actual = stateMapping.routeToState({ - indexName: { - query: 'zamboni', - refinementList: { - color: ['red'], - }, - configure: { - advancedSyntax: false, - }, - }, - }); - - expect(actual).toEqual({ - indexName: { - query: 'zamboni', - refinementList: { - color: ['red'], - }, - }, - }); - }); - it('passes non-UiState through', () => { const stateMapping = simpleStateMapping<{ [indexId in string]: UiState[indexId] & { spy: string[] }; diff --git a/packages/instantsearch-core/src/routing/__tests__/singleIndexStateMapping.test.ts b/packages/instantsearch-core/src/routing/__tests__/singleIndexStateMapping.test.ts index d88bc16f31..24c51bfed8 100644 --- a/packages/instantsearch-core/src/routing/__tests__/singleIndexStateMapping.test.ts +++ b/packages/instantsearch-core/src/routing/__tests__/singleIndexStateMapping.test.ts @@ -23,28 +23,6 @@ describe('singleIndexStateMapping', () => { }); }); - it('removes configure', () => { - const stateMapping = singleIndexStateMapping('indexName'); - const actual = stateMapping.stateToRoute({ - indexName: { - query: 'zamboni', - refinementList: { - color: ['red'], - }, - configure: { - advancedSyntax: false, - }, - }, - }); - - expect(actual).toEqual({ - query: 'zamboni', - refinementList: { - color: ['red'], - }, - }); - }); - it('passes non-UiState through', () => { const stateMapping = singleIndexStateMapping('indexName'); const actual = stateMapping.stateToRoute({ @@ -135,28 +113,6 @@ describe('singleIndexStateMapping', () => { }); }); - it('removes configure', () => { - const stateMapping = singleIndexStateMapping('indexName'); - const actual = stateMapping.routeToState({ - query: 'zamboni', - refinementList: { - color: ['red'], - }, - configure: { - advancedSyntax: false, - }, - }); - - expect(actual).toEqual({ - indexName: { - query: 'zamboni', - refinementList: { - color: ['red'], - }, - }, - }); - }); - it('passes non-UiState through', () => { const stateMapping = singleIndexStateMapping< UiState & { [indexName: string]: { spy: string[] } } diff --git a/packages/instantsearch-core/src/routing/simpleStateMapping.ts b/packages/instantsearch-core/src/routing/simpleStateMapping.ts index 97f57c9162..d39f94a521 100644 --- a/packages/instantsearch-core/src/routing/simpleStateMapping.ts +++ b/packages/instantsearch-core/src/routing/simpleStateMapping.ts @@ -1,15 +1,5 @@ -import type { UiState, IndexUiState, StateMapping } from '../types'; +import type { UiState, StateMapping } from '../types'; -function getIndexStateWithoutConfigure( - uiState: TIndexUiState -): Omit { - const { configure, ...trackedUiState } = uiState; - return trackedUiState; -} - -// technically a URL could contain any key, since users provide it, -// which is why the input to this function is UiState, not something -// which excludes "configure" as this function does. export function simpleStateMapping< TUiState extends UiState = UiState >(): StateMapping { @@ -17,23 +7,11 @@ export function simpleStateMapping< $$type: 'ais.simple', stateToRoute(uiState) { - return Object.keys(uiState).reduce( - (state, indexId) => ({ - ...state, - [indexId]: getIndexStateWithoutConfigure(uiState[indexId]), - }), - {} as TUiState - ); + return uiState; }, routeToState(routeState = {} as TUiState) { - return Object.keys(routeState).reduce( - (state, indexId) => ({ - ...state, - [indexId]: getIndexStateWithoutConfigure(routeState[indexId]), - }), - {} as TUiState - ); + return routeState; }, }; } diff --git a/packages/instantsearch-core/src/routing/singleIndexStateMapping.ts b/packages/instantsearch-core/src/routing/singleIndexStateMapping.ts index 4495ae436f..0315ab4cad 100644 --- a/packages/instantsearch-core/src/routing/singleIndexStateMapping.ts +++ b/packages/instantsearch-core/src/routing/singleIndexStateMapping.ts @@ -1,11 +1,4 @@ -import type { StateMapping, IndexUiState, UiState } from '../types'; - -function getIndexStateWithoutConfigure( - uiState: TIndexUiState -): TIndexUiState { - const { configure, ...trackedUiState } = uiState; - return trackedUiState as TIndexUiState; -} +import type { StateMapping, UiState } from '../types'; export function singleIndexStateMapping( indexName: keyof TUiState @@ -13,11 +6,11 @@ export function singleIndexStateMapping( return { $$type: 'ais.singleIndex', stateToRoute(uiState) { - return getIndexStateWithoutConfigure(uiState[indexName] || {}); + return uiState[indexName] || {}; }, routeToState(routeState = {} as TUiState[typeof indexName]) { return { - [indexName]: getIndexStateWithoutConfigure(routeState), + [indexName]: routeState, } as unknown as TUiState; }, }; diff --git a/packages/instantsearch-core/src/types/ui-state.ts b/packages/instantsearch-core/src/types/ui-state.ts index b305f47cfc..6883d1a7b8 100644 --- a/packages/instantsearch-core/src/types/ui-state.ts +++ b/packages/instantsearch-core/src/types/ui-state.ts @@ -1,6 +1,5 @@ import type { AutocompleteWidgetDescription, - ConfigureWidgetDescription, GeoSearchWidgetDescription, HierarchicalMenuWidgetDescription, HitsPerPageWidgetDescription, @@ -19,7 +18,6 @@ import type { } from '../connectors'; type ConnectorUiStates = AutocompleteWidgetDescription['indexUiState'] & - ConfigureWidgetDescription['indexUiState'] & GeoSearchWidgetDescription['indexUiState'] & HierarchicalMenuWidgetDescription['indexUiState'] & HitsPerPageWidgetDescription['indexUiState'] & diff --git a/packages/instantsearch-core/src/types/widget.ts b/packages/instantsearch-core/src/types/widget.ts index 131de32bae..c9e3da462c 100644 --- a/packages/instantsearch-core/src/types/widget.ts +++ b/packages/instantsearch-core/src/types/widget.ts @@ -48,9 +48,6 @@ export type RenderOptions = SharedRenderOptions & { }; export type DisposeOptions = { - helper: Helper; - state: SearchParameters; - recommendState: RecommendParameters; parent: IndexWidget; }; diff --git a/packages/instantsearch-core/src/widgets/__tests__/index-widget.test.ts b/packages/instantsearch-core/src/widgets/__tests__/index-widget.test.ts index 2f5d90091d..f7ba4a8d97 100644 --- a/packages/instantsearch-core/src/widgets/__tests__/index-widget.test.ts +++ b/packages/instantsearch-core/src/widgets/__tests__/index-widget.test.ts @@ -14,6 +14,12 @@ import algoliasearchHelper, { RecommendParameters, RecommendResults, } from 'algoliasearch-helper'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; +import { + createWidget, + createIndexInitOptions, + createDisposeOptions, +} from 'instantsearch-core/test/createWidget'; import { instantsearch, @@ -23,12 +29,6 @@ import { connectRefinementList, connectSearchBox, } from '../..'; -import { createInstantSearch } from '../../../test/createInstantSearch'; -import { - createWidget, - createIndexInitOptions, - createDisposeOptions, -} from '../../../test/createWidget'; import type { Widget } from '../../types'; import type { PlainSearchParameters } from 'algoliasearch-helper'; @@ -36,9 +36,7 @@ import type { PlainSearchParameters } from 'algoliasearch-helper'; describe('index', () => { const createSearchBox = (args: Partial = {}): Widget => createWidget({ - dispose: jest.fn(({ state }) => { - return state.setQueryParameter('query', undefined); - }), + dispose: jest.fn(() => {}), getWidgetUiState: jest.fn((uiState, { searchParameters }) => { if (!searchParameters.query) { return uiState; @@ -57,9 +55,7 @@ describe('index', () => { const createPagination = (args: Partial = {}): Widget => createWidget({ - dispose: jest.fn(({ state }) => { - return state.setQueryParameter('page', undefined); - }), + dispose: jest.fn(() => {}), getWidgetUiState: jest.fn((uiState, { searchParameters }) => { if (!searchParameters.page) { return uiState; @@ -81,17 +77,7 @@ describe('index', () => { args: Partial = {} ): Widget => createWidget({ - dispose: jest.fn(({ state }) => { - return state.setQueryParameters( - Object.keys(params).reduce( - (acc, key) => ({ - ...acc, - [key]: undefined, - }), - {} - ) - ); - }), + dispose: jest.fn(() => {}), getWidgetUiState(uiState) { return { ...uiState, @@ -121,9 +107,7 @@ describe('index', () => { objectID: 'abc', }); }, - dispose({ recommendState }) { - return recommendState.removeParams(this.$$id!); - }, + dispose() {}, ...args, } as Widget) as unknown as Widget & { $$id: number }; @@ -712,16 +696,11 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/index-widge expect(widget.dispose).toHaveBeenCalledTimes(0); }); - const stateBefore = instance.getHelper()!.state; - instance.removeWidgets(widgets); widgets.forEach((widget) => { expect(widget.dispose).toHaveBeenCalledTimes(1); expect(widget.dispose).toHaveBeenCalledWith({ - helper: instance.getHelper(), - state: stateBefore, - recommendState: instance.getHelper()!.recommendState, parent: instance, }); }); @@ -2972,22 +2951,11 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/index-widge expect(widget.dispose).toHaveBeenCalledTimes(0); }); - // Save the Helper to be able to simulate the search - const helper = instance.getHelper(); - - instance.dispose( - createDisposeOptions({ - helper: instantSearchInstance.helper!, - state: instantSearchInstance.helper!.state, - }) - ); + instance.dispose(createDisposeOptions()); widgets.forEach((widget) => { expect(widget.dispose).toHaveBeenCalledTimes(1); expect(widget.dispose).toHaveBeenCalledWith({ - state: helper!.state, - recommendState: helper!.recommendState, - helper, parent: instance, }); }); diff --git a/packages/instantsearch-core/src/widgets/index-widget.ts b/packages/instantsearch-core/src/widgets/index-widget.ts index 8b4fbcfc3f..719a12c620 100644 --- a/packages/instantsearch-core/src/widgets/index-widget.ts +++ b/packages/instantsearch-core/src/widgets/index-widget.ts @@ -438,45 +438,34 @@ export const index = (widgetParams: IndexWidgetParams): IndexWidget => { }); if (localInstantSearchInstance && Boolean(widgets.length)) { - const { cleanedRecommendState } = widgets.reduce( - (states, widget) => { - // @MAJOR remove the "cleanup" part of the dispose method - // the `dispose` method exists at this point we already assert it - const next = widget.dispose!({ - helper: helper!, - state: states.cleanedSearchState, - recommendState: states.cleanedRecommendState, - parent: this, - }); - - if (next instanceof algoliasearchHelper.RecommendParameters) { - states.cleanedRecommendState = next; - } else if (next) { - states.cleanedSearchState = next; - } + widgets.forEach((widget) => + widget.dispose!({ + parent: this, + }) + ); - return states; - }, + helper!.setState( + getLocalWidgetsSearchParameters(localWidgets, { + uiState: localUiState, + initialSearchParameters: new algoliasearchHelper.SearchParameters({ + index: this.getIndexName(), + }), + }) + ); + helper!.recommendState = getLocalWidgetsRecommendParameters( + localWidgets, { - cleanedSearchState: helper!.state, - cleanedRecommendState: helper!.recommendState, + uiState: localUiState, + initialRecommendParameters: + new algoliasearchHelper.RecommendParameters(), } ); - const newState = getLocalWidgetsSearchParameters(localWidgets, { - uiState: localUiState, - initialSearchParameters: new algoliasearchHelper.SearchParameters({ - index: this.getIndexName(), - }), - }); localUiState = getLocalWidgetsUiState(localWidgets, { - searchParameters: newState, + searchParameters: helper!.state, helper: helper!, }); - helper!.setState(newState); - helper!.recommendState = cleanedRecommendState; - if (localWidgets.length) { localInstantSearchInstance.scheduleSearch(); } @@ -791,9 +780,6 @@ export const index = (widgetParams: IndexWidgetParams): IndexWidget => { // because we want to keep the widgets on the instance, to allow idempotent // operations on `add` & `remove`. widget.dispose({ - helper, - state: helper.state, - recommendState: helper.recommendState, parent: this, }); } diff --git a/packages/instantsearch-core/test/createWidget.ts b/packages/instantsearch-core/test/createWidget.ts index da46a57401..7f9b57c267 100644 --- a/packages/instantsearch-core/test/createWidget.ts +++ b/packages/instantsearch-core/test/createWidget.ts @@ -1,6 +1,8 @@ import { createMultiSearchResponse } from '@instantsearch/mocks'; import algoliasearchHelper from 'algoliasearch-helper'; +import { index } from '../src'; + import { createInstantSearch } from './createInstantSearch'; import type { @@ -81,14 +83,8 @@ export const createRenderOptions = ( export const createDisposeOptions = ( args: Partial = {} ): DisposeOptions => { - const instantSearchInstance = createInstantSearch(); - const helper = args.helper || instantSearchInstance.helper!; - return { - helper, - state: helper.state, - recommendState: helper.recommendState, - parent: instantSearchInstance.mainIndex, + parent: index({ indexName: 'indexName' }), ...args, }; }; diff --git a/packages/instantsearch.js/src/components/Panel/__tests__/Panel-test.tsx b/packages/instantsearch.js/src/components/Panel/__tests__/Panel-test.tsx index 4a20dac126..e5641caf82 100644 --- a/packages/instantsearch.js/src/components/Panel/__tests__/Panel-test.tsx +++ b/packages/instantsearch.js/src/components/Panel/__tests__/Panel-test.tsx @@ -4,9 +4,9 @@ /** @jsx h */ import { render, fireEvent } from '@testing-library/preact'; +import { createRenderOptions } from 'instantsearch-core/test/createWidget'; import { h } from 'preact'; -import { createRenderOptions } from '../../../../test/createWidget'; import Panel from '../Panel'; import type { PanelProps } from '../Panel'; diff --git a/packages/instantsearch.js/src/widgets/dynamic-widgets/__tests__/dynamic-widgets-test.ts b/packages/instantsearch.js/src/widgets/dynamic-widgets/__tests__/dynamic-widgets-test.ts index 80e4220144..3600a5f4e7 100644 --- a/packages/instantsearch.js/src/widgets/dynamic-widgets/__tests__/dynamic-widgets-test.ts +++ b/packages/instantsearch.js/src/widgets/dynamic-widgets/__tests__/dynamic-widgets-test.ts @@ -9,14 +9,14 @@ import { import { wait } from '@instantsearch/testutils/wait'; import { widgetSnapshotSerializer } from '@instantsearch/testutils/widgetSnapshotSerializer'; import { SearchParameters, SearchResults } from 'algoliasearch-helper'; - -import { index, searchBox, menu, dynamicWidgets } from '../..'; -import instantsearch from '../../..'; -import { createInstantSearch } from '../../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createInitOptions, createRenderOptions, -} from '../../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; + +import { index, searchBox, menu, dynamicWidgets } from '../..'; +import instantsearch from '../../..'; import refinementList from '../../refinement-list/refinement-list'; import type { SearchResponse } from 'instantsearch-core'; diff --git a/packages/instantsearch.js/src/widgets/geo-search/__tests__/geo-search-test.ts b/packages/instantsearch.js/src/widgets/geo-search/__tests__/geo-search-test.ts index 9f4224eaa0..7554abad65 100644 --- a/packages/instantsearch.js/src/widgets/geo-search/__tests__/geo-search-test.ts +++ b/packages/instantsearch.js/src/widgets/geo-search/__tests__/geo-search-test.ts @@ -9,14 +9,13 @@ import { } from '@instantsearch/mocks'; import { castToJestMock } from '@instantsearch/testutils/castToJestMock'; import algoliasearchHelper, { SearchResults } from 'algoliasearch-helper'; -import { render as preactRender } from 'preact'; - -import { createInstantSearch } from '../../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { - createDisposeOptions, createInitOptions, createRenderOptions, -} from '../../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; +import { render as preactRender } from 'preact'; + import createHTMLMarker from '../createHTMLMarker'; import geoSearch from '../geo-search'; import originalRenderer from '../GeoSearchRenderer'; @@ -366,50 +365,6 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/geo-search/ }); }); - it('expect to unmount', () => { - const container = createContainer(); - const instantSearchInstance = createFakeInstantSearch(); - const helper = createFakeHelper(); - const googleReference = createFakeGoogleReference(); - - const widget = geoSearch({ - googleReference, - container, - }); - - widget.init!( - createInitOptions({ - helper, - instantSearchInstance, - state: helper.state, - }) - ); - - widget.render!( - createRenderOptions({ - helper, - instantSearchInstance, - results: new SearchResults(helper.state, [ - createSingleSearchResponse({ - hits: [], - }), - ]), - }) - ); - - expect(render).toHaveBeenCalledTimes(1); - - widget.dispose!( - createDisposeOptions({ - helper, - state: helper.state, - }) - ); - - expect(render).toHaveBeenCalledTimes(2); - expect(render).toHaveBeenCalledWith(null, container); - }); - describe('setup events', () => { it('expect to listen for "idle" once and trigger the registration of the rest of the listeners', () => { const container = createContainer(); diff --git a/packages/instantsearch.js/src/widgets/panel/__tests__/panel-test.ts b/packages/instantsearch.js/src/widgets/panel/__tests__/panel-test.ts index e8a88b1ee6..633ffbb84b 100644 --- a/packages/instantsearch.js/src/widgets/panel/__tests__/panel-test.ts +++ b/packages/instantsearch.js/src/widgets/panel/__tests__/panel-test.ts @@ -3,14 +3,13 @@ */ import { castToJestMock } from '@instantsearch/testutils/castToJestMock'; -import algoliasearchHelper from 'algoliasearch-helper'; -import { render as preactRender } from 'preact'; - import { createInitOptions, createRenderOptions, createDisposeOptions, -} from '../../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; +import { render as preactRender } from 'preact'; + import panel from '../panel'; import type { PanelProps } from '../../../components/Panel/Panel'; @@ -433,13 +432,10 @@ describe('Lifecycle', () => { describe('dispose', () => { test("returns the state from the widget's dispose function", () => { - const nextSearchParameters = new algoliasearchHelper.SearchParameters({ - facets: ['brands'], - }); const widget = { $$type: 'mock.widget', init: jest.fn(), - dispose: jest.fn(() => nextSearchParameters), + dispose: jest.fn(), }; const widgetFactory = () => widget; @@ -447,9 +443,9 @@ describe('Lifecycle', () => { container: document.createElement('div'), }); - const nextState = widgetWithPanel.dispose!(createDisposeOptions()); + widgetWithPanel.dispose!(createDisposeOptions()); - expect(nextState).toEqual(nextSearchParameters); + expect(widget.dispose).toHaveBeenCalled(); }); }); }); diff --git a/packages/instantsearch.js/src/widgets/query-rule-custom-data/__tests__/query-rule-custom-data-test.ts b/packages/instantsearch.js/src/widgets/query-rule-custom-data/__tests__/query-rule-custom-data-test.ts index 1caed4e218..71d8a19660 100644 --- a/packages/instantsearch.js/src/widgets/query-rule-custom-data/__tests__/query-rule-custom-data-test.ts +++ b/packages/instantsearch.js/src/widgets/query-rule-custom-data/__tests__/query-rule-custom-data-test.ts @@ -5,12 +5,9 @@ import { createSearchClient } from '@instantsearch/mocks'; import { castToJestMock } from '@instantsearch/testutils/castToJestMock'; import algoliasearchHelper from 'algoliasearch-helper'; +import { createInitOptions } from 'instantsearch-core/test/createWidget'; import { render as preactRender } from 'preact'; -import { - createDisposeOptions, - createInitOptions, -} from '../../../../test/createWidget'; import queryRuleCustomData from '../query-rule-custom-data'; import type { QueryRuleCustomDataProps } from '../../../components/QueryRuleCustomData/QueryRuleCustomData'; @@ -190,35 +187,4 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/query-rule- }); }); }); - - describe('Lifecycle', () => { - describe('unmountFn', () => { - test('unmounts the component', () => { - const container = document.createElement('div'); - const helper = createFakeHelper(); - const widget = queryRuleCustomData({ - container, - }); - - widget.init!( - createInitOptions({ - helper, - state: helper.state, - }) - ); - - expect(render).toHaveBeenCalledTimes(1); - - widget.dispose!( - createDisposeOptions({ - helper, - state: helper.state, - }) - ); - - expect(render).toHaveBeenCalledTimes(2); - expect(render).toHaveBeenCalledWith(null, container); - }); - }); - }); }); diff --git a/packages/instantsearch.js/src/widgets/range-slider/__tests__/range-slider-test.ts b/packages/instantsearch.js/src/widgets/range-slider/__tests__/range-slider-test.ts index 679c87743d..05e783275d 100644 --- a/packages/instantsearch.js/src/widgets/range-slider/__tests__/range-slider-test.ts +++ b/packages/instantsearch.js/src/widgets/range-slider/__tests__/range-slider-test.ts @@ -11,13 +11,13 @@ import algoliasearchHelper, { SearchParameters, SearchResults, } from 'algoliasearch-helper'; -import { render as preactRender } from 'preact'; - -import { createInstantSearch } from '../../../../test/createInstantSearch'; +import { createInstantSearch } from 'instantsearch-core/test/createInstantSearch'; import { createInitOptions, createRenderOptions, -} from '../../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; +import { render as preactRender } from 'preact'; + import rangeSlider from '../range-slider'; import type { InstantSearch } from '../../../types'; diff --git a/packages/instantsearch.js/src/widgets/relevant-sort/__tests__/relevant-sort-test.ts b/packages/instantsearch.js/src/widgets/relevant-sort/__tests__/relevant-sort-test.ts index 51eb9cbb36..ff20760835 100644 --- a/packages/instantsearch.js/src/widgets/relevant-sort/__tests__/relevant-sort-test.ts +++ b/packages/instantsearch.js/src/widgets/relevant-sort/__tests__/relevant-sort-test.ts @@ -7,12 +7,12 @@ import { createSingleSearchResponse, } from '@instantsearch/mocks'; import algoliasearchHelper, { SearchResults } from 'algoliasearch-helper'; -import { render } from 'preact'; - import { createInitOptions, createRenderOptions, -} from '../../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; +import { render } from 'preact'; + import relevantSort from '../relevant-sort'; import type { RelevantSortTemplates } from '../relevant-sort'; diff --git a/packages/instantsearch.js/src/widgets/voice-search/__tests__/voice-search-test.ts b/packages/instantsearch.js/src/widgets/voice-search/__tests__/voice-search-test.ts index f3bdc5cf07..ad7e603e3d 100644 --- a/packages/instantsearch.js/src/widgets/voice-search/__tests__/voice-search-test.ts +++ b/packages/instantsearch.js/src/widgets/voice-search/__tests__/voice-search-test.ts @@ -11,12 +11,12 @@ import algoliasearchHelper, { SearchResults, SearchParameters, } from 'algoliasearch-helper'; -import { render as preactRender } from 'preact'; - import { createInitOptions, createRenderOptions, -} from '../../../../test/createWidget'; +} from 'instantsearch-core/test/createWidget'; +import { render as preactRender } from 'preact'; + import voiceSearch from '../voice-search'; import type { VoiceSearchProps } from '../../../components/VoiceSearch/VoiceSearch'; diff --git a/packages/instantsearch.js/stories/geo-search.stories.ts b/packages/instantsearch.js/stories/geo-search.stories.ts index 4ac7622906..7524eb1a39 100644 --- a/packages/instantsearch.js/stories/geo-search.stories.ts +++ b/packages/instantsearch.js/stories/geo-search.stories.ts @@ -490,7 +490,7 @@ stories if (hitElement) { removeActiveMarkerClassNames(); - const objectID = parseInt(hitElement.id.substr(4), 10); + const objectID = parseInt(hitElement.id.slice(4), 10); const selector = `.my-custom-marker[data-id="${objectID}"]`; const marker = document.querySelector(selector); diff --git a/packages/instantsearch.js/test/createInstantSearch.ts b/packages/instantsearch.js/test/createInstantSearch.ts deleted file mode 100644 index 258711c43d..0000000000 --- a/packages/instantsearch.js/test/createInstantSearch.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { createSearchClient } from '@instantsearch/mocks'; -import algoliasearchHelper from 'algoliasearch-helper'; - -import { INSTANTSEARCH_FUTURE_DEFAULTS } from '../src/lib/InstantSearch'; -import { defer } from '../src/lib/utils'; -import { index } from '../src/widgets'; - -import type { InstantSearch } from '../src/types'; - -export const createInstantSearch = ( - args: Partial = {} -): InstantSearch => { - const { indexName = 'indexName', client = createSearchClient() } = args; - const mainHelper = algoliasearchHelper(client, indexName, {}); - const mainIndex = index({ indexName }); - - return { - indexName, - mainIndex, - mainHelper, - client, - started: false, - status: 'idle', - error: undefined, - start() { - this.started = true; - }, - dispose() { - this.started = false; - }, - refresh: jest.fn(), - helper: mainHelper, // @TODO: use the Helper from the index once the RoutingManger uses the index - middleware: [], - renderState: {}, - scheduleStalledRender: defer(jest.fn()), - scheduleSearch: defer(jest.fn()), - scheduleRender: defer(jest.fn()), - _stalledSearchDelay: 200, - _searchStalledTimer: null, - _initialUiState: {}, - _initialResults: null, - _createURL: jest.fn(() => '#'), - _insights: undefined, - _hasRecommendWidget: false, - _hasSearchWidget: false, - onStateChange: null, - setUiState: jest.fn(), - getUiState: jest.fn(() => ({})), - // Since we defer `onInternalStateChange` with our `defer` util which - // creates a scoped deferred function, we're not able to spy that method. - // We'll therefore need to override it when calling `createInstantSearch`. - // See https://github.com/algolia/instantsearch/blob/f3213b2f118d75acac31a1f6cf4640241c438e9d/src/lib/utils/defer.ts#L13-L28 - onInternalStateChange: jest.fn() as any, - createURL: jest.fn(() => '#'), - addWidget: jest.fn(), - addWidgets: jest.fn(), - removeWidget: jest.fn(), - removeWidgets: jest.fn(), - use: jest.fn(), - unuse: jest.fn(), - // methods from EventEmitter - addListener: jest.fn(), - removeListener: jest.fn(), - on: jest.fn(), - once: jest.fn(), - removeAllListeners: jest.fn(), - setMaxListeners: jest.fn(), - listeners: jest.fn(), - emit: jest.fn(), - listenerCount: jest.fn(), - sendEventToInsights: jest.fn(), - future: { - ...INSTANTSEARCH_FUTURE_DEFAULTS, - ...(args.future || {}), - }, - ...args, - }; -}; diff --git a/packages/instantsearch.js/test/createWidget.ts b/packages/instantsearch.js/test/createWidget.ts deleted file mode 100644 index 72a70c0c02..0000000000 --- a/packages/instantsearch.js/test/createWidget.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { createMultiSearchResponse } from '@instantsearch/mocks'; -import algoliasearchHelper from 'algoliasearch-helper'; - -import { createInstantSearch } from './createInstantSearch'; - -import type { - InitOptions, - RenderOptions, - DisposeOptions, - Widget, -} from '../src/types'; -import type { IndexInitOptions } from '../src/widgets/index/index'; -import type { SearchResponse } from 'algoliasearch-helper/types/algoliasearch'; - -export const createInitOptions = ( - args: Partial = {} -): InitOptions => { - const { instantSearchInstance = createInstantSearch(), ...rest } = args; - const helper = args.helper || instantSearchInstance.helper!; - - return { - instantSearchInstance, - parent: instantSearchInstance.mainIndex, - uiState: instantSearchInstance._initialUiState, - helper, - state: helper.state, - renderState: instantSearchInstance.renderState, - scopedResults: [], - createURL: jest.fn(() => '#'), - status: instantSearchInstance.status, - error: instantSearchInstance.error, - ...rest, - }; -}; - -export const createIndexInitOptions = ( - args: Partial = {} -): IndexInitOptions => { - const { instantSearchInstance = createInstantSearch(), ...rest } = args; - - return { - instantSearchInstance, - parent: instantSearchInstance.mainIndex, - uiState: instantSearchInstance._initialUiState, - ...rest, - }; -}; - -export const createRenderOptions = ( - args: Partial = {} -): RenderOptions => { - const { instantSearchInstance = createInstantSearch(), ...rest } = args; - const response = createMultiSearchResponse(); - const helper = args.helper || instantSearchInstance.helper!; - const results = new algoliasearchHelper.SearchResults( - instantSearchInstance.helper!.state, - response.results as Array> - ); - - return { - instantSearchInstance, - parent: instantSearchInstance.mainIndex, - helper, - state: helper.state, - renderState: instantSearchInstance.renderState, - results, - scopedResults: [ - { - indexId: helper.state.index, - helper, - results, - }, - ], - status: instantSearchInstance.status, - error: instantSearchInstance.error, - createURL: jest.fn(() => '#'), - ...rest, - }; -}; - -export const createDisposeOptions = ( - args: Partial = {} -): DisposeOptions => { - const instantSearchInstance = createInstantSearch(); - const helper = args.helper || instantSearchInstance.helper!; - - return { - helper, - state: helper.state, - recommendState: helper.recommendState, - parent: instantSearchInstance.mainIndex, - ...args, - }; -}; - -export const createWidget = (args: Partial = {}): Widget => - ({ - $$type: 'mock.widget', - init: jest.fn(), - render: jest.fn(), - dispose: jest.fn(), - ...args, - } as unknown as Widget); diff --git a/packages/react-instantsearch/src/widgets/__tests__/all-widgets.test.tsx b/packages/react-instantsearch/src/widgets/__tests__/all-widgets.test.tsx index 8fbab91543..8d538afd42 100644 --- a/packages/react-instantsearch/src/widgets/__tests__/all-widgets.test.tsx +++ b/packages/react-instantsearch/src/widgets/__tests__/all-widgets.test.tsx @@ -29,7 +29,7 @@ describe('widgets', () => { test('starts with "ais."', () => { widgets.forEach(({ name, widget }) => - expect([name, widget.$$type.substr(0, 4)]).toEqual([name, 'ais.']) + expect([name, widget.$$type.slice(0, 4)]).toEqual([name, 'ais.']) ); }); }); @@ -43,10 +43,7 @@ describe('widgets', () => { test('starts with "ais."', () => { widgets.forEach(({ name, widget }) => - expect([name, widget.$$widgetType!.substr(0, 4)]).toEqual([ - name, - 'ais.', - ]) + expect([name, widget.$$widgetType!.slice(0, 4)]).toEqual([name, 'ais.']) ); }); }); diff --git a/packages/vue-instantsearch/src/util/__tests__/createServerRootMixin.test.js b/packages/vue-instantsearch/src/util/__tests__/createServerRootMixin.test.js index 938c961b65..2e95a9616a 100644 --- a/packages/vue-instantsearch/src/util/__tests__/createServerRootMixin.test.js +++ b/packages/vue-instantsearch/src/util/__tests__/createServerRootMixin.test.js @@ -244,28 +244,20 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsear await renderToString(wrapper); - expect(mainIndex.getWidgetUiState({})).toMatchInlineSnapshot(` - { - "hello": { - "configure": { - "hitsPerPage": 100, - }, - }, - } - `); + expect(mainIndex.getWidgetUiState({})).toEqual({ + hello: {}, + }); expect(searchClient.search).toHaveBeenCalledTimes(1); - expect(searchClient.search.mock.calls[0][0]).toMatchInlineSnapshot(` - [ - { - "indexName": "hello", - "params": { - "hitsPerPage": 100, - "query": "", - }, + expect(searchClient.search.mock.calls[0][0]).toEqual([ + { + indexName: 'hello', + params: { + hitsPerPage: 100, + query: '', }, - ] - `); + }, + ]); }); it('returns correct results state', () => { @@ -870,17 +862,15 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsear await renderToString(wrapper); expect(searchClient.search).toHaveBeenCalledTimes(1); - expect(searchClient.search.mock.calls[0][0]).toMatchInlineSnapshot(` - [ - { - "indexName": "hello", - "params": { - "hitsPerPage": 100, - "query": "", - }, + expect(searchClient.search.mock.calls[0][0]).toEqual([ + { + indexName: 'hello', + params: { + hitsPerPage: 100, + query: '', }, - ] - `); + }, + ]); }); it('works when component is at root (and therefore has no $vnode)', async () => { @@ -933,28 +923,20 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsear await renderToString(wrapper); - expect(mainIndex.getWidgetUiState({})).toMatchInlineSnapshot(` - { - "hello": { - "configure": { - "hitsPerPage": 100, - }, - }, - } - `); + expect(mainIndex.getWidgetUiState({})).toEqual({ + hello: {}, + }); expect(searchClient.search).toHaveBeenCalledTimes(1); - expect(searchClient.search.mock.calls[0][0]).toMatchInlineSnapshot(` - [ - { - "indexName": "hello", - "params": { - "hitsPerPage": 100, - "query": "", - }, + expect(searchClient.search.mock.calls[0][0]).toEqual([ + { + indexName: 'hello', + params: { + hitsPerPage: 100, + query: '', }, - ] - `); + }, + ]); }); } }); @@ -1117,39 +1099,21 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsear const renderArgs = widget.render.mock.calls[0][0]; - expect(renderArgs).toMatchInlineSnapshot( - { - helper: expect.anything(), - results: expect.anything(), - scopedResults: expect.arrayContaining([ - expect.objectContaining({ - helper: expect.anything(), - indexId: expect.any(String), - results: expect.anything(), - }), - ]), - parent: expect.anything(), - state: expect.anything(), - instantSearchInstance: expect.anything(), - }, - ` - { - "createURL": [Function], - "helper": Anything, - "instantSearchInstance": Anything, - "parent": Anything, - "results": Anything, - "scopedResults": ArrayContaining [ - ObjectContaining { - "helper": Anything, - "indexId": Any, - "results": Anything, - }, - ], - "state": Anything, - } - ` - ); + expect(renderArgs).toEqual({ + createURL: expect.any(Function), + helper: expect.anything(), + results: expect.anything(), + scopedResults: expect.arrayContaining([ + expect.objectContaining({ + helper: expect.anything(), + indexId: expect.any(String), + results: expect.anything(), + }), + ]), + parent: expect.anything(), + state: expect.anything(), + instantSearchInstance: expect.anything(), + }); }); it('uses the results passed to hydrate for rendering', () => {