-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(commerce): add commerce category facets (#3495)
https://coveord.atlassian.net/browse/CAPI-90 Accompanying branch in barca: coveo/barca-sports#191 --------- Co-authored-by: Nicholas-David Labarre <[email protected]> Co-authored-by: Nicholas Labarre <[email protected]>
- Loading branch information
1 parent
bcd1ffd
commit 138a8b1
Showing
29 changed files
with
2,144 additions
and
366 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
315 changes: 315 additions & 0 deletions
315
...ss/src/controllers/commerce/core/facets/category/headless-commerce-category-facet.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,315 @@ | ||
import { | ||
CategoryFacetValueRequest, | ||
CommerceFacetRequest, | ||
} from '../../../../../features/commerce/facets/facet-set/interfaces/request'; | ||
import {CategoryFacetValue} from '../../../../../features/commerce/facets/facet-set/interfaces/response'; | ||
import { | ||
toggleSelectCategoryFacetValue, | ||
updateCategoryFacetNumberOfValues, | ||
} from '../../../../../features/facets/category-facet-set/category-facet-set-actions'; | ||
import {CommerceAppState} from '../../../../../state/commerce-app-state'; | ||
import {buildMockCommerceFacetRequest} from '../../../../../test/mock-commerce-facet-request'; | ||
import {buildMockCategoryFacetResponse} from '../../../../../test/mock-commerce-facet-response'; | ||
import {buildMockCommerceFacetSlice} from '../../../../../test/mock-commerce-facet-slice'; | ||
import {buildMockCategoryFacetValue} from '../../../../../test/mock-commerce-facet-value'; | ||
import {buildMockCommerceState} from '../../../../../test/mock-commerce-state'; | ||
import { | ||
MockedCommerceEngine, | ||
buildMockCommerceEngine, | ||
} from '../../../../../test/mock-engine-v2'; | ||
import {commonOptions} from '../../../product-listing/facets/headless-product-listing-facet-options'; | ||
import { | ||
CategoryFacet, | ||
CategoryFacetOptions, | ||
buildCategoryFacet, | ||
} from './headless-commerce-category-facet'; | ||
|
||
jest.mock( | ||
'../../../../../features/facets/category-facet-set/category-facet-set-actions' | ||
); | ||
|
||
describe('CategoryFacet', () => { | ||
const facetId: string = 'category_facet_id'; | ||
let engine: MockedCommerceEngine; | ||
let state: CommerceAppState; | ||
let options: CategoryFacetOptions; | ||
let facet: CategoryFacet; | ||
|
||
function initEngine(preloadedState = buildMockCommerceState()) { | ||
engine = buildMockCommerceEngine(preloadedState); | ||
} | ||
|
||
function initCategoryFacet() { | ||
facet = buildCategoryFacet(engine, options); | ||
} | ||
|
||
function setFacetState( | ||
config: Partial<CommerceFacetRequest<CategoryFacetValueRequest>> = {}, | ||
moreValuesAvailable = false | ||
) { | ||
state.commerceFacetSet[facetId] = buildMockCommerceFacetSlice({ | ||
request: buildMockCommerceFacetRequest({ | ||
facetId, | ||
type: 'hierarchical', | ||
...config, | ||
}), | ||
}); | ||
state.productListing.facets = [ | ||
buildMockCategoryFacetResponse({ | ||
moreValuesAvailable, | ||
facetId, | ||
type: 'hierarchical', | ||
values: (config.values as CategoryFacetValue[]) ?? [], | ||
}), | ||
]; | ||
} | ||
|
||
// eslint-disable-next-line @cspell/spellchecker | ||
// TODO CAPI-90: Test facet search | ||
/*function setFacetSearch() { | ||
state.facetSearchSet[facetId] = buildMockFacetSearch(); | ||
}*/ | ||
|
||
beforeEach(() => { | ||
jest.resetAllMocks(); | ||
|
||
options = { | ||
facetId, | ||
...commonOptions, | ||
}; | ||
|
||
state = buildMockCommerceState(); | ||
setFacetState(); | ||
// eslint-disable-next-line @cspell/spellchecker | ||
// TODO CAPI-90: Test facet search | ||
// setFacetSearch(); | ||
|
||
initEngine(state); | ||
initCategoryFacet(); | ||
}); | ||
|
||
describe('initialization', () => { | ||
it('initializes', () => { | ||
expect(facet).toBeTruthy(); | ||
}); | ||
|
||
it('exposes #subscribe method', () => { | ||
expect(facet.subscribe).toBeTruthy(); | ||
}); | ||
}); | ||
|
||
it('#toggleSelect dispatches #toggleSelectCategoryFacetValue with correct payload', () => { | ||
const facetValue = buildMockCategoryFacetValue(); | ||
facet.toggleSelect(facetValue); | ||
|
||
expect(toggleSelectCategoryFacetValue).toHaveBeenCalledWith({ | ||
facetId, | ||
selection: facetValue, | ||
}); | ||
}); | ||
|
||
it('#showLessValues dispatches #updateCategoryFacetNumberOfValues with correct payload', () => { | ||
facet.showLessValues(); | ||
|
||
expect(updateCategoryFacetNumberOfValues).toHaveBeenCalledWith({ | ||
facetId, | ||
numberOfValues: 5, | ||
}); | ||
}); | ||
|
||
it('#showMoreValues dispatches #updateCategoryFacetNumberOfValues with correct payload', () => { | ||
facet.showMoreValues(); | ||
|
||
expect(updateCategoryFacetNumberOfValues).toHaveBeenCalledWith({ | ||
facetId, | ||
numberOfValues: 5, | ||
}); | ||
}); | ||
|
||
describe('#state', () => { | ||
describe('#activeValue', () => { | ||
it('when no value is selected, returns undefined', () => { | ||
expect(facet.state.activeValue).toBeUndefined(); | ||
}); | ||
it('when a value is selected, returns the selected value', () => { | ||
const activeValue = buildMockCategoryFacetValue({ | ||
state: 'selected', | ||
}); | ||
setFacetState({ | ||
values: [activeValue, buildMockCategoryFacetValue()], | ||
}); | ||
|
||
expect(facet.state.activeValue).toBe(activeValue); | ||
}); | ||
}); | ||
|
||
describe('#canShowLessValues', () => { | ||
describe('when no value is selected', () => { | ||
it('when there are no values, returns false', () => { | ||
expect(facet.state.canShowLessValues).toBe(false); | ||
}); | ||
it('when there are fewer values than default number of values, returns false', () => { | ||
setFacetState({ | ||
values: [buildMockCategoryFacetValue()], | ||
}); | ||
|
||
expect(facet.state.canShowLessValues).toBe(false); | ||
}); | ||
it('when there are more values than default number of values, returns true', () => { | ||
setFacetState({ | ||
values: [ | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
], | ||
}); | ||
|
||
expect(facet.state.canShowLessValues).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('when a value is selected', () => { | ||
it('when selected value has no children, returns false', () => { | ||
setFacetState({ | ||
values: [ | ||
buildMockCategoryFacetValue({ | ||
state: 'selected', | ||
}), | ||
], | ||
}); | ||
|
||
expect(facet.state.canShowLessValues).toBe(false); | ||
}); | ||
it('when selected value fewer children than default number of values, returns false', () => { | ||
setFacetState({ | ||
values: [ | ||
buildMockCategoryFacetValue({ | ||
state: 'selected', | ||
children: [buildMockCategoryFacetValue()], | ||
}), | ||
], | ||
}); | ||
|
||
expect(facet.state.canShowLessValues).toBe(false); | ||
}); | ||
it('when selected value has more children than default number of values, return true', () => { | ||
setFacetState({ | ||
values: [ | ||
buildMockCategoryFacetValue({ | ||
state: 'selected', | ||
children: [ | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
buildMockCategoryFacetValue(), | ||
], | ||
}), | ||
], | ||
}); | ||
|
||
expect(facet.state.canShowLessValues).toBe(true); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('#canShowMoreValues', () => { | ||
describe('when no value is selected', () => { | ||
it('when there are no more values available, returns false', () => { | ||
expect(facet.state.canShowMoreValues).toBe(false); | ||
}); | ||
|
||
it('when there are more values available, returns true', () => { | ||
setFacetState({}, true); | ||
|
||
expect(facet.state.canShowMoreValues).toBe(true); | ||
}); | ||
}); | ||
|
||
describe('when a value is selected', () => { | ||
it('when selected values has no more values available, returns false', () => { | ||
setFacetState({ | ||
values: [buildMockCategoryFacetValue({state: 'selected'})], | ||
}); | ||
|
||
expect(facet.state.canShowMoreValues).toBe(false); | ||
}); | ||
it('when selected value has more values available, returns true', () => { | ||
setFacetState({ | ||
values: [ | ||
buildMockCategoryFacetValue({ | ||
state: 'selected', | ||
moreValuesAvailable: true, | ||
}), | ||
], | ||
}); | ||
|
||
expect(facet.state.canShowMoreValues).toBe(true); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('#hasActiveValues', () => { | ||
it('when no value is selected, returns false', () => { | ||
expect(facet.state.hasActiveValues).toBe(false); | ||
}); | ||
|
||
it('when a value is selected, returns true', () => { | ||
setFacetState({ | ||
values: [buildMockCategoryFacetValue({state: 'selected'})], | ||
}); | ||
|
||
expect(facet.state.hasActiveValues).toBe(true); | ||
}); | ||
}); | ||
|
||
describe('#selectedValueAncestry', () => { | ||
it('when no value is selected, returns empty array', () => { | ||
expect(facet.state.selectedValueAncestry).toEqual([]); | ||
}); | ||
|
||
it('when a value is selected, returns the selected value ancestry', () => { | ||
const activeValue = buildMockCategoryFacetValue({ | ||
value: 'c', | ||
path: ['a', 'b', 'c'], | ||
state: 'selected', | ||
children: [ | ||
buildMockCategoryFacetValue({ | ||
value: 'd', | ||
path: ['a', 'b', 'c', 'd'], | ||
}), | ||
buildMockCategoryFacetValue({ | ||
value: 'e', | ||
path: ['a', 'b', 'c', 'e'], | ||
}), | ||
], | ||
}); | ||
const parentValue = buildMockCategoryFacetValue({ | ||
value: 'b', | ||
path: ['a', 'b'], | ||
children: [activeValue], | ||
}); | ||
|
||
const rootValue = buildMockCategoryFacetValue({ | ||
value: 'a', | ||
path: ['a'], | ||
children: [parentValue], | ||
}); | ||
|
||
setFacetState({ | ||
values: [rootValue], | ||
}); | ||
|
||
expect(facet.state.selectedValueAncestry).toEqual([ | ||
rootValue, | ||
parentValue, | ||
activeValue, | ||
]); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.