From 0154995e93cf220edfde631cba76a073dee34fe7 Mon Sep 17 00:00:00 2001 From: Haroen Viaene Date: Tue, 21 May 2024 09:49:18 +0200 Subject: [PATCH] fix(queries): prevent network request (#6205) --- bundlesize.config.json | 6 +- .../instantsearch.js/src/lib/InstantSearch.ts | 14 +- .../InstantSearch-integration-test.ts | 517 +++++++++++++++++- .../src/widgets/index/index.ts | 43 +- .../test/createInstantSearch.ts | 2 + .../__tests__/useRelatedProducts.test.tsx | 11 +- .../__tests__/useTrendingItems.test.tsx | 11 +- .../FrequentlyBoughtTogether.test.tsx | 2 +- .../widgets/__tests__/LookingSimilar.test.tsx | 2 +- .../__tests__/RelatedProducts.test.tsx | 2 +- .../widgets/__tests__/TrendingItems.test.tsx | 2 +- 11 files changed, 591 insertions(+), 21 deletions(-) diff --git a/bundlesize.config.json b/bundlesize.config.json index ceae09ddb0..e77eb74715 100644 --- a/bundlesize.config.json +++ b/bundlesize.config.json @@ -10,7 +10,7 @@ }, { "path": "./packages/instantsearch.js/dist/instantsearch.production.min.js", - "maxSize": "80.5 kB" + "maxSize": "81.5 kB" }, { "path": "./packages/instantsearch.js/dist/instantsearch.development.js", @@ -18,11 +18,11 @@ }, { "path": "packages/react-instantsearch-core/dist/umd/ReactInstantSearchCore.min.js", - "maxSize": "48.5 kB" + "maxSize": "49.5 kB" }, { "path": "packages/react-instantsearch/dist/umd/ReactInstantSearch.min.js", - "maxSize": "62 kB" + "maxSize": "62.5 kB" }, { "path": "packages/vue-instantsearch/vue2/umd/index.js", diff --git a/packages/instantsearch.js/src/lib/InstantSearch.ts b/packages/instantsearch.js/src/lib/InstantSearch.ts index df3ae5cd34..e6ef136d12 100644 --- a/packages/instantsearch.js/src/lib/InstantSearch.ts +++ b/packages/instantsearch.js/src/lib/InstantSearch.ts @@ -222,6 +222,8 @@ class InstantSearch< public _createURL: CreateURL; public _searchFunction?: InstantSearchOptions['searchFunction']; public _mainHelperSearch?: AlgoliaSearchHelper['search']; + public _hasSearchWidget: boolean = false; + public _hasRecommendWidget: boolean = false; public _insights: InstantSearchOptions['insights']; public middleware: Array<{ creator: Middleware; @@ -580,9 +582,15 @@ See documentation: ${createDocumentationLink({ // under the hood, we have a different implementation. It should be // completely transparent for the rest of the codebase. Only this module // is impacted. - return ( - mainHelper.searchOnlyWithDerivedHelpers() && mainHelper.recommend() - ); + if (this._hasSearchWidget) { + mainHelper.searchOnlyWithDerivedHelpers(); + } + + if (this._hasRecommendWidget) { + mainHelper.recommend(); + } + + return mainHelper; }; if (this._searchFunction) { diff --git a/packages/instantsearch.js/src/lib/__tests__/InstantSearch-integration-test.ts b/packages/instantsearch.js/src/lib/__tests__/InstantSearch-integration-test.ts index 849b13154e..f5bbf70d21 100644 --- a/packages/instantsearch.js/src/lib/__tests__/InstantSearch-integration-test.ts +++ b/packages/instantsearch.js/src/lib/__tests__/InstantSearch-integration-test.ts @@ -3,12 +3,14 @@ */ 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 { connectConfigure, connectSearchBox } from '../../connectors'; import instantsearch from '../../index.es'; -import { configure, searchBox } from '../../widgets'; +import { configure, frequentlyBoughtTogether, searchBox } from '../../widgets'; import type { MiddlewareDefinition } from '../../types'; @@ -156,3 +158,516 @@ describe('errors', () => { search.start(); }); }); + +describe('network requests', () => { + describe('no insights', () => { + it('sends no search or recommend query when there are no widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + }).start(); + + await wait(0); + + expect( + castToJestMock(searchClient.search).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + }); + + it('sends only one search query when there are search widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + }) + .addWidgets([searchBox({ container: document.createElement('div') })]) + .start(); + + await wait(0); + + expect(castToJestMock(searchClient.search).mock.calls[0]?.[0]) + .toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "params": { + "facets": [], + "query": "", + "tagFilters": "", + }, + }, + ] + `); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + }); + + it('sends only one recommend query when there are recommend widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + }) + .addWidgets([ + frequentlyBoughtTogether({ + objectIDs: ['one'], + container: document.createElement('div'), + }), + ]) + .start(); + + await wait(0); + + expect( + castToJestMock(searchClient.search).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "maxRecommendations": undefined, + "model": "bought-together", + "objectID": "one", + "queryParameters": { + "highlightPostTag": "__/ais-highlight__", + "highlightPreTag": "__ais-highlight__", + }, + "threshold": undefined, + }, + ] + `); + }); + + it('sends only one search and recommend query when there are search and recommend widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + }) + .addWidgets([ + searchBox({ container: document.createElement('div') }), + frequentlyBoughtTogether({ + objectIDs: ['one'], + container: document.createElement('div'), + }), + ]) + .start(); + + await wait(0); + + expect(castToJestMock(searchClient.search).mock.calls[0]?.[0]) + .toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "params": { + "facets": [], + "query": "", + "tagFilters": "", + }, + }, + ] + `); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "maxRecommendations": undefined, + "model": "bought-together", + "objectID": "one", + "queryParameters": { + "highlightPostTag": "__/ais-highlight__", + "highlightPreTag": "__ais-highlight__", + }, + "threshold": undefined, + }, + ] + `); + }); + }); + + describe('with insights', () => { + let cookie: string; + beforeEach(() => { + cookie = document.cookie; + document.cookie = '_ALGOLIA=cookie-key'; + }); + + afterEach(() => { + document.cookie = cookie; + }); + + it('sends no search or recommend query when there are no widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + insights: true, + }).start(); + + await wait(0); + + expect( + castToJestMock(searchClient.search).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + }); + + it('sends only one search query when there are search widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + insights: true, + }) + .addWidgets([searchBox({ container: document.createElement('div') })]) + .start(); + + await wait(0); + + expect(castToJestMock(searchClient.search).mock.calls[0]?.[0]) + .toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "params": { + "clickAnalytics": true, + "facets": [], + "query": "", + "tagFilters": "", + "userToken": "cookie-key", + }, + }, + ] + `); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + }); + + it('sends only one recommend query when there are recommend widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + insights: true, + }) + .addWidgets([ + frequentlyBoughtTogether({ + objectIDs: ['one'], + container: document.createElement('div'), + }), + ]) + .start(); + + await wait(0); + + expect( + castToJestMock(searchClient.search).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "maxRecommendations": undefined, + "model": "bought-together", + "objectID": "one", + "queryParameters": { + "highlightPostTag": "__/ais-highlight__", + "highlightPreTag": "__ais-highlight__", + }, + "threshold": undefined, + }, + ] + `); + }); + + it('sends only one search and recommend query when there are search and recommend widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + insights: true, + }) + .addWidgets([ + searchBox({ container: document.createElement('div') }), + frequentlyBoughtTogether({ + objectIDs: ['one'], + container: document.createElement('div'), + }), + ]) + .start(); + + await wait(0); + + expect(castToJestMock(searchClient.search).mock.calls[0]?.[0]) + .toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "params": { + "clickAnalytics": true, + "facets": [], + "query": "", + "tagFilters": "", + "userToken": "cookie-key", + }, + }, + ] + `); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "maxRecommendations": undefined, + "model": "bought-together", + "objectID": "one", + "queryParameters": { + "highlightPostTag": "__/ais-highlight__", + "highlightPreTag": "__ais-highlight__", + }, + "threshold": undefined, + }, + ] + `); + }); + }); + + describe('with insights (no cookie)', () => { + let cookie: string; + beforeEach(() => { + cookie = document.cookie; + document.cookie = '_ALGOLIA='; + }); + + afterEach(() => { + document.cookie = cookie; + }); + + it('sends no search or recommend query when there are no widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + insights: true, + }).start(); + + await wait(0); + + expect( + castToJestMock(searchClient.search).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + }); + + it('sends only one search query when there are search widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + insights: true, + }) + .addWidgets([searchBox({ container: document.createElement('div') })]) + .start(); + + await wait(0); + + expect(castToJestMock(searchClient.search).mock.calls[0]?.[0]) + .toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "params": { + "clickAnalytics": true, + "facets": [], + "query": "", + "tagFilters": "", + }, + }, + ] + `); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + }); + + it('sends only one recommend query when there are recommend widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + insights: true, + }) + .addWidgets([ + frequentlyBoughtTogether({ + objectIDs: ['one'], + container: document.createElement('div'), + }), + ]) + .start(); + + await wait(0); + + expect( + castToJestMock(searchClient.search).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(`undefined`); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "maxRecommendations": undefined, + "model": "bought-together", + "objectID": "one", + "queryParameters": { + "highlightPostTag": "__/ais-highlight__", + "highlightPreTag": "__ais-highlight__", + }, + "threshold": undefined, + }, + ] + `); + }); + + it('sends only one search and recommend query when there are search and recommend widgets', async () => { + const searchClient = createRecommendSearchClient(); + instantsearch({ + indexName: 'indexName', + searchClient, + insights: true, + }) + .addWidgets([ + searchBox({ container: document.createElement('div') }), + frequentlyBoughtTogether({ + objectIDs: ['one'], + container: document.createElement('div'), + }), + ]) + .start(); + + await wait(0); + + expect(castToJestMock(searchClient.search).mock.calls[0]?.[0]) + .toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "params": { + "clickAnalytics": true, + "facets": [], + "query": "", + "tagFilters": "", + }, + }, + ] + `); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "maxRecommendations": undefined, + "model": "bought-together", + "objectID": "one", + "queryParameters": { + "highlightPostTag": "__/ais-highlight__", + "highlightPreTag": "__ais-highlight__", + }, + "threshold": undefined, + }, + ] + `); + }); + }); + + describe('interactive life cycle', () => { + it('sends no queries when widgets are removed', async () => { + const searchClient = createRecommendSearchClient(); + const searchBoxWidget = searchBox({ + container: document.createElement('div'), + }); + const frequentlyBoughtTogetherWidget = frequentlyBoughtTogether({ + objectIDs: ['one'], + container: document.createElement('div'), + }); + const search = instantsearch({ + indexName: 'indexName', + searchClient, + }).addWidgets([searchBoxWidget, frequentlyBoughtTogetherWidget]); + + search.start(); + await wait(0); + + expect(castToJestMock(searchClient.search).mock.calls[0]?.[0]) + .toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "params": { + "facets": [], + "query": "", + "tagFilters": "", + }, + }, + ] + `); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[0]?.[0] + ).toMatchInlineSnapshot(` + [ + { + "indexName": "indexName", + "maxRecommendations": undefined, + "model": "bought-together", + "objectID": "one", + "queryParameters": { + "highlightPostTag": "__/ais-highlight__", + "highlightPreTag": "__ais-highlight__", + }, + "threshold": undefined, + }, + ] + `); + + search.removeWidgets([searchBoxWidget, frequentlyBoughtTogetherWidget]); + + await wait(0); + + expect( + castToJestMock(searchClient.search).mock.calls[1]?.[0] + ).toMatchInlineSnapshot(`undefined`); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[1]?.[0] + ).toMatchInlineSnapshot(`undefined`); + + // Ensure that calling search() after removing all widgets doesn't trigger a new search + search.helper!.search(); + + expect( + castToJestMock(searchClient.search).mock.calls[2]?.[0] + ).toMatchInlineSnapshot(`undefined`); + expect( + castToJestMock(searchClient.getRecommendations!).mock.calls[2]?.[0] + ).toMatchInlineSnapshot(`undefined`); + }); + }); +}); diff --git a/packages/instantsearch.js/src/widgets/index/index.ts b/packages/instantsearch.js/src/widgets/index/index.ts index c3ac1dcec7..24f7a59a62 100644 --- a/packages/instantsearch.js/src/widgets/index/index.ts +++ b/packages/instantsearch.js/src/widgets/index/index.ts @@ -273,6 +273,8 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { let helper: Helper | null = null; let derivedHelper: DerivedHelper | null = null; let lastValidSearchParameters: SearchParameters | null = null; + let hasRecommendWidget: boolean = false; + let hasSearchWidget: boolean = false; return { $$type: 'ais.index', @@ -382,11 +384,20 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { return; } + if (localInstantSearchInstance && widget.dependsOn === 'recommend') { + localInstantSearchInstance._hasRecommendWidget = true; + } else if (localInstantSearchInstance) { + localInstantSearchInstance._hasSearchWidget = true; + } else if (widget.dependsOn === 'recommend') { + hasRecommendWidget = true; + } else { + hasSearchWidget = true; + } + addWidgetId(widget); }); localWidgets = localWidgets.concat(widgets); - if (localInstantSearchInstance && Boolean(widgets.length)) { privateHelperSetState(helper!, { state: getLocalWidgetsSearchParameters(localWidgets, { @@ -457,6 +468,22 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { (widget) => widgets.indexOf(widget) === -1 ); + localWidgets.forEach((widget) => { + if (isIndexWidget(widget)) { + return; + } + + if (localInstantSearchInstance && widget.dependsOn === 'recommend') { + localInstantSearchInstance._hasRecommendWidget = true; + } else if (localInstantSearchInstance) { + localInstantSearchInstance._hasSearchWidget = true; + } else if (widget.dependsOn === 'recommend') { + hasRecommendWidget = true; + } else { + hasSearchWidget = true; + } + }); + if (localInstantSearchInstance && Boolean(widgets.length)) { const { cleanedSearchState, cleanedRecommendState } = widgets.reduce( (states, widget) => { @@ -734,6 +761,13 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { // schedule a render that will render the results injected on the helper. instantSearchInstance.scheduleRender(); } + + if (hasRecommendWidget) { + instantSearchInstance._hasRecommendWidget = true; + } + if (hasSearchWidget) { + instantSearchInstance._hasSearchWidget = true; + } }, render({ instantSearchInstance }: IndexRenderOptions) { @@ -749,9 +783,10 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { // We only render index widgets if there are no results. // This makes sure `render` is never called with `results` being `null`. - let widgetsToRender = this.getResults() - ? localWidgets - : localWidgets.filter(isIndexWidget); + let widgetsToRender = + this.getResults() || derivedHelper?.lastRecommendResults + ? localWidgets + : localWidgets.filter(isIndexWidget); widgetsToRender = widgetsToRender.filter((widget) => { if (!widget.shouldRender) { diff --git a/packages/instantsearch.js/test/createInstantSearch.ts b/packages/instantsearch.js/test/createInstantSearch.ts index cfce007eb1..e7934d2442 100644 --- a/packages/instantsearch.js/test/createInstantSearch.ts +++ b/packages/instantsearch.js/test/createInstantSearch.ts @@ -44,6 +44,8 @@ export const createInstantSearch = ( _initialResults: null, _createURL: jest.fn(() => '#'), _insights: undefined, + _hasRecommendWidget: false, + _hasSearchWidget: false, onStateChange: null, setUiState: jest.fn(), getUiState: jest.fn(() => ({})), diff --git a/packages/react-instantsearch-core/src/connectors/__tests__/useRelatedProducts.test.tsx b/packages/react-instantsearch-core/src/connectors/__tests__/useRelatedProducts.test.tsx index c1c99245f9..9439da21e7 100644 --- a/packages/react-instantsearch-core/src/connectors/__tests__/useRelatedProducts.test.tsx +++ b/packages/react-instantsearch-core/src/connectors/__tests__/useRelatedProducts.test.tsx @@ -1,3 +1,4 @@ +import { createRecommendSearchClient } from '@instantsearch/mocks/fixtures'; import { createInstantSearchTestWrapper } from '@instantsearch/testutils'; import { renderHook } from '@testing-library/react-hooks'; @@ -5,7 +6,9 @@ import { useRelatedProducts } from '../useRelatedProducts'; describe('useRelatedProducts', () => { test('returns the connector render state', async () => { - const wrapper = createInstantSearchTestWrapper(); + const wrapper = createInstantSearchTestWrapper({ + searchClient: createRecommendSearchClient({ minimal: true }), + }); const { result, waitForNextUpdate } = renderHook( () => useRelatedProducts({ objectIDs: ['1'] }), { @@ -14,11 +17,13 @@ describe('useRelatedProducts', () => { ); // Initial render state from manual `getWidgetRenderState` - expect(result.current).toEqual({ items: expect.any(Array) }); + expect(result.current).toEqual({ items: [] }); await waitForNextUpdate(); // InstantSearch.js state from the `render` lifecycle step - expect(result.current).toEqual({ items: expect.any(Array) }); + expect(result.current).toEqual({ + items: expect.arrayContaining([{ objectID: '1' }, { objectID: '2' }]), + }); }); }); diff --git a/packages/react-instantsearch-core/src/connectors/__tests__/useTrendingItems.test.tsx b/packages/react-instantsearch-core/src/connectors/__tests__/useTrendingItems.test.tsx index 7061f121f8..7a53e1bcee 100644 --- a/packages/react-instantsearch-core/src/connectors/__tests__/useTrendingItems.test.tsx +++ b/packages/react-instantsearch-core/src/connectors/__tests__/useTrendingItems.test.tsx @@ -1,3 +1,4 @@ +import { createRecommendSearchClient } from '@instantsearch/mocks/fixtures'; import { createInstantSearchTestWrapper } from '@instantsearch/testutils'; import { renderHook } from '@testing-library/react-hooks'; @@ -5,7 +6,9 @@ import { useTrendingItems } from '../useTrendingItems'; describe('useTrendingItems', () => { test('returns the connector render state', async () => { - const wrapper = createInstantSearchTestWrapper(); + const wrapper = createInstantSearchTestWrapper({ + searchClient: createRecommendSearchClient({ minimal: true }), + }); const { result, waitForNextUpdate } = renderHook( () => useTrendingItems({}), { @@ -14,11 +17,13 @@ describe('useTrendingItems', () => { ); // Initial render state from manual `getWidgetRenderState` - expect(result.current).toEqual({ items: expect.any(Array) }); + expect(result.current).toEqual({ items: [] }); await waitForNextUpdate(); // InstantSearch.js state from the `render` lifecycle step - expect(result.current).toEqual({ items: expect.any(Array) }); + expect(result.current).toEqual({ + items: expect.arrayContaining([{ objectID: '1' }, { objectID: '2' }]), + }); }); }); diff --git a/packages/react-instantsearch/src/widgets/__tests__/FrequentlyBoughtTogether.test.tsx b/packages/react-instantsearch/src/widgets/__tests__/FrequentlyBoughtTogether.test.tsx index c8e348b064..ab7c4f1fbb 100644 --- a/packages/react-instantsearch/src/widgets/__tests__/FrequentlyBoughtTogether.test.tsx +++ b/packages/react-instantsearch/src/widgets/__tests__/FrequentlyBoughtTogether.test.tsx @@ -24,7 +24,7 @@ describe('FrequentlyBoughtTogether', () => { ); await waitFor(() => { - expect(client.search).toHaveBeenCalledTimes(1); + expect(client.getRecommendations).toHaveBeenCalledTimes(1); }); await waitFor(() => { diff --git a/packages/react-instantsearch/src/widgets/__tests__/LookingSimilar.test.tsx b/packages/react-instantsearch/src/widgets/__tests__/LookingSimilar.test.tsx index 53c250217b..69ed826d3d 100644 --- a/packages/react-instantsearch/src/widgets/__tests__/LookingSimilar.test.tsx +++ b/packages/react-instantsearch/src/widgets/__tests__/LookingSimilar.test.tsx @@ -21,7 +21,7 @@ describe('LookingSimilar', () => { ); await waitFor(() => { - expect(client.search).toHaveBeenCalledTimes(1); + expect(client.getRecommendations).toHaveBeenCalledTimes(1); }); await waitFor(() => { diff --git a/packages/react-instantsearch/src/widgets/__tests__/RelatedProducts.test.tsx b/packages/react-instantsearch/src/widgets/__tests__/RelatedProducts.test.tsx index 1ce09af18b..5985893861 100644 --- a/packages/react-instantsearch/src/widgets/__tests__/RelatedProducts.test.tsx +++ b/packages/react-instantsearch/src/widgets/__tests__/RelatedProducts.test.tsx @@ -24,7 +24,7 @@ describe('RelatedProducts', () => { ); await waitFor(() => { - expect(client.search).toHaveBeenCalledTimes(1); + expect(client.getRecommendations).toHaveBeenCalledTimes(1); }); await waitFor(() => { diff --git a/packages/react-instantsearch/src/widgets/__tests__/TrendingItems.test.tsx b/packages/react-instantsearch/src/widgets/__tests__/TrendingItems.test.tsx index a16dffb921..b101ec024a 100644 --- a/packages/react-instantsearch/src/widgets/__tests__/TrendingItems.test.tsx +++ b/packages/react-instantsearch/src/widgets/__tests__/TrendingItems.test.tsx @@ -21,7 +21,7 @@ describe('TrendingItems', () => { ); await waitFor(() => { - expect(client.search).toHaveBeenCalledTimes(1); + expect(client.getRecommendations).toHaveBeenCalledTimes(1); }); await waitFor(() => {