Skip to content

Commit

Permalink
feat(hits): implement getWidgetRenderState (#4525)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yannick Croissant authored and Haroenv committed Nov 30, 2020
1 parent a4604a2 commit 0f8dbd3
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/connectors/autocomplete/connectAutocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ search.addWidgets([
};
},

getWidgetRenderState({ helper, scopedResults }) {
getWidgetRenderState({ helper, scopedResults, instantSearchInstance }) {
const indices = scopedResults.map(scopedResult => {
// We need to escape the hits because highlighting
// exposes HTML tags to the end-user.
Expand Down
118 changes: 118 additions & 0 deletions src/connectors/hits/__tests__/connectHits-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,124 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hits/js/#co
expect(((results.hits as unknown) as EscapedHits).__escaped).toBe(true);
});

describe('getRenderState', () => {
it('returns the render state', () => {
const renderFn = jest.fn();
const unmountFn = jest.fn();
const createHits = connectHits(renderFn, unmountFn);
const hitsWidget = createHits({});
const helper = algoliasearchHelper(createSearchClient(), 'indexName', {
index: 'indexName',
});

const renderState1 = hitsWidget.getRenderState(
{},
createInitOptions({ state: helper.state, helper })
);

expect(renderState1.hits).toEqual({
hits: [],
results: undefined,
sendEvent: expect.any(Function),
bindEvent: expect.any(Function),
widgetParams: {},
});

const hits = [
{ objectID: '1', name: 'name 1' },
{ objectID: '2', name: 'name 2' },
];

const results = new SearchResults(helper.state, [
createSingleSearchResponse({ hits, queryID: 'theQueryID' }),
]);

const renderState2 = hitsWidget.getRenderState(
{},
createRenderOptions({
helper,
state: helper.state,
results,
})
);

const expectedHits = [
{ objectID: '1', name: 'name 1', __queryID: 'theQueryID' },
{ objectID: '2', name: 'name 2', __queryID: 'theQueryID' },
];

((expectedHits as unknown) as EscapedHits).__escaped = true;

expect(renderState2.hits).toEqual(
expect.objectContaining({
hits: expectedHits,
results,
sendEvent: expect.any(Function),
bindEvent: expect.any(Function),
widgetParams: {},
})
);
});
});

describe('getWidgetRenderState', () => {
it('returns the widget render state', () => {
const renderFn = jest.fn();
const unmountFn = jest.fn();
const createHits = connectHits(renderFn, unmountFn);
const hitsWidget = createHits({});
const helper = algoliasearchHelper(createSearchClient(), 'indexName', {
index: 'indexName',
});

const renderState1 = hitsWidget.getWidgetRenderState(
createInitOptions({ state: helper.state, helper })
);

expect(renderState1).toEqual({
hits: [],
results: undefined,
sendEvent: expect.any(Function),
bindEvent: expect.any(Function),
widgetParams: {},
});

const hits = [
{ objectID: '1', name: 'name 1' },
{ objectID: '2', name: 'name 2' },
];

const results = new SearchResults(helper.state, [
createSingleSearchResponse({ hits, queryID: 'theQueryID' }),
]);

const renderState2 = hitsWidget.getWidgetRenderState(
createRenderOptions({
helper,
state: helper.state,
results,
})
);

const expectedHits = [
{ objectID: '1', name: 'name 1', __queryID: 'theQueryID' },
{ objectID: '2', name: 'name 2', __queryID: 'theQueryID' },
];

((expectedHits as unknown) as EscapedHits).__escaped = true;

expect(renderState2).toEqual(
expect.objectContaining({
hits: expectedHits,
results,
sendEvent: expect.any(Function),
bindEvent: expect.any(Function),
widgetParams: {},
})
);
});
});

describe('getWidgetSearchParameters', () => {
it('adds the TAG_PLACEHOLDER to the `SearchParameters`', () => {
const render = () => {};
Expand Down
83 changes: 54 additions & 29 deletions src/connectors/hits/connectHits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,31 +71,62 @@ const connectHits: HitsConnector = function connectHits(
return {
$$type: 'ais.hits',

init({ instantSearchInstance, helper }) {
sendEvent = createSendEventForHits({
instantSearchInstance,
index: helper.getIndex(),
widgetType: this.$$type!,
});
bindEvent = createBindEventForHits({
index: helper.getIndex(),
widgetType: this.$$type!,
});
init(initOptions) {
renderFn(
{
...this.getWidgetRenderState(initOptions),
instantSearchInstance: initOptions.instantSearchInstance,
},
true
);
},

render(renderOptions) {
const renderState = this.getWidgetRenderState(renderOptions);
renderState.sendEvent('view', renderState.hits);

renderFn(
{
...renderState,
instantSearchInstance: renderOptions.instantSearchInstance,
},
false
);
},

getRenderState(renderState, renderOptions) {
return {
...renderState,
hits: this.getWidgetRenderState(renderOptions),
};
},

getWidgetRenderState({ results, helper, instantSearchInstance }) {
if (!sendEvent) {
sendEvent = createSendEventForHits({
instantSearchInstance,
index: helper.getIndex(),
widgetType: this.$$type!,
});
}

if (!bindEvent) {
bindEvent = createBindEventForHits({
index: helper.getIndex(),
widgetType: this.$$type!,
});
}

if (!results) {
return {
hits: [],
results: undefined,
sendEvent,
bindEvent,
instantSearchInstance,
widgetParams,
},
true
);
},
};
}

render({ results, instantSearchInstance }) {
if (escapeHTML && results.hits.length > 0) {
results.hits = escapeHits(results.hits);
}
Expand All @@ -120,19 +151,13 @@ const connectHits: HitsConnector = function connectHits(
typeof escapeHits
>).__escaped = initialEscaped;

sendEvent('view', results.hits);

renderFn(
{
hits: results.hits,
results,
sendEvent,
bindEvent,
instantSearchInstance,
widgetParams,
},
false
);
return {
hits: results.hits,
results,
sendEvent,
bindEvent,
widgetParams,
};
},

dispose({ state }) {
Expand Down
5 changes: 5 additions & 0 deletions src/types/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import {
CurrentRefinementsRendererOptions,
CurrentRefinementsConnectorParams,
} from '../connectors/current-refinements/connectCurrentRefinements';
import {
HitsRendererOptions,
HitsConnectorParams,
} from '../connectors/hits/connectHits';

export type ScopedResult = {
indexId: string;
Expand Down Expand Up @@ -201,6 +205,7 @@ export type IndexRenderState = Partial<{
}
>;
};
hits: WidgetRenderState<HitsRendererOptions, HitsConnectorParams>;
}>;

type WidgetRenderState<
Expand Down

0 comments on commit 0f8dbd3

Please sign in to comment.