Skip to content

Commit

Permalink
feat(breadcrumb): implement getWidgetRenderState (#4467)
Browse files Browse the repository at this point in the history
  • Loading branch information
francoischalifour authored and Haroenv committed Nov 30, 2020
1 parent ac4182e commit 9d40364
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 42 deletions.
112 changes: 94 additions & 18 deletions src/connectors/breadcrumb/__tests__/connectBreadcrumb-test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import jsHelper, {
import algoliasearchHelper, {
SearchResults,
SearchParameters,
} from 'algoliasearch-helper';
Expand Down Expand Up @@ -67,6 +67,82 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
);
});

describe('getWidgetRenderState', () => {
test('returns the render state', () => {
const renderFn = jest.fn();
const unmountFn = jest.fn();
const createBreadcrumb = connectBreadcrumb(renderFn, unmountFn);
const breadcrumb = createBreadcrumb({
attributes: ['category', 'subCategory'],
});
const helper = algoliasearchHelper(createSearchClient(), 'indexName', {
index: 'indexName',
hierarchicalFacets: [
{
name: 'category',
attributes: ['category', 'subCategory'],
separator: ' > ',
},
],
});

helper.toggleRefinement('category', 'Decoration');

const renderState1 = breadcrumb.getWidgetRenderState!(
{},
createInitOptions({ helper })
);

expect(renderState1.breadcrumb).toEqual({
canRefine: false,
createURL: undefined,
items: [],
refine: undefined,
widgetParams: { attributes: ['category', 'subCategory'] },
});

breadcrumb.init!(createInitOptions({ helper }));

const renderState2 = breadcrumb.getWidgetRenderState!(
{},
createRenderOptions({
helper,
state: helper.state,
results: new SearchResults(helper.state, [
createSingleSearchResponse({
hits: [],
facets: {
category: {
Decoration: 880,
},
subCategory: {
'Decoration > Candle holders & candles': 193,
'Decoration > Frames & pictures': 173,
},
},
}),
createSingleSearchResponse({
facets: {
category: {
Decoration: 880,
Outdoor: 47,
},
},
}),
]),
})
);

expect(renderState2.breadcrumb).toEqual({
canRefine: true,
createURL: expect.any(Function),
items: [{ label: 'Decoration', value: null }],
refine: expect.any(Function),
widgetParams: { attributes: ['category', 'subCategory'] },
});
});
});

describe('getWidgetSearchParameters', () => {
beforeEach(() => {
warning.cache = {};
Expand All @@ -75,7 +151,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
it('returns the `SearchParameters` with default value', () => {
const render = () => {};
const makeWidget = connectBreadcrumb(render);
const helper = jsHelper(createSearchClient(), '');
const helper = algoliasearchHelper(createSearchClient(), '');
const widget = makeWidget({
attributes: ['category', 'sub_category'],
});
Expand All @@ -97,7 +173,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
it('returns the `SearchParameters` with default a custom `separator`', () => {
const render = () => {};
const makeWidget = connectBreadcrumb(render);
const helper = jsHelper(createSearchClient(), '');
const helper = algoliasearchHelper(createSearchClient(), '');
const widget = makeWidget({
attributes: ['category', 'sub_category'],
separator: ' / ',
Expand All @@ -120,7 +196,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
it('returns the `SearchParameters` with default a custom `rootPath`', () => {
const render = () => {};
const makeWidget = connectBreadcrumb(render);
const helper = jsHelper(createSearchClient(), '');
const helper = algoliasearchHelper(createSearchClient(), '');
const widget = makeWidget({
attributes: ['category', 'sub_category'],
rootPath: 'TopLevel > SubLevel',
Expand All @@ -143,7 +219,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
it('returns the `SearchParameters` with another `hierarchicalFacets` already defined', () => {
const render = () => {};
const makeWidget = connectBreadcrumb(render);
const helper = jsHelper(createSearchClient(), '', {
const helper = algoliasearchHelper(createSearchClient(), '', {
hierarchicalFacets: [
{
name: 'country',
Expand Down Expand Up @@ -179,7 +255,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
it('returns the `SearchParameters` with the same `hierarchicalFacets` already defined', () => {
const render = () => {};
const makeWidget = connectBreadcrumb(render);
const helper = jsHelper(createSearchClient(), '', {
const helper = algoliasearchHelper(createSearchClient(), '', {
hierarchicalFacets: [
{
name: 'category',
Expand Down Expand Up @@ -213,7 +289,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
it('warns with the same `hierarchicalFacets` already defined with different `attributes`', () => {
const render = () => {};
const makeWidget = connectBreadcrumb(render);
const helper = jsHelper(createSearchClient(), '', {
const helper = algoliasearchHelper(createSearchClient(), '', {
hierarchicalFacets: [
{
name: 'category',
Expand All @@ -239,7 +315,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
it('warns with the same `hierarchicalFacets` already defined with different `separator`', () => {
const render = () => {};
const makeWidget = connectBreadcrumb(render);
const helper = jsHelper(createSearchClient(), '', {
const helper = algoliasearchHelper(createSearchClient(), '', {
hierarchicalFacets: [
{
name: 'category',
Expand All @@ -266,7 +342,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
it('warns with the same `hierarchicalFacets` already defined with different `rootPath`', () => {
const render = () => {};
const makeWidget = connectBreadcrumb(render);
const helper = jsHelper(createSearchClient(), '', {
const helper = algoliasearchHelper(createSearchClient(), '', {
hierarchicalFacets: [
{
name: 'category',
Expand Down Expand Up @@ -316,7 +392,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
// Verify that the widget has not been rendered yet at this point
expect(rendering.mock.calls).toHaveLength(0);

const helper = jsHelper(createSearchClient(), '', config);
const helper = algoliasearchHelper(createSearchClient(), '', config);
helper.search = jest.fn();

widget.init!(
Expand Down Expand Up @@ -379,7 +455,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
const config = widget.getWidgetSearchParameters!(new SearchParameters(), {
uiState: {},
});
const helper = jsHelper(createSearchClient(), '', config);
const helper = algoliasearchHelper(createSearchClient(), '', config);
helper.search = jest.fn();

helper.toggleRefinement('category', 'Decoration');
Expand Down Expand Up @@ -439,7 +515,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
const config = widget.getWidgetSearchParameters!(new SearchParameters({}), {
uiState: {},
});
const helper = jsHelper(createSearchClient(), '', config);
const helper = algoliasearchHelper(createSearchClient(), '', config);

helper.search = jest.fn();

Expand Down Expand Up @@ -488,7 +564,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
const config = widget.getWidgetSearchParameters!(new SearchParameters(), {
uiState: {},
});
const helper = jsHelper(createSearchClient(), '', config);
const helper = algoliasearchHelper(createSearchClient(), '', config);
helper.search = jest.fn();

helper.toggleRefinement('category', 'Decoration');
Expand Down Expand Up @@ -546,7 +622,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
const config = widget.getWidgetSearchParameters!(new SearchParameters(), {
uiState: {},
});
const helper = jsHelper(createSearchClient(), '', config);
const helper = algoliasearchHelper(createSearchClient(), '', config);
helper.search = jest.fn();

widget.init!(
Expand Down Expand Up @@ -613,7 +689,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
const config = widget.getWidgetSearchParameters!(new SearchParameters(), {
uiState: {},
});
const helper = jsHelper(createSearchClient(), '', config);
const helper = algoliasearchHelper(createSearchClient(), '', config);
helper.search = jest.fn();

widget.init!(
Expand Down Expand Up @@ -779,7 +855,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
const config = widget.getWidgetSearchParameters!(new SearchParameters(), {
uiState: {},
});
const helper = jsHelper(createSearchClient(), '', config);
const helper = algoliasearchHelper(createSearchClient(), '', config);
helper.search = jest.fn();

widget.init!(
Expand Down Expand Up @@ -832,7 +908,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/

describe('dispose', () => {
it('does not throw without the unmount function', () => {
const helper = jsHelper(createSearchClient(), '');
const helper = algoliasearchHelper(createSearchClient(), '');

const renderFn = () => {};
const makeWidget = connectBreadcrumb(renderFn);
Expand All @@ -848,7 +924,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/breadcrumb/
const makeWidget = connectBreadcrumb(renderFn);
const widget = makeWidget({ attributes: ['category'] });

const helper = jsHelper(createSearchClient(), '', {
const helper = algoliasearchHelper(createSearchClient(), '', {
hierarchicalFacetsRefinements: {
category: ['boxes'],
},
Expand Down
67 changes: 44 additions & 23 deletions src/connectors/breadcrumb/connectBreadcrumb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ const connectBreadcrumb: BreadcrumbConnector = function connectBreadcrumb(
return {
$$type: 'ais.breadcrumb',

init({ createURL, helper, instantSearchInstance }) {
init(initOptions) {
const { helper, createURL } = initOptions;

connectorState.createURL = facetValue => {
if (!facetValue) {
const breadcrumb = helper.getHierarchicalFacetBreadcrumb(
Expand Down Expand Up @@ -148,35 +150,22 @@ const connectBreadcrumb: BreadcrumbConnector = function connectBreadcrumb(

renderFn(
{
createURL: connectorState.createURL,
canRefine: false,
instantSearchInstance,
items: [],
refine: connectorState.refine,
widgetParams,
...this.getWidgetRenderState!(initOptions.renderState, initOptions)
.breadcrumb!,
instantSearchInstance: initOptions.instantSearchInstance,
},
true
);
},

render({ instantSearchInstance, results, state }) {
const [{ name: facetName }] = state.hierarchicalFacets;

const facetValues = results.getFacetValues(
facetName,
{}
) as SearchResults.HierarchicalFacet;
const data = Array.isArray(facetValues.data) ? facetValues.data : [];
const items = transformItems(shiftItemsValues(prepareItems(data)));

render(renderOptions) {
renderFn(
{
canRefine: items.length > 0,
createURL: connectorState.createURL,
instantSearchInstance,
items,
refine: connectorState.refine,
widgetParams,
...this.getWidgetRenderState!(
renderOptions.renderState,
renderOptions
).breadcrumb!,
instantSearchInstance: renderOptions.instantSearchInstance,
},
false
);
Expand All @@ -186,6 +175,38 @@ const connectBreadcrumb: BreadcrumbConnector = function connectBreadcrumb(
unmountFn();
},

getWidgetRenderState(renderState, { results, state }) {
function getItems() {
if (!results) {
return [];
}

const [{ name: facetName }] = state.hierarchicalFacets;

const facetValues = results.getFacetValues(
facetName,
{}
) as SearchResults.HierarchicalFacet;
const data = Array.isArray(facetValues.data) ? facetValues.data : [];
const items = transformItems(shiftItemsValues(prepareItems(data)));

return items;
}

const items = getItems();

return {
...renderState,
breadcrumb: {
canRefine: items.length > 0,
createURL: connectorState.createURL,
items,
refine: connectorState.refine,
widgetParams,
},
};
},

getWidgetSearchParameters(searchParameters) {
if (searchParameters.isHierarchicalFacet(hierarchicalFacetName)) {
const facet = searchParameters.getHierarchicalFacetByName(
Expand Down
12 changes: 11 additions & 1 deletion src/types/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import {
AutocompleteRendererOptions,
AutocompleteConnectorParams,
} from '../connectors/autocomplete/connectAutocomplete';
import {
BreadcrumbRendererOptions,
BreadcrumbConnectorParams,
} from '../connectors/breadcrumb/connectBreadcrumb';

export type ScopedResult = {
indexId: string;
Expand All @@ -34,6 +38,7 @@ type SharedRenderOptions = {

export type InitOptions = SharedRenderOptions & {
uiState: UiState;
results?: undefined;
};

export type RenderOptions = SharedRenderOptions & {
Expand Down Expand Up @@ -143,13 +148,18 @@ export type IndexRenderState = Partial<{
AutocompleteRendererOptions,
AutocompleteConnectorParams
>;
breadcrumb: WidgetRenderState<
BreadcrumbRendererOptions,
BreadcrumbConnectorParams
>;
}>;

type WidgetRenderState<
TWidgetRenderState,
// @ts-ignore
TWidgetParams
> = TWidgetRenderState & {
widgetParams: TWidgetParams;
widgetParams: any; // @TODO type as TWidgetParams
};

/**
Expand Down

0 comments on commit 9d40364

Please sign in to comment.