From 05e338e8d7425c1668fe1f0ea91f6cbcf7ec31e8 Mon Sep 17 00:00:00 2001 From: Bram Kaashoek Date: Wed, 13 Aug 2025 16:02:48 +0200 Subject: [PATCH 1/2] fix: master variant predicates and AND predicates --- .changeset/green-queens-rule.md | 5 +++++ src/lib/predicateParser.ts | 7 ++++++- src/services/product-projection.test.ts | 27 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 .changeset/green-queens-rule.md diff --git a/.changeset/green-queens-rule.md b/.changeset/green-queens-rule.md new file mode 100644 index 00000000..406cee63 --- /dev/null +++ b/.changeset/green-queens-rule.md @@ -0,0 +1,5 @@ +--- +"@labdigital/commercetools-mock": patch +--- + +Fixes a bug where main variants were not included in where predicates. Fixes a bug where vars were not read in predicates with AND statements diff --git a/src/lib/predicateParser.ts b/src/lib/predicateParser.ts index 77276d4a..7b80745c 100644 --- a/src/lib/predicateParser.ts +++ b/src/lib/predicateParser.ts @@ -88,6 +88,11 @@ const resolveValue = (obj: any, val: TypeSymbol): any => { throw new PredicateError("Internal error"); } + // variants() includes both masterVariant and variants for predicates + if (val.value === "variants" && obj.masterVariant && obj.variants !== undefined) { + return [obj.masterVariant, ...(obj.variants ?? [])]; + } + if (!(val.value in obj)) { if (Array.isArray(obj)) { return Object.values(obj) @@ -230,7 +235,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => { .led("AND", 5, ({ left, bp }) => { const expr = parser.parse({ terminals: [bp - 1] }); - return (obj: any) => left(obj) && expr(obj); + return (obj: any, vars: object) => left(obj, vars) && expr(obj, vars); }) .led("OR", 5, ({ left, token, bp }) => { const expr = parser.parse({ terminals: [bp - 1] }); diff --git a/src/services/product-projection.test.ts b/src/services/product-projection.test.ts index 08ac12af..ba15477b 100644 --- a/src/services/product-projection.test.ts +++ b/src/services/product-projection.test.ts @@ -97,6 +97,10 @@ beforeEach(async () => { name: "number", value: 4 as any, }, + { + name: "store", + value: ["test-store"] + }, ], }, variants: [ @@ -252,6 +256,29 @@ describe("Product Projection Query - Generic", () => { } }); + + test("Filter on complex query", async () => { + { + const response = await supertest(ctMock.app) + .get("/dummy/product-projections") + .query({ + limit: 50, + where: ['slug(nl-NL=:slug) and variants(attributes(name="store" and value="test-store"))'], + "var.slug": "test-product", + "var.store": "test-store" + }); + + const result: ProductProjectionPagedSearchResponse = response.body; + expect(result).toEqual({ + count: 1, + limit: 50, + offset: 0, + total: 1, + results: [productProjection], + }); + } + }); + test("Filter on invalid slug", async () => { { const response = await supertest(ctMock.app) From e896c90f3c12022eed5cfc18238a5fd6b1658a04 Mon Sep 17 00:00:00 2001 From: Bram Kaashoek Date: Wed, 13 Aug 2025 16:38:33 +0200 Subject: [PATCH 2/2] fix: formatting --- src/lib/predicateParser.ts | 6 +++++- src/services/product-projection.test.ts | 9 +++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/lib/predicateParser.ts b/src/lib/predicateParser.ts index 7b80745c..624e4b2d 100644 --- a/src/lib/predicateParser.ts +++ b/src/lib/predicateParser.ts @@ -89,7 +89,11 @@ const resolveValue = (obj: any, val: TypeSymbol): any => { } // variants() includes both masterVariant and variants for predicates - if (val.value === "variants" && obj.masterVariant && obj.variants !== undefined) { + if ( + val.value === "variants" && + obj.masterVariant && + obj.variants !== undefined + ) { return [obj.masterVariant, ...(obj.variants ?? [])]; } diff --git a/src/services/product-projection.test.ts b/src/services/product-projection.test.ts index ba15477b..f8a99b5d 100644 --- a/src/services/product-projection.test.ts +++ b/src/services/product-projection.test.ts @@ -99,7 +99,7 @@ beforeEach(async () => { }, { name: "store", - value: ["test-store"] + value: ["test-store"], }, ], }, @@ -256,16 +256,17 @@ describe("Product Projection Query - Generic", () => { } }); - test("Filter on complex query", async () => { { const response = await supertest(ctMock.app) .get("/dummy/product-projections") .query({ limit: 50, - where: ['slug(nl-NL=:slug) and variants(attributes(name="store" and value="test-store"))'], + where: [ + 'slug(nl-NL=:slug) and variants(attributes(name="store" and value="test-store"))', + ], "var.slug": "test-product", - "var.store": "test-store" + "var.store": "test-store", }); const result: ProductProjectionPagedSearchResponse = response.body;