Skip to content

Commit

Permalink
refactor(instantsearch): replace "helper" with the value of "mainHelp…
Browse files Browse the repository at this point in the history
…er" (#6516)

* refactor(instantsearch): remove "helper" in favor of "mainHelper"

[FX-3212]

* refactor(instantsearch): rename "mainHelper" to "helper"

[FX-3212]


BREAKING CHANGE: the value search.helper is what used to be search.mainHelper. search.mainHelper no longer exists. Use either search.helper now or search.mainIndex.getHelper()
  • Loading branch information
Haroenv committed Jan 9, 2025
1 parent 503a357 commit 7da7ed5
Show file tree
Hide file tree
Showing 20 changed files with 136 additions and 154 deletions.
60 changes: 28 additions & 32 deletions packages/instantsearch-core/src/__tests__/instantsearch.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ search.addWidgets([
See https://www.algolia.com/doc/api-reference/widgets/configure/js/`);
});

it("exposes helper's last results", async () => {
it("helper's results are null", async () => {
const searchClient = createSearchClient();

const search = new InstantSearch({
Expand All @@ -394,8 +394,7 @@ See https://www.algolia.com/doc/api-reference/widgets/configure/js/`);

await wait(0);

// could be null if we don't pretend the main helper is the one who searched
expect(search.helper!.lastResults).not.toBe(null);
expect(search.helper!.lastResults).toBe(null);
});

describe('insights middleware', () => {
Expand Down Expand Up @@ -822,9 +821,9 @@ describe('start', () => {

await wait(0);

expect(
search.mainHelper!.searchOnlyWithDerivedHelpers
).toHaveBeenCalledTimes(1);
expect(search.helper!.searchOnlyWithDerivedHelpers).toHaveBeenCalledTimes(
1
);
});

it('forwards the `initialUiState` to the main index', () => {
Expand Down Expand Up @@ -1004,7 +1003,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsear
`);
});

it('keeps a mainHelper already set on the instance (Vue SSR)', () => {
it('keeps a helper already set on the instance (Vue SSR)', () => {
const searchClient = createSearchClient();
const instance = new InstantSearch({
indexName: 'indexName',
Expand All @@ -1013,17 +1012,17 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsear

const helper = algoliasearchHelper(searchClient, '');

// explicitly setting the mainHelper before start is used to force render to
// explicitly setting the helper before start is used to force render to
// happen before the results of the first search are done. We need to make
// sure no extra helper is created, as that can cause certain things (like routing)
// to be listening to the wrong helper.
instance.mainHelper = helper;
instance.helper = helper;

expect(instance.mainHelper).toBe(helper);
expect(instance.helper).toBe(helper);

instance.start();

expect(instance.mainHelper).toBe(helper);
expect(instance.helper).toBe(helper);
});

it('no query for root if indexName is not given', async () => {
Expand Down Expand Up @@ -1122,7 +1121,7 @@ describe('dispose', () => {
await wait(0);

// Simulate a search
search.mainHelper!.search();
search.helper!.search();

search.dispose();

Expand Down Expand Up @@ -1195,17 +1194,17 @@ describe('dispose', () => {

search.start();

const mainHelper = search.mainHelper!;
const helper = search.helper!;

mainHelper.on('searchQueueEmpty', onEventName);
helper.on('searchQueueEmpty', onEventName);

mainHelper.emit('searchQueueEmpty');
helper.emit('searchQueueEmpty');

expect(onEventName).toHaveBeenCalledTimes(1);

search.dispose();

mainHelper.emit('searchQueueEmpty');
helper.emit('searchQueueEmpty');

expect(onEventName).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -1240,25 +1239,22 @@ describe('dispose', () => {
expect(onRender).toHaveBeenCalledTimes(2);
});

it('removes the Helpers references', () => {
it('removes the helper references', () => {
const search = new InstantSearch({
indexName: 'indexName',
searchClient: createSearchClient(),
});

search.start();

expect(search.mainHelper).not.toBe(null);
expect(search.helper).not.toBe(null);

search.dispose();

expect(search.mainHelper).toBe(null);
expect(search.helper).toBe(null);

search.start();

expect(search.mainHelper).not.toBe(null);
expect(search.helper).not.toBe(null);
});

Expand All @@ -1283,15 +1279,15 @@ describe('scheduleSearch', () => {

search.start();

const mainHelperSearch = jest.spyOn(search.mainHelper!, 'search');
const helperSearch = jest.spyOn(search.helper!, 'search');

search.scheduleSearch();

expect(mainHelperSearch).toHaveBeenCalledTimes(0);
expect(helperSearch).toHaveBeenCalledTimes(0);

await wait(0);

expect(mainHelperSearch).toHaveBeenCalledTimes(1);
expect(helperSearch).toHaveBeenCalledTimes(1);
});

it('deduplicates the calls to the `search` method', async () => {
Expand All @@ -1304,18 +1300,18 @@ describe('scheduleSearch', () => {

search.start();

const mainHelperSearch = jest.spyOn(search.mainHelper!, 'search');
const helperSearch = jest.spyOn(search.helper!, 'search');

search.scheduleSearch();
search.scheduleSearch();
search.scheduleSearch();
search.scheduleSearch();

expect(mainHelperSearch).toHaveBeenCalledTimes(0);
expect(helperSearch).toHaveBeenCalledTimes(0);

await wait(0);

expect(mainHelperSearch).toHaveBeenCalledTimes(1);
expect(helperSearch).toHaveBeenCalledTimes(1);
});
});

Expand Down Expand Up @@ -1418,7 +1414,7 @@ describe('scheduleStalledRender', () => {
castToJestMock(widget.render!).mockReset();

// Trigger a new search
search.mainHelper!.search();
search.helper!.search();

// search starts
await wait(0);
Expand Down Expand Up @@ -1456,10 +1452,10 @@ describe('scheduleStalledRender', () => {
castToJestMock(widget.render!).mockClear();

// Trigger multiple searches
search.mainHelper!.search();
search.mainHelper!.search();
search.mainHelper!.search();
search.mainHelper!.search();
search.helper!.search();
search.helper!.search();
search.helper!.search();
search.helper!.search();

await wait(0);

Expand Down Expand Up @@ -1507,7 +1503,7 @@ describe('scheduleStalledRender', () => {
);

// Trigger a new search
search.mainHelper!.search();
search.helper!.search();

expect(widget.render).toHaveBeenCalledTimes(1);
castToJestMock(widget.render!).mockClear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('connectGeoSearch', () => {
const widget = customGeoSearch({});

const instantSearchInstance = createInstantSearch();
const helper = instantSearchInstance.mainHelper!;
const helper = instantSearchInstance.helper!;

widget.init!(
createInitOptions({
Expand Down Expand Up @@ -160,7 +160,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/geo-search/
const widget = customGeoSearch({});

const instantSearchInstance = createInstantSearch();
const { mainHelper: helper } = instantSearchInstance;
const { helper } = instantSearchInstance;

widget.init!(createInitOptions({ instantSearchInstance }));

Expand Down
41 changes: 17 additions & 24 deletions packages/instantsearch-core/src/instantsearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ export class InstantSearch<
onStateChange: InstantSearchOptions<TUiState>['onStateChange'] | null = null;
future: NonNullable<InstantSearchOptions<TUiState>['future']>;
helper: AlgoliaSearchHelper | null;
mainHelper: AlgoliaSearchHelper | null;
mainIndex: IndexWidget;
started: boolean;
renderState: RenderState = {};
Expand All @@ -74,7 +73,7 @@ export class InstantSearch<
_initialUiState: TUiState;
_initialResults: InitialResults | null;
_createURL: CreateURL<TUiState>;
_mainHelperSearch?: AlgoliaSearchHelper['search'];
_helperSearch?: AlgoliaSearchHelper['search'];
_hasSearchWidget: boolean = false;
_hasRecommendWidget: boolean = false;
_insights: InstantSearchOptions['insights'];
Expand Down Expand Up @@ -150,7 +149,6 @@ See ${createDocumentationLink({
this.future = future;
this.indexName = indexName;
this.helper = null;
this.mainHelper = null;
this.mainIndex = index({
indexName,
});
Expand Down Expand Up @@ -296,11 +294,11 @@ See ${createDocumentationLink({
// DerivedHelper scoped into the `index` widgets.
// In Vue InstantSearch' hydrate, a main helper gets set before start, so
// we need to respect this helper as a way to keep all listeners correct.
const mainHelper =
this.mainHelper ||
const helper =
this.helper ||
algoliasearchHelper(this.client, this.indexName, undefined);

mainHelper.search = () => {
helper.search = () => {
this.status = 'loading';
this.scheduleRender(false);

Expand All @@ -315,19 +313,19 @@ See ${createDocumentationLink({
// completely transparent for the rest of the codebase. Only this module
// is impacted.
if (this._hasSearchWidget) {
mainHelper.searchOnlyWithDerivedHelpers();
helper.searchOnlyWithDerivedHelpers();
}

if (this._hasRecommendWidget) {
mainHelper.recommend();
helper.recommend();
}

return mainHelper;
return helper;
};

// Only the "main" Helper emits the `error` event vs the one for `search`
// and `results` that are also emitted on the derived one.
mainHelper.on('error', (error) => {
helper.on('error', (error) => {
if (!(error instanceof Error)) {
// typescript lies here, error is in some cases { name: string, message: string }
const err = error as Record<string, any>;
Expand All @@ -345,7 +343,7 @@ See ${createDocumentationLink({
this.emit('error', this.error);
});

this.mainHelper = mainHelper;
this.helper = helper;

this.middleware.forEach(({ instance }) => {
instance.subscribe();
Expand All @@ -359,7 +357,7 @@ See ${createDocumentationLink({

if (this._initialResults) {
hydrateSearchClient(this.client, this._initialResults);
hydrateRecommendCache(this.mainHelper, this._initialResults);
hydrateRecommendCache(this.helper, this._initialResults);

const originalScheduleSearch = this.scheduleSearch;
// We don't schedule a first search when initial results are provided
Expand Down Expand Up @@ -387,10 +385,6 @@ See ${createDocumentationLink({
this.scheduleSearch();
}

// Keep the previous reference for legacy purpose, some pattern use
// the direct Helper access `search.helper` (e.g multi-index).
this.helper = this.mainIndex.getHelper();

// track we started the search if we add more widgets,
// to init them directly after add
this.started = true;
Expand All @@ -403,7 +397,7 @@ See ${createDocumentationLink({
// added when `insights` is unset and the initial results possess `queryID`.
// Any user-provided middleware will be added later and override this one.
if (typeof this._insights === 'undefined') {
mainHelper.derivedHelpers[0].once('result', () => {
helper.derivedHelpers[0].once('result', () => {
const hasAutomaticInsights = this.mainIndex
.getScopedResults()
.some(({ results }) => results?._automaticInsights);
Expand Down Expand Up @@ -435,8 +429,7 @@ See ${createDocumentationLink({
// The helper needs to be reset to perform the next search from a fresh state.
// If not reset, it would use the state stored before calling `dispose()`.
this.removeAllListeners();
this.mainHelper?.removeAllListeners();
this.mainHelper = null;
this.helper?.removeAllListeners();
this.helper = null;

this.middleware.forEach(({ instance }) => {
Expand All @@ -446,12 +439,12 @@ See ${createDocumentationLink({

scheduleSearch = defer(() => {
if (this.started) {
this.mainHelper!.search();
this.helper!.search();
}
});

scheduleRender = defer((shouldResetStatus: boolean = true) => {
if (!this.mainHelper?.hasPendingRequests()) {
if (!this.helper?.hasPendingRequests()) {
clearTimeout(this._searchStalledTimer);
this._searchStalledTimer = null;

Expand Down Expand Up @@ -481,7 +474,7 @@ See ${createDocumentationLink({
uiState: TUiState | ((previousUiState: TUiState) => TUiState),
callOnStateChange = true
) {
if (!this.mainHelper) {
if (!this.helper) {
throw new Error(
withUsage('The `start` method needs to be called before `setUiState`.')
);
Expand Down Expand Up @@ -548,13 +541,13 @@ See ${createDocumentationLink({
}

refresh() {
if (!this.mainHelper) {
if (!this.helper) {
throw new Error(
withUsage('The `start` method needs to be called before `refresh`.')
);
}

this.mainHelper.clearCache().search();
this.helper.clearCache().search();
}
}

Expand Down
Loading

0 comments on commit 7da7ed5

Please sign in to comment.