From 3f647756aeba1729e975e61ff5625c9da37594b9 Mon Sep 17 00:00:00 2001 From: Simon Walenkamp Hansen Date: Mon, 12 Aug 2024 10:37:17 +0200 Subject: [PATCH 1/5] Feat: implements product search constraints --- .../builders/search/productSearchBuilder.ts | 12 +++++++++++- .../search/searchConstraintBuilder.ts | 19 +++++++++++++++++++ .../productSearch.integration.test.ts | 13 ++++++++++++- .../search/productSearchBuilder.unit.test.ts | 10 ++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 packages/client/src/builders/search/searchConstraintBuilder.ts diff --git a/packages/client/src/builders/search/productSearchBuilder.ts b/packages/client/src/builders/search/productSearchBuilder.ts index 4fae64b..7741658 100644 --- a/packages/client/src/builders/search/productSearchBuilder.ts +++ b/packages/client/src/builders/search/productSearchBuilder.ts @@ -1,9 +1,10 @@ -import { ProductSearchRequest, ProductSearchSettings, RecommendationSettings, RetailMediaQuery, SelectedBrandPropertiesSettings, SelectedProductPropertiesSettings, SelectedVariantPropertiesSettings, VariantSearchSettings } from '../../models/data-contracts'; +import { ProductSearchRequest, ProductSearchSettings, RecommendationSettings, ResultMustHaveVariantConstraint, RetailMediaQuery, SelectedBrandPropertiesSettings, SelectedProductPropertiesSettings, SelectedVariantPropertiesSettings, VariantSearchSettings } from '../../models/data-contracts'; import { PaginationBuilder } from '../paginationBuilder'; import { Settings } from '../settings'; import { FacetBuilder } from './facetBuilder'; import { ProductSortingBuilder } from './productSortingBuilder'; import { SearchBuilder } from './searchBuilder'; +import { SearchConstraintBuilder } from './searchConstraintBuilder'; import { SearchRequestBuilder } from './searchRequestBuilder'; export class ProductSearchBuilder extends SearchRequestBuilder implements SearchBuilder { @@ -11,6 +12,7 @@ export class ProductSearchBuilder extends SearchRequestBuilder implements Search private retailMediaQuery: RetailMediaQuery | null = null; private paginationBuilder: PaginationBuilder = new PaginationBuilder(); private sortingBuilder: ProductSortingBuilder = new ProductSortingBuilder(); + private searchConstraintBuilder: SearchConstraintBuilder = new SearchConstraintBuilder(); private term: string | null | undefined; private searchSettings: ProductSearchSettings = { @@ -104,6 +106,14 @@ export class ProductSearchBuilder extends SearchRequestBuilder implements Search return this; } + public searchConstraints(searchConstraintbuilder: (searchConstraintBuilder: SearchConstraintBuilder) => void): this { + searchConstraintbuilder(this.searchConstraintBuilder); + + this.searchSettings.resultConstraint = this.searchConstraintBuilder.build() + + return this; + } + public build(): ProductSearchRequest { const { take, skip } = this.paginationBuilder.build(); return { diff --git a/packages/client/src/builders/search/searchConstraintBuilder.ts b/packages/client/src/builders/search/searchConstraintBuilder.ts new file mode 100644 index 0000000..e797c70 --- /dev/null +++ b/packages/client/src/builders/search/searchConstraintBuilder.ts @@ -0,0 +1,19 @@ +import { ProductSearchResultConstraint, ResultMustHaveVariantConstraint } from 'src/models/data-contracts'; + +export class SearchConstraintBuilder { + private resultConstraint: ProductSearchResultConstraint | null = null; + + public setResultMustHaveVariantConstraint(constaint: { exceptWhenProductHasNoVariants: boolean }): this { + this.resultConstraint = { + $type: 'Relewise.Client.Requests.Search.Settings.ResultMustHaveVariantConstraint, Relewise.Client', + ...constaint, + } as ResultMustHaveVariantConstraint; + return this; + } + + build(): ResultMustHaveVariantConstraint | null { + // Do to how the data contracts are generated, resultsConstraints on searchSettings expect this specific type + // Once more types are added it will expect the generic type and this cast should be removed and the generic type should be returned + return this.resultConstraint as ResultMustHaveVariantConstraint | null; + } +} diff --git a/packages/client/tests/integration-tests/productSearch.integration.test.ts b/packages/client/tests/integration-tests/productSearch.integration.test.ts index ecf4efc..74c0f81 100644 --- a/packages/client/tests/integration-tests/productSearch.integration.test.ts +++ b/packages/client/tests/integration-tests/productSearch.integration.test.ts @@ -82,4 +82,15 @@ test('Facet result', async() => { } expect(result?.hits).toBeGreaterThan(0); -}); \ No newline at end of file +}); + +test('ProductSearch with search constraint', async() => { + + const request: ProductSearchRequest = baseProductBuilder() + .searchConstraints(constraints => constraints.setResultMustHaveVariantConstraint({ exceptWhenProductHasNoVariants: true })) + .build(); + + const result = await searcher.searchProducts(request); + + expect(result?.hits).toBeGreaterThan(0); +}); diff --git a/packages/client/tests/unit-tests/builders/search/productSearchBuilder.unit.test.ts b/packages/client/tests/unit-tests/builders/search/productSearchBuilder.unit.test.ts index f63cb2f..dc8439d 100644 --- a/packages/client/tests/unit-tests/builders/search/productSearchBuilder.unit.test.ts +++ b/packages/client/tests/unit-tests/builders/search/productSearchBuilder.unit.test.ts @@ -94,4 +94,14 @@ test('variantSearchSettings', () => { .build(); expect(subject.settings?.variantSettings?.excludeResultsWithoutVariant).toBe(true); +}); + +test('resultMustHaveVariantConstraint', () => { + const subject: ProductSearchRequest = baseBuilder() + .searchConstraints(s => s.setResultMustHaveVariantConstraint({ + exceptWhenProductHasNoVariants: true, + })) + .build(); + + expect(subject.settings?.resultConstraint?.exceptWhenProductHasNoVariants).toBe(true); }); \ No newline at end of file From e71b6a50b98f9124fc46e687b1afc149547f1e2f Mon Sep 17 00:00:00 2001 From: Simon Walenkamp Hansen Date: Mon, 12 Aug 2024 11:16:26 +0200 Subject: [PATCH 2/5] Export search constraint builder --- packages/client/src/builders/search/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/client/src/builders/search/index.ts b/packages/client/src/builders/search/index.ts index 45aecb3..cb68f74 100644 --- a/packages/client/src/builders/search/index.ts +++ b/packages/client/src/builders/search/index.ts @@ -13,4 +13,5 @@ export * from './searchTermPredictionBuilder'; export * from './dataObjectValueSelectorBuilder'; export * from './getProductFacet'; export * from './getContentFacet'; -export * from './getProductCategoryFacet'; \ No newline at end of file +export * from './getProductCategoryFacet'; +export * from './searchConstraintBuilder'; \ No newline at end of file From 255f12568f9ea6fe1b810aa81f9e5177e0f14304 Mon Sep 17 00:00:00 2001 From: Simon Walenkamp Hansen Date: Mon, 12 Aug 2024 11:18:11 +0200 Subject: [PATCH 3/5] Correct the import --- packages/client/src/builders/search/searchConstraintBuilder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/builders/search/searchConstraintBuilder.ts b/packages/client/src/builders/search/searchConstraintBuilder.ts index e797c70..ab5eec8 100644 --- a/packages/client/src/builders/search/searchConstraintBuilder.ts +++ b/packages/client/src/builders/search/searchConstraintBuilder.ts @@ -1,4 +1,4 @@ -import { ProductSearchResultConstraint, ResultMustHaveVariantConstraint } from 'src/models/data-contracts'; +import { ProductSearchResultConstraint, ResultMustHaveVariantConstraint } from '../../models/data-contracts'; export class SearchConstraintBuilder { private resultConstraint: ProductSearchResultConstraint | null = null; From 5deef241c16cab1eee18bf507d5f3cfbfa3f1b17 Mon Sep 17 00:00:00 2001 From: Simon Walenkamp Hansen Date: Mon, 12 Aug 2024 11:21:23 +0200 Subject: [PATCH 4/5] Review style comment --- packages/client/src/builders/search/productSearchBuilder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/builders/search/productSearchBuilder.ts b/packages/client/src/builders/search/productSearchBuilder.ts index 7741658..b934b50 100644 --- a/packages/client/src/builders/search/productSearchBuilder.ts +++ b/packages/client/src/builders/search/productSearchBuilder.ts @@ -109,7 +109,7 @@ export class ProductSearchBuilder extends SearchRequestBuilder implements Search public searchConstraints(searchConstraintbuilder: (searchConstraintBuilder: SearchConstraintBuilder) => void): this { searchConstraintbuilder(this.searchConstraintBuilder); - this.searchSettings.resultConstraint = this.searchConstraintBuilder.build() + this.searchSettings.resultConstraint = this.searchConstraintBuilder.build(); return this; } From c5264679c3b3b69a97c3ce56ee088eb9ff6e7f4e Mon Sep 17 00:00:00 2001 From: Simon Walenkamp Hansen Date: Mon, 12 Aug 2024 11:50:16 +0200 Subject: [PATCH 5/5] Review comment --- .../client/src/builders/search/searchConstraintBuilder.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/client/src/builders/search/searchConstraintBuilder.ts b/packages/client/src/builders/search/searchConstraintBuilder.ts index ab5eec8..fb1944d 100644 --- a/packages/client/src/builders/search/searchConstraintBuilder.ts +++ b/packages/client/src/builders/search/searchConstraintBuilder.ts @@ -4,10 +4,12 @@ export class SearchConstraintBuilder { private resultConstraint: ProductSearchResultConstraint | null = null; public setResultMustHaveVariantConstraint(constaint: { exceptWhenProductHasNoVariants: boolean }): this { - this.resultConstraint = { + const constraint: ResultMustHaveVariantConstraint = { $type: 'Relewise.Client.Requests.Search.Settings.ResultMustHaveVariantConstraint, Relewise.Client', ...constaint, - } as ResultMustHaveVariantConstraint; + }; + + this.resultConstraint = constraint; return this; }