Skip to content

Commit

Permalink
fix(headless): don't leak pagination state to productSuggest call (#4667
Browse files Browse the repository at this point in the history
)

https://coveord.atlassian.net/browse/KIT-3660

For some context, 

Initially the ticket was "stop culling productSuggest to 5". It could
not be done since the pagination part of the state was overwriting the
perPage value for the productSuggest call (a feature from CAPI). So
let's say there was 25 products in the page, there would be 25 product
suggesting since both call were using the same pagination.

Pagination is useless for now in productSuggest so we can simply remove
it from the request.

---------

Co-authored-by: GitHub Actions Bot <>
  • Loading branch information
alexprudhomme authored Jan 20, 2025
1 parent 7c2491c commit b69cf0a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class SearchBoxPageObject extends BasePageObject<'atomic-commerce-search-
}: {index?: number; total?: number; listSide?: 'Left' | 'Right'} = {}) {
return this.page.getByLabel(
new RegExp(
`instant result\\.(?: Button\\.)? ${index ?? '\\d'} of ${total ?? '\\d'}\\.${this.listSideAffix(listSide)}`
`instant result\\.(?: Button\\.)? ${index ?? '\\d{1,2}'} of ${total ?? '\\d{1,2}'}\\.${this.listSideAffix(listSide)}`
)
);
}
Expand Down
38 changes: 38 additions & 0 deletions packages/headless/src/features/commerce/common/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,4 +530,42 @@ describe('commerce common actions', () => {
});
});
});

describe('#buildInstantProductsAPIRequest', () => {
let state: Actions.ListingAndSearchStateNeededByQueryCommerceAPI;
let mockedBuildInstantProductsAPIRequest: MockInstance;

beforeEach(() => {
vi.clearAllMocks();
state = buildMockCommerceState();
mockedBuildInstantProductsAPIRequest = vi.spyOn(
Actions,
'buildInstantProductsAPIRequest'
);
});

it('given a state that has commercePagination, returns request without it', () => {
state.commercePagination = {
principal: {
page: 1,
perPage: 10,
totalEntries: 50,
totalPages: 5,
},
recommendations: {},
};

const request = Actions.buildInstantProductsAPIRequest(
state,
navigatorContext
);

expect(mockedBuildInstantProductsAPIRequest).toHaveBeenCalledWith(
state,
navigatorContext
);

expect(request.page).toEqual(undefined);
});
});
});
10 changes: 10 additions & 0 deletions packages/headless/src/features/commerce/common/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ export const buildCommerceAPIRequest = (
};
};

export const buildInstantProductsAPIRequest = (
state: ListingAndSearchStateNeededByQueryCommerceAPI,
navigatorContext: NavigatorContext
): CommerceAPIRequest => {
const {commercePagination, ...restState} = state;
return {
...buildCommerceAPIRequest(restState, navigatorContext),
};
};

export const buildBaseCommerceAPIRequest = (
state: StateNeededByQueryCommerceAPI,
navigatorContext: NavigatorContext,
Expand Down
14 changes: 6 additions & 8 deletions packages/headless/src/features/commerce/search/search-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import {ChildProduct} from '../../../api/commerce/common/product.js';
import {SearchCommerceSuccessResponse} from '../../../api/commerce/search/response.js';
import {validatePayload} from '../../../utils/validate-payload.js';
import {deselectAllNonBreadcrumbs} from '../../breadcrumb/breadcrumb-actions.js';
import {buildCommerceAPIRequest} from '../common/actions.js';
import {
buildCommerceAPIRequest,
buildInstantProductsAPIRequest,
} from '../common/actions.js';
import {
clearAllCoreFacets,
updateAutoSelectionForAllCoreFacets,
Expand Down Expand Up @@ -155,21 +158,16 @@ export const fetchInstantProducts = createAsyncThunk<
const {apiClient, navigatorContext} = extra;
const {q} = payload;
const fetched = await apiClient.productSuggestions({
...buildCommerceAPIRequest(state, navigatorContext),
...buildInstantProductsAPIRequest(state, navigatorContext),
query: q,
});

if (isErrorResponse(fetched)) {
return rejectWithValue(fetched.error);
}

// TODO: Should ultimately rely on different config for product suggest endpoint which would support
// different config for pagination: Would not have to cull array of products client side.
// https://coveord.atlassian.net/browse/CAPI-682
const products = fetched.success.products.slice(0, 5);

return {
response: {...fetched.success, products},
response: {...fetched.success, products: fetched.success.products},
};
}
);
Expand Down

0 comments on commit b69cf0a

Please sign in to comment.