diff --git a/packages/headless/src/controllers/commerce/core/sub-controller/headless-sub-controller.test.ts b/packages/headless/src/controllers/commerce/core/sub-controller/headless-sub-controller.test.ts new file mode 100644 index 00000000000..56d24629a9b --- /dev/null +++ b/packages/headless/src/controllers/commerce/core/sub-controller/headless-sub-controller.test.ts @@ -0,0 +1,81 @@ +import {buildMockCommerceState} from '../../../../test/mock-commerce-state'; +import { + MockedCommerceEngine, + buildMockCommerceEngine, +} from '../../../../test/mock-engine-v2'; +import * as CorePagination from '../pagination/headless-core-commerce-pagination'; +import * as CoreInteractiveResult from '../result-list/headless-core-interactive-result'; +import * as CoreSort from '../sort/headless-core-commerce-sort'; +import { + buildSolutionTypeSubControllers, + SolutionTypeSubControllers, +} from './headless-sub-controller'; + +describe('sub controllers', () => { + let engine: MockedCommerceEngine; + let subControllers: SolutionTypeSubControllers; + const mockResponseIdSelector = jest.fn(); + const mockFetchResultsActionCreator = jest.fn(); + + function initSubControllers() { + engine = buildMockCommerceEngine(buildMockCommerceState()); + + subControllers = buildSolutionTypeSubControllers(engine, { + responseIdSelector: mockResponseIdSelector, + fetchResultsActionCreator: mockFetchResultsActionCreator, + }); + } + + beforeEach(() => { + initSubControllers(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('#interactiveResult builds interactive result controller', () => { + const buildCoreInteractiveResultMock = jest.spyOn( + CoreInteractiveResult, + 'buildCoreInteractiveResult' + ); + + const props = { + options: { + product: { + productId: '1', + name: 'Product name', + price: 17.99, + }, + position: 1, + }, + }; + + const interactiveResult = subControllers.interactiveResult({ + ...props, + }); + + expect(interactiveResult).toEqual( + buildCoreInteractiveResultMock.mock.results[0].value + ); + }); + + it('#pagination builds pagination controller', () => { + const buildCorePaginationMock = jest.spyOn( + CorePagination, + 'buildCorePagination' + ); + + const pagination = subControllers.pagination(); + + expect(pagination).toEqual(buildCorePaginationMock.mock.results[0].value); + }); + + it('#sort builds sort controller', () => { + const buildCoreSortMock = jest.spyOn(CoreSort, 'buildCoreSort'); + + const sort = subControllers.sort(); + + expect(sort).toEqual(buildCoreSortMock.mock.results[0].value); + }); +}); diff --git a/packages/headless/src/controllers/commerce/core/sub-controller/headless-sub-controller.ts b/packages/headless/src/controllers/commerce/core/sub-controller/headless-sub-controller.ts index 46c33200711..4fbf72d6bd4 100644 --- a/packages/headless/src/controllers/commerce/core/sub-controller/headless-sub-controller.ts +++ b/packages/headless/src/controllers/commerce/core/sub-controller/headless-sub-controller.ts @@ -2,29 +2,56 @@ import { CommerceEngine, CommerceEngineState, } from '../../../../app/commerce-engine/commerce-engine'; +import {FetchResultsActionCreator} from '../common'; +import { + buildCorePagination, + Pagination, + PaginationProps, +} from '../pagination/headless-core-commerce-pagination'; import { buildCoreInteractiveResult, InteractiveResult, InteractiveResultProps, } from '../result-list/headless-core-interactive-result'; +import { + buildCoreSort, + Sort, + SortProps, +} from '../sort/headless-core-commerce-sort'; export interface SolutionTypeSubControllers { interactiveResult: (props: InteractiveResultProps) => InteractiveResult; + pagination: (props?: PaginationProps) => Pagination; + sort: (props?: SortProps) => Sort; } interface SubControllerProps { responseIdSelector: (state: CommerceEngineState) => string; + fetchResultsActionCreator: FetchResultsActionCreator; } export function buildSolutionTypeSubControllers( engine: CommerceEngine, subControllerProps: SubControllerProps ): SolutionTypeSubControllers { + const {responseIdSelector, fetchResultsActionCreator} = subControllerProps; return { interactiveResult(props: InteractiveResultProps) { return buildCoreInteractiveResult(engine, { ...props, - responseIdSelector: subControllerProps.responseIdSelector, + responseIdSelector, + }); + }, + pagination(props?: PaginationProps) { + return buildCorePagination(engine, { + ...props, + fetchResultsActionCreator, + }); + }, + sort(props?: SortProps) { + return buildCoreSort(engine, { + ...props, + fetchResultsActionCreator, }); }, }; diff --git a/packages/headless/src/controllers/commerce/product-listing/headless-product-listing.ts b/packages/headless/src/controllers/commerce/product-listing/headless-product-listing.ts index d25b0e6adf9..0dcb1502f58 100644 --- a/packages/headless/src/controllers/commerce/product-listing/headless-product-listing.ts +++ b/packages/headless/src/controllers/commerce/product-listing/headless-product-listing.ts @@ -54,6 +54,7 @@ export function buildProductListing(engine: CommerceEngine): ProductListing { const getState = () => engine.state; const subControllers = buildSolutionTypeSubControllers(engine, { responseIdSelector, + fetchResultsActionCreator: fetchProductListing, }); return { diff --git a/packages/headless/src/controllers/commerce/search/headless-search.ts b/packages/headless/src/controllers/commerce/search/headless-search.ts index e27e5d41c12..628f08825da 100644 --- a/packages/headless/src/controllers/commerce/search/headless-search.ts +++ b/packages/headless/src/controllers/commerce/search/headless-search.ts @@ -47,6 +47,7 @@ export function buildSearch(engine: CommerceEngine): Search { const getState = () => engine.state; const subControllers = buildSolutionTypeSubControllers(engine, { responseIdSelector, + fetchResultsActionCreator: executeSearch, }); return {