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

feat(commerce): expose facet generator as sub-controller #3855

Merged
merged 4 commits into from
May 2, 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
Expand Up @@ -3,6 +3,7 @@ import {
MockedCommerceEngine,
buildMockCommerceEngine,
} from '../../../../test/mock-engine-v2';
import * as CoreFacetGenerator from '../facets/generator/headless-commerce-facet-generator';
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';
Expand All @@ -17,6 +18,8 @@ describe('sub controllers', () => {
let engine: MockedCommerceEngine;
const mockResponseIdSelector = jest.fn();
const mockFetchResultsActionCreator = jest.fn();
const mockFacetResponseSelector = jest.fn();
const mockIsFacetLoadingResponseSelector = jest.fn();

beforeEach(() => {
engine = buildMockCommerceEngine(buildMockCommerceState());
Expand Down Expand Up @@ -47,6 +50,8 @@ describe('sub controllers', () => {
const subControllers = subControllersBuilder(engine, {
responseIdSelector: mockResponseIdSelector,
fetchResultsActionCreator: mockFetchResultsActionCreator,
facetResponseSelector: mockFacetResponseSelector,
isFacetLoadingResponseSelector: mockIsFacetLoadingResponseSelector,
});
const buildCoreInteractiveResultMock = jest.spyOn(
CoreInteractiveResult,
Expand Down Expand Up @@ -81,6 +86,8 @@ describe('sub controllers', () => {
subControllers = buildSolutionTypeSubControllers(engine, {
responseIdSelector: mockResponseIdSelector,
fetchResultsActionCreator: mockFetchResultsActionCreator,
facetResponseSelector: mockFacetResponseSelector,
isFacetLoadingResponseSelector: mockIsFacetLoadingResponseSelector,
});
});

Expand All @@ -102,6 +109,19 @@ describe('sub controllers', () => {

expect(sort).toEqual(buildCoreSortMock.mock.results[0].value);
});

it('#facetGenerator builds facet generator', () => {
const buildCoreFacetGenerator = jest.spyOn(
CoreFacetGenerator,
'buildFacetGenerator'
);

const facetGenerator = subControllers.facetGenerator();

expect(facetGenerator).toEqual(
buildCoreFacetGenerator.mock.results[0].value
);
});
});

describe('#buildRecommendationsSubControllers', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@ import {
CommerceEngine,
CommerceEngineState,
} from '../../../../app/commerce-engine/commerce-engine';
import {AnyFacetResponse} from '../../../../features/commerce/facets/facet-set/interfaces/response';
import {FetchResultsActionCreator} from '../common';
import {buildCategoryFacet} from '../facets/category/headless-commerce-category-facet';
import {buildCommerceDateFacet} from '../facets/date/headless-commerce-date-facet';
import {
buildFacetGenerator,
FacetGenerator,
} from '../facets/generator/headless-commerce-facet-generator';
import {buildCommerceNumericFacet} from '../facets/numeric/headless-commerce-numeric-facet';
import {buildCommerceRegularFacet} from '../facets/regular/headless-commerce-regular-facet';
import {
buildCorePagination,
Pagination,
Expand All @@ -24,21 +33,36 @@ export interface BaseSolutionTypeSubControllers {
pagination: (props?: PaginationProps) => Pagination;
}

export type SearchAndListingSubControllers = BaseSolutionTypeSubControllers & {
export interface SearchAndListingSubControllers
extends BaseSolutionTypeSubControllers {
sort: (props?: SortProps) => Sort;
};
facetGenerator: () => FacetGenerator;
}

interface SubControllerProps {
interface BaseSubControllerProps {
responseIdSelector: (state: CommerceEngineState) => string;
fetchResultsActionCreator: FetchResultsActionCreator;
slotId?: string;
}

export interface SearchAndListingSubControllerProps
extends BaseSubControllerProps {
facetResponseSelector: (
state: CommerceEngine['state'],
facetId: string
) => AnyFacetResponse | undefined;
isFacetLoadingResponseSelector: (state: CommerceEngine['state']) => boolean;
}

export function buildSolutionTypeSubControllers(
engine: CommerceEngine,
subControllerProps: SubControllerProps
subControllerProps: SearchAndListingSubControllerProps
): SearchAndListingSubControllers {
const {fetchResultsActionCreator} = subControllerProps;
const {
fetchResultsActionCreator,
facetResponseSelector,
isFacetLoadingResponseSelector,
} = subControllerProps;
return {
...buildBaseSolutionTypeControllers(engine, subControllerProps),
sort(props?: SortProps) {
Expand All @@ -47,12 +71,29 @@ export function buildSolutionTypeSubControllers(
fetchResultsActionCreator,
});
},
facetGenerator() {
const commonOptions = {
fetchResultsActionCreator,
facetResponseSelector,
isFacetLoadingResponseSelector,
};
return buildFacetGenerator(engine, {
buildRegularFacet: (_engine, options) =>
buildCommerceRegularFacet(engine, {...options, ...commonOptions}),
buildNumericFacet: (_engine, options) =>
buildCommerceNumericFacet(engine, {...options, ...commonOptions}),
buildDateFacet: (_engine, options) =>
buildCommerceDateFacet(engine, {...options, ...commonOptions}),
buildCategoryFacet: (_engine, options) =>
buildCategoryFacet(engine, {...options, ...commonOptions}),
});
},
};
}

export function buildBaseSolutionTypeControllers(
engine: CommerceEngine,
subControllerProps: SubControllerProps
subControllerProps: BaseSubControllerProps
): BaseSolutionTypeSubControllers {
const {responseIdSelector, fetchResultsActionCreator, slotId} =
subControllerProps;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ export const facetResponseSelector = (
return undefined;
};

const isFacetLoadingResponseSelector = (state: ProductListingV2Section) =>
state.productListing.isLoading;
export const isFacetLoadingResponseSelector = (
state: ProductListingV2Section
) => state.productListing.isLoading;

export const commonOptions: Pick<
CoreCommerceFacetOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import {
buildSolutionTypeSubControllers,
SearchAndListingSubControllers,
} from '../core/sub-controller/headless-sub-controller';
import {
facetResponseSelector,
isFacetLoadingResponseSelector,
} from './facets/headless-product-listing-facet-options';

/**
* The `ProductListing` controller exposes a method for retrieving product listing content in a commerce interface.
Expand Down Expand Up @@ -57,6 +61,8 @@ export function buildProductListing(engine: CommerceEngine): ProductListing {
const subControllers = buildSolutionTypeSubControllers(engine, {
responseIdSelector,
fetchResultsActionCreator: fetchProductListing,
facetResponseSelector,
isFacetLoadingResponseSelector,
});

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const facetResponseSelector = (
return undefined;
};

const isFacetLoadingResponseSelector = (state: CommerceSearchSection) =>
export const isFacetLoadingResponseSelector = (state: CommerceSearchSection) =>
state.commerceSearch.isLoading;

export const commonOptions: Pick<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import {
buildSolutionTypeSubControllers,
SearchAndListingSubControllers,
} from '../core/sub-controller/headless-sub-controller';
import {
facetResponseSelector,
isFacetLoadingResponseSelector,
} from './facets/headless-search-facet-options';

export interface Search extends Controller, SearchAndListingSubControllers {
/**
Expand Down Expand Up @@ -48,6 +52,8 @@ export function buildSearch(engine: CommerceEngine): Search {
const subControllers = buildSolutionTypeSubControllers(engine, {
responseIdSelector,
fetchResultsActionCreator: executeSearch,
facetResponseSelector,
isFacetLoadingResponseSelector,
});

return {
Expand Down
Loading