Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(commerce): namespace field suggestions to prevent clash with facet search #4247

Merged
merged 4 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import {executeCommerceFieldSuggest} from '../../../features/commerce/facets/facet-search-set/commerce-facet-search-actions';
import {
executeCommerceFieldSuggest,
getFacetIdWithCommerceFieldSuggestionNamespace,
} from '../../../features/commerce/facets/facet-search-set/commerce-facet-search-actions';
import {commerceFacetSetReducer as commerceFacetSet} from '../../../features/commerce/facets/facet-set/facet-set-slice';
import {CategoryFacetRequest} from '../../../features/commerce/facets/facet-set/interfaces/request';
import {fieldSuggestionsOrderReducer as fieldSuggestionsOrder} from '../../../features/commerce/facets/field-suggestions-order/field-suggestions-order-slice';
Expand Down Expand Up @@ -33,15 +36,17 @@ describe('categoryFieldSuggestions', () => {
let fieldSuggestions: CategoryFieldSuggestions;
let options: CategoryFacetOptions;

function initFacet() {
function initFieldSuggestions() {
engine = buildMockCommerceEngine(state);
fieldSuggestions = buildCategoryFieldSuggestions(engine, options);
}

function setFacetRequest(config: Partial<CategoryFacetRequest> = {}) {
const request = buildMockCommerceFacetRequest({facetId, ...config});
state.commerceFacetSet[facetId] = buildMockCommerceFacetSlice({request});
state.categoryFacetSearchSet[facetId] = buildMockCategoryFacetSearch({
state.categoryFacetSearchSet[
getFacetIdWithCommerceFieldSuggestionNamespace(facetId)
] = buildMockCategoryFacetSearch({
initialNumberOfValues: 5,
});
}
Expand All @@ -58,7 +63,7 @@ describe('categoryFieldSuggestions', () => {
state = buildMockCommerceState();
setFacetRequest();

initFacet();
initFieldSuggestions();
});

it('adds correct reducers to engine', () => {
Expand All @@ -72,7 +77,7 @@ describe('categoryFieldSuggestions', () => {
it('should dispatch an #updateFacetSearch and #executeFieldSuggest action on #updateText', () => {
fieldSuggestions.updateText('foo');
expect(updateFacetSearch).toHaveBeenCalledWith({
facetId,
facetId: getFacetIdWithCommerceFieldSuggestionNamespace(facetId),
query: 'foo',
numberOfValues: 5,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CommerceEngineState,
} from '../../../app/commerce-engine/commerce-engine';
import {stateKey} from '../../../app/state-key';
import {getFacetIdWithCommerceFieldSuggestionNamespace} from '../../../features/commerce/facets/facet-search-set/commerce-facet-search-actions';
import {commerceFacetSetReducer as commerceFacetSet} from '../../../features/commerce/facets/facet-set/facet-set-slice';
import {fieldSuggestionsOrderReducer as fieldSuggestionsOrder} from '../../../features/commerce/facets/field-suggestions-order/field-suggestions-order-slice';
import {categoryFacetSearchSetReducer as categoryFacetSearchSet} from '../../../features/facets/facet-search-set/category/category-facet-search-set-slice';
Expand Down Expand Up @@ -81,9 +82,12 @@ export function buildCategoryFieldSuggestions(

const {dispatch} = engine;

const namespacedFacetId = getFacetIdWithCommerceFieldSuggestionNamespace(
options.facetId
);
const facetSearch = buildCategoryFacetSearch(engine, {
options: {
facetId: options.facetId,
facetId: namespacedFacetId,
...options.facetSearch,
numberOfValues: 10,
},
Expand All @@ -105,7 +109,7 @@ export function buildCategoryFieldSuggestions(

const facetSearchStateSelector = createSelector(
(state: CommerceEngineState) =>
state.categoryFacetSearchSet[options.facetId],
state.categoryFacetSearchSet[namespacedFacetId],
(facetSearch) => ({
isLoading: facetSearch.isLoading,
moreValuesAvailable: facetSearch.response.moreValuesAvailable,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {FacetSearchType} from '../../../api/commerce/facet-search/facet-search-request';
import {FieldSuggestionsFacet} from '../../../api/commerce/search/query-suggest/query-suggest-response';
import {getFacetIdWithCommerceFieldSuggestionNamespace} from '../../../features/commerce/facets/facet-search-set/commerce-facet-search-actions';
import {fieldSuggestionsOrderReducer as fieldSuggestionsOrder} from '../../../features/commerce/facets/field-suggestions-order/field-suggestions-order-slice';
import {CommerceAppState} from '../../../state/commerce-app-state';
import {buildMockCategoryFacetSearch} from '../../../test/mock-category-facet-search';
Expand Down Expand Up @@ -38,16 +39,22 @@ describe('fieldSuggestionsGenerator', () => {

function setFacetState(config: FieldSuggestionsFacet[] = []) {
for (const facet of config) {
const namespacedFacetId = getFacetIdWithCommerceFieldSuggestionNamespace(
facet.facetId
);
state.fieldSuggestionsOrder.push(facet);
state.commerceFacetSet[facet.facetId] = {
request: buildMockCommerceFacetRequest({
facetId: facet.facetId,
type: facet.type,
}),
};
state.facetSearchSet[facet.facetId] = buildMockFacetSearch();
state.categoryFacetSearchSet[facet.facetId] =
buildMockCategoryFacetSearch();
if (facet.type === 'regular') {
state.facetSearchSet[namespacedFacetId] = buildMockFacetSearch();
} else {
state.commerceFacetSet[facet.facetId] = {
request: buildMockCommerceFacetRequest({
facetId: facet.facetId,
type: facet.type,
}),
};
state.categoryFacetSearchSet[namespacedFacetId] =
buildMockCategoryFacetSearch();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {executeCommerceFieldSuggest} from '../../../features/commerce/facets/facet-search-set/commerce-facet-search-actions';
import {
executeCommerceFieldSuggest,
getFacetIdWithCommerceFieldSuggestionNamespace,
} from '../../../features/commerce/facets/facet-search-set/commerce-facet-search-actions';
import {commerceFacetSetReducer as commerceFacetSet} from '../../../features/commerce/facets/facet-set/facet-set-slice';
import {RegularFacetRequest} from '../../../features/commerce/facets/facet-set/interfaces/request';
import {fieldSuggestionsOrderReducer as fieldSuggestionsOrder} from '../../../features/commerce/facets/field-suggestions-order/field-suggestions-order-slice';
import {updateFacetSearch} from '../../../features/facets/facet-search-set/specific/specific-facet-search-actions';
import {specificFacetSearchSetReducer as facetSearchSet} from '../../../features/facets/facet-search-set/specific/specific-facet-search-set-slice';
import {CommerceAppState} from '../../../state/commerce-app-state';
import {buildMockCommerceFacetRequest} from '../../../test/mock-commerce-facet-request';
import {buildMockCommerceFacetSlice} from '../../../test/mock-commerce-facet-slice';
import {buildMockCommerceState} from '../../../test/mock-commerce-state';
import {
buildMockCommerceEngine,
Expand All @@ -33,16 +33,15 @@ describe('fieldSuggestions', () => {
let fieldSuggestions: FieldSuggestions;
let options: RegularFacetOptions;

function initFacet() {
function initFieldSuggestions() {
engine = buildMockCommerceEngine(state);
fieldSuggestions = buildFieldSuggestions(engine, options);
}

function setFacetRequest(config: Partial<RegularFacetRequest> = {}) {
state.commerceFacetSet[facetId] = buildMockCommerceFacetSlice({
request: buildMockCommerceFacetRequest({facetId, ...config}),
});
state.facetSearchSet[facetId] = buildMockFacetSearch({
function setFacetSearchRequest() {
state.facetSearchSet[
getFacetIdWithCommerceFieldSuggestionNamespace(facetId)
] = buildMockFacetSearch({
initialNumberOfValues: 5,
});
}
Expand All @@ -58,9 +57,9 @@ describe('fieldSuggestions', () => {
};

state = buildMockCommerceState();
setFacetRequest();
setFacetSearchRequest();

initFacet();
initFieldSuggestions();
});

it('adds correct reducers to engine', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
CommerceEngineState,
} from '../../../app/commerce-engine/commerce-engine';
import {stateKey} from '../../../app/state-key';
import {getFacetIdWithCommerceFieldSuggestionNamespace} from '../../../features/commerce/facets/facet-search-set/commerce-facet-search-actions';
import {commerceFacetSetReducer as commerceFacetSet} from '../../../features/commerce/facets/facet-set/facet-set-slice';
import {fieldSuggestionsOrderReducer as fieldSuggestionsOrder} from '../../../features/commerce/facets/field-suggestions-order/field-suggestions-order-slice';
import {specificFacetSearchSetReducer as facetSearchSet} from '../../../features/facets/facet-search-set/specific/specific-facet-search-set-slice';
Expand Down Expand Up @@ -99,8 +100,11 @@ export function buildFieldSuggestions(

const {dispatch} = engine;

const namespacedFacetId = getFacetIdWithCommerceFieldSuggestionNamespace(
options.facetId
);
const facetSearch = buildRegularFacetSearch(engine, {
options: {facetId: options.facetId, ...options.facetSearch},
options: {facetId: namespacedFacetId, ...options.facetSearch},
select: () => {
dispatch(options.fetchProductsActionCreator());
},
Expand All @@ -121,7 +125,7 @@ export function buildFieldSuggestions(
const controller = buildController(engine);

const facetSearchStateSelector = createSelector(
(state: CommerceEngineState) => state.facetSearchSet[options.facetId],
(state: CommerceEngineState) => state.facetSearchSet[namespacedFacetId],
(facetSearch) => ({
isLoading: facetSearch.isLoading,
moreValuesAvailable: facetSearch.response.moreValuesAvailable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,25 @@ import {buildMockCommerceState} from '../../../../../test/mock-commerce-state';
import {buildMockFacetSearchRequestOptions} from '../../../../../test/mock-facet-search-request-options';
import {buildMockNavigatorContextProvider} from '../../../../../test/mock-navigator-context-provider';
import {CategoryFacetValueRequest} from '../../facet-set/interfaces/request';
import {
getFacetIdWithCommerceFieldSuggestionNamespace,
getFacetIdWithoutCommerceFieldSuggestionNamespace,
} from '../commerce-facet-search-actions';
import {buildCategoryFacetSearchRequest} from './commerce-category-facet-search-request-builder';

describe('#buildCategoryFacetSearchRequest', () => {
let state: CommerceAppState;
let navigatorContext: NavigatorContext;
let facetId: string;
const facetId = '1';
let query: string;
let buildCommerceAPIRequestMock: jest.SpyInstance;

beforeEach(() => {
jest.clearAllMocks();

facetId = '1';
query = 'test';
state = buildMockCommerceState();

state.categoryFacetSearchSet[facetId] = buildMockCategoryFacetSearch({
options: {...buildMockFacetSearchRequestOptions(), query},
});
Expand Down Expand Up @@ -64,7 +68,28 @@ describe('#buildCategoryFacetSearchRequest', () => {
);
});

describe('returned object #ignorePaths property', () => {
describe.each([
{
facetId: 'a_non_namespaced_facet_id',
},
{
facetId: getFacetIdWithCommerceFieldSuggestionNamespace(
'a_namespaced_facet_id'
),
},
])('returned object #ignorePaths property', ({facetId}) => {
beforeEach(() => {
state.categoryFacetSearchSet[facetId] = buildMockCategoryFacetSearch({
options: {...buildMockFacetSearchRequestOptions(), query},
});

state.commerceFacetSet[
getFacetIdWithoutCommerceFieldSuggestionNamespace(facetId)
] = buildMockCommerceFacetSlice({
request: buildMockCommerceFacetRequest({type: 'hierarchical'}),
});
});

it('when the facet request has no selected value, is an empty array', () => {
const request = buildCategoryFacetSearchRequest(
facetId,
Expand All @@ -77,8 +102,12 @@ describe('#buildCategoryFacetSearchRequest', () => {
});

it('when the facet request has a selected value with no ancestry, is an array with a single array containing the selected value', () => {
state.commerceFacetSet[facetId].request.values[0] =
buildMockCategoryFacetValue({state: 'selected', value: 'test'});
state.commerceFacetSet[
getFacetIdWithoutCommerceFieldSuggestionNamespace(facetId)
].request.values[0] = buildMockCategoryFacetValue({
state: 'selected',
value: 'test',
});
const request = buildCategoryFacetSearchRequest(
facetId,
state,
Expand All @@ -89,15 +118,18 @@ describe('#buildCategoryFacetSearchRequest', () => {
expect(request.ignorePaths).toStrictEqual([
[
(
state.commerceFacetSet[facetId].request
.values[0] as CategoryFacetValueRequest
state.commerceFacetSet[
getFacetIdWithoutCommerceFieldSuggestionNamespace(facetId)
].request.values[0] as CategoryFacetValueRequest
).value,
],
]);
});

it('when the facet request has a selected value with ancestry, is an array with a single array containing the selected value and its ancestors', () => {
state.commerceFacetSet[facetId].request.values[0] =
const nonNamespacedId =
getFacetIdWithoutCommerceFieldSuggestionNamespace(facetId);
state.commerceFacetSet[nonNamespacedId].request.values[0] =
buildMockCategoryFacetValue({
value: 'test',
children: [
Expand All @@ -122,15 +154,15 @@ describe('#buildCategoryFacetSearchRequest', () => {
expect(request.ignorePaths).toStrictEqual([
[
(
state.commerceFacetSet[facetId].request
state.commerceFacetSet[nonNamespacedId].request
.values[0] as CategoryFacetValueRequest
).value,
(
state.commerceFacetSet[facetId].request
state.commerceFacetSet[nonNamespacedId].request
.values[0] as CategoryFacetValueRequest
).children[0].value,
(
state.commerceFacetSet[facetId].request
state.commerceFacetSet[nonNamespacedId].request
.values[0] as CategoryFacetValueRequest
).children[0].children[0].value,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
AnyFacetRequest,
CategoryFacetRequest,
} from '../../facet-set/interfaces/request';
import {getFacetIdWithoutCommerceFieldSuggestionNamespace} from '../commerce-facet-search-actions';
import {StateNeededForCategoryFacetSearch} from './commerce-category-facet-search-state';

export const buildCategoryFacetSearchRequest = (
Expand All @@ -15,7 +16,10 @@ export const buildCategoryFacetSearchRequest = (
): CategoryFacetSearchRequest => {
const baseFacetQuery = state.categoryFacetSearchSet[facetId]!.options.query;
const facetQuery = `*${baseFacetQuery}*`;
const categoryFacet = state.commerceFacetSet[facetId]?.request;
const categoryFacet =
state.commerceFacetSet[
getFacetIdWithoutCommerceFieldSuggestionNamespace(facetId)
]?.request;
const path =
categoryFacet && isCategoryFacetRequest(categoryFacet)
? categoryFacet && getPathToSelectedCategoryFacetItem(categoryFacet)
Expand All @@ -40,7 +44,7 @@ export const buildCategoryFacetSearchRequest = (
url,
accessToken,
organizationId,
facetId,
facetId: getFacetIdWithoutCommerceFieldSuggestionNamespace(facetId),
facetQuery,
ignorePaths,
trackingId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,21 @@ export const isRegularFieldSuggestionsState = (
(facet) => facet.facetId === facetId && facet.type === 'regular'
);
};

const commerceFieldSuggestionNamespace = 'field_suggestion:';

export function getFacetIdWithoutCommerceFieldSuggestionNamespace(
facetId: string
) {
return facetId.startsWith(commerceFieldSuggestionNamespace)
? facetId.slice(commerceFieldSuggestionNamespace.length)
: facetId;
}

export function getFacetIdWithCommerceFieldSuggestionNamespace(
facetId: string
): string {
return facetId.startsWith(commerceFieldSuggestionNamespace)
? facetId
: `${commerceFieldSuggestionNamespace}${facetId}`;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {CommerceFacetSearchRequest} from '../../../../../api/commerce/facet-search/facet-search-request';
import {NavigatorContext} from '../../../../../app/navigatorContextProvider';
import {buildCommerceAPIRequest} from '../../../common/actions';
import {getFacetIdWithoutCommerceFieldSuggestionNamespace} from '../commerce-facet-search-actions';
import {StateNeededForRegularFacetSearch} from './commerce-regular-facet-search-state';

export const buildFacetSearchRequest = (
Expand Down Expand Up @@ -30,7 +31,7 @@ export const buildFacetSearchRequest = (
url,
accessToken,
organizationId,
facetId,
facetId: getFacetIdWithoutCommerceFieldSuggestionNamespace(facetId),
facetQuery,
trackingId,
language,
Expand Down
Loading
Loading