Skip to content

Commit

Permalink
feat(helper): persistHierarchicalRootCount: true
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the default behaviour of the helper is now persistHierarchicalRootCount: true
  • Loading branch information
Haroenv committed Dec 18, 2024
1 parent 1778a8a commit 34cca9a
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 108 deletions.
2 changes: 1 addition & 1 deletion packages/algoliasearch-helper/src/SearchResults/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ function SearchResults(state, results, options) {

// Make every key of the result options reachable from the instance
var opts = defaultsPure(options, {
persistHierarchicalRootCount: false,
persistHierarchicalRootCount: true,
});
Object.keys(opts).forEach(function (key) {
self[key] = opts[key];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ function getData() {
index: 'test_hotels-node',
hitsPerPage: 20,
nbHits: 4,
persistHierarchicalRootCount: false,
persistHierarchicalRootCount: true,
nbPages: 1,
page: 0,
params:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
var algoliasearchHelper = require('../../../index');
var SearchParameters = require('../../../src/SearchParameters');

test('searchOnce should call the algolia client according to the number of refinements and call callback with no error and with results when no error', function (done) {
test('searchOnce should call the algolia client according to the number of refinements and call callback with no error and with results when no error', async function () {
var testData = require('../../datasets/SearchParameters/search.dataset')();

var client = {
Expand All @@ -21,76 +21,72 @@ test('searchOnce should call the algolia client according to the number of refin
.addDisjunctiveFacetRefinement('city', 'Paris')
.addDisjunctiveFacetRefinement('city', 'New York');

helper.searchOnce(parameters, function (err, data) {
expect(err).toBe(null);

// shame deepclone, to remove any associated methods coming from the results
expect(JSON.parse(JSON.stringify(data))).toEqual(
JSON.parse(JSON.stringify(testData.responseHelper))
);

var cityValues = data.getFacetValues('city');
var expectedCityValues = [
{ name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true },
{ name: 'New York', escapedValue: 'New York', count: 1, isRefined: true },
{
name: 'San Francisco',
escapedValue: 'San Francisco',
count: 1,
isRefined: false,
},
];

expect(cityValues).toEqual(expectedCityValues);

var cityValuesCustom = data.getFacetValues('city', {
sortBy: ['count:asc', 'name:asc'],
});
var expectedCityValuesCustom = [
{ name: 'New York', escapedValue: 'New York', count: 1, isRefined: true },
{
name: 'San Francisco',
escapedValue: 'San Francisco',
count: 1,
isRefined: false,
},
{ name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true },
];

expect(cityValuesCustom).toEqual(expectedCityValuesCustom);

var cityValuesFn = data.getFacetValues('city', {
sortBy: function (a, b) {
return a.count - b.count;
},
});
var expectedCityValuesFn = [
{ name: 'New York', escapedValue: 'New York', count: 1, isRefined: true },
{
name: 'San Francisco',
escapedValue: 'San Francisco',
count: 1,
isRefined: false,
},
{ name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true },
];

expect(cityValuesFn).toEqual(expectedCityValuesFn);

expect(client.search).toHaveBeenCalledTimes(1);

var queries = client.search.mock.calls[0][0];
for (var i = 0; i < queries.length; i++) {
var query = queries[i];
expect(query.query).toBeUndefined();
expect(query.params.query).toBeUndefined();
}

done();
const { content } = await helper.searchOnce(parameters);

// shame deepclone, to remove any associated methods coming from the results
expect(JSON.parse(JSON.stringify(content))).toEqual(
JSON.parse(JSON.stringify(testData.responseHelper))
);

var cityValues = content.getFacetValues('city');
var expectedCityValues = [
{ name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true },
{ name: 'New York', escapedValue: 'New York', count: 1, isRefined: true },
{
name: 'San Francisco',
escapedValue: 'San Francisco',
count: 1,
isRefined: false,
},
];

expect(cityValues).toEqual(expectedCityValues);

var cityValuesCustom = content.getFacetValues('city', {
sortBy: ['count:asc', 'name:asc'],
});
var expectedCityValuesCustom = [
{ name: 'New York', escapedValue: 'New York', count: 1, isRefined: true },
{
name: 'San Francisco',
escapedValue: 'San Francisco',
count: 1,
isRefined: false,
},
{ name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true },
];

expect(cityValuesCustom).toEqual(expectedCityValuesCustom);

var cityValuesFn = content.getFacetValues('city', {
sortBy: function (a, b) {
return a.count - b.count;
},
});
var expectedCityValuesFn = [
{ name: 'New York', escapedValue: 'New York', count: 1, isRefined: true },
{
name: 'San Francisco',
escapedValue: 'San Francisco',
count: 1,
isRefined: false,
},
{ name: 'Paris', escapedValue: 'Paris', count: 3, isRefined: true },
];

expect(cityValuesFn).toEqual(expectedCityValuesFn);

expect(client.search).toHaveBeenCalledTimes(1);

var queries = client.search.mock.calls[0][0];
for (var i = 0; i < queries.length; i++) {
var query = queries[i];
expect(query.query).toBeUndefined();
expect(query.params.query).toBeUndefined();
}
});

test('searchOnce should call the algolia client according to the number of refinements and call callback with error and no results when error', function (done) {
test('searchOnce should call the algolia client according to the number of refinements and call callback with error and no results when error', async function () {
var error = { message: 'error' };
var client = {
search: jest.fn().mockImplementationOnce(function () {
Expand All @@ -107,19 +103,14 @@ test('searchOnce should call the algolia client according to the number of refin
.addDisjunctiveFacetRefinement('city', 'Paris')
.addDisjunctiveFacetRefinement('city', 'New York');

helper.searchOnce(parameters, function (err, data) {
expect(err).toBe(error);
expect(data).toBe(null);

expect(client.search).toHaveBeenCalledTimes(1);
await expect(() => helper.searchOnce(parameters)).rejects.toEqual(error);

var queries = client.search.mock.calls[0][0];
for (var i = 0; i < queries.length; i++) {
var query = queries[i];
expect(query.query).toBeUndefined();
expect(query.params.query).toBeUndefined();
}
expect(client.search).toHaveBeenCalledTimes(1);

done();
});
var queries = client.search.mock.calls[0][0];
for (var i = 0; i < queries.length; i++) {
var query = queries[i];
expect(query.query).toBeUndefined();
expect(query.params.query).toBeUndefined();
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,26 @@ describe('hierarchical facets: simple usage', function () {
});

test('persistHierarchicalRootCount: false', function (done) {
var helper = algoliasearchHelper(client, indexName, {
hierarchicalFacets: [
{
name: 'categories',
attributes: [
'categories.lvl0',
'categories.lvl1',
'categories.lvl2',
'categories.lvl3',
],
},
],
});
var helper = algoliasearchHelper(
client,
indexName,
{
hierarchicalFacets: [
{
name: 'categories',
attributes: [
'categories.lvl0',
'categories.lvl1',
'categories.lvl2',
'categories.lvl3',
],
},
],
},
{
persistHierarchicalRootCount: false,
}
);

helper.toggleFacetRefinement('categories', 'beers > IPA > Flying dog');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

test('hierarchical facets: using sortBy', function (done) {
test('hierarchical facets: using sortBy', async function () {
var algoliasearch = require('algoliasearch');
algoliasearch = algoliasearch.algoliasearch || algoliasearch;

Expand Down Expand Up @@ -30,6 +30,7 @@ test('hierarchical facets: using sortBy', function (done) {

var algoliaResponse = {
results: [
// for hits
{
query: 'a',
index: indexName,
Expand All @@ -45,6 +46,7 @@ test('hierarchical facets: using sortBy', function (done) {
'categories.lvl2': { 'beers > IPA > Flying dog': 1 },
},
},
// deepest level
{
query: 'a',
index: indexName,
Expand All @@ -54,15 +56,16 @@ test('hierarchical facets: using sortBy', function (done) {
nbPages: 1,
hitsPerPage: 1,
facets: {
'categories.lvl0': { beers: 5 },
'categories.lvl1': { 'beers > IPA': 5 },
'categories.lvl0': { beers: 1 },
'categories.lvl1': { 'beers > IPA': 1 },
'categories.lvl2': {
'beers > IPA > Flying dog': 1,
'beers > IPA > Anchor steam': 1,
'beers > IPA > Brewdog punk IPA': 3,
},
},
},
// root level
{
query: 'a',
index: indexName,
Expand All @@ -75,6 +78,19 @@ test('hierarchical facets: using sortBy', function (done) {
'categories.lvl0': { beers: 5 },
},
},
// other levels
{
query: 'a',
index: indexName,
hits: [{ objectID: 'one' }],
nbHits: 1,
page: 0,
nbPages: 1,
hitsPerPage: 1,
facets: {
'categories.lvl1': { 'beers > IPA': 5 },
},
},
],
};

Expand Down Expand Up @@ -143,8 +159,10 @@ test('hierarchical facets: using sortBy', function (done) {
});

helper.setQuery('a').search();
helper.once('result', function (event) {
expect(event.results.hierarchicalFacets).toEqual(expectedHelperResponse);
done();

const { results } = await new Promise(function (resolve) {
helper.once('result', resolve);
});

expect(results.hierarchicalFacets).toEqual(expectedHelperResponse);
});
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ describe('start', () => {
searchClient,
indexName,
undefined,
{ persistHierarchicalRootCount: false }
{ persistHierarchicalRootCount: true }
);
});

Expand All @@ -887,7 +887,7 @@ describe('start', () => {
searchClient,
indexName,
undefined,
future
{ persistHierarchicalRootCount: true }
);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/instantsearch-core/src/instantsearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const INSTANTSEARCH_FUTURE_DEFAULTS: Required<
InstantSearchOptions['future']
> = {
preserveSharedStateOnUnmount: false,
persistHierarchicalRootCount: false,
persistHierarchicalRootCount: true,
};

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/instantsearch-core/src/types/instantsearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ export type InstantSearchOptions<
*
* If `true`, the count of the root level stays the same as the count of all children levels.
*
* @default false
* @default true
*/
persistHierarchicalRootCount?: boolean; // @MAJOR change the default to true
persistHierarchicalRootCount?: boolean; // @MAJOR remove the option
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3346,7 +3346,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/index-widge
nbPages: 1,
page: 0,
params: '',
persistHierarchicalRootCount: false,
persistHierarchicalRootCount: true,
processingTimeMS: 0,
query: 'iphone',
};
Expand Down

0 comments on commit 34cca9a

Please sign in to comment.