@labdigital/commercetools-mock 2.46.0 → 2.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +568 -241
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +782 -58
- package/dist/index.d.ts +782 -58
- package/dist/index.js +556 -229
- package/dist/index.js.map +1 -1
- package/package.json +41 -48
- package/src/ctMock.ts +11 -13
- package/src/index.test.ts +5 -5
- package/src/lib/predicateParser.test.ts +62 -62
- package/src/lib/predicateParser.ts +32 -42
- package/src/lib/productSearchFilter.test.ts +18 -0
- package/src/lib/productSearchFilter.ts +7 -0
- package/src/lib/projectionSearchFilter.test.ts +17 -17
- package/src/lib/projectionSearchFilter.ts +2 -3
- package/src/oauth/server.test.ts +1 -1
- package/src/oauth/server.ts +11 -11
- package/src/priceSelector.ts +1 -1
- package/src/product-projection-search.ts +18 -19
- package/src/repositories/business-unit.ts +17 -16
- package/src/repositories/cart/actions.ts +32 -32
- package/src/repositories/cart/helpers.ts +1 -1
- package/src/repositories/cart/index.ts +8 -8
- package/src/repositories/cart-discount/actions.ts +1 -4
- package/src/repositories/category/actions.ts +2 -6
- package/src/repositories/custom-object.ts +20 -21
- package/src/repositories/customer/actions.ts +4 -4
- package/src/repositories/errors.ts +1 -1
- package/src/repositories/extension.ts +2 -1
- package/src/repositories/helpers.ts +27 -27
- package/src/repositories/index.ts +17 -17
- package/src/repositories/my-customer.ts +1 -1
- package/src/repositories/my-order.ts +2 -2
- package/src/repositories/order/index.ts +1 -1
- package/src/repositories/product/actions.ts +1 -1
- package/src/repositories/quote/actions.ts +83 -0
- package/src/repositories/quote/index.ts +54 -0
- package/src/repositories/quote-request/actions.ts +84 -0
- package/src/repositories/quote-request/index.test.ts +167 -0
- package/src/repositories/quote-request/index.ts +67 -0
- package/src/repositories/quote-staged/actions.ts +84 -0
- package/src/repositories/quote-staged/index.ts +47 -0
- package/src/repositories/review.ts +4 -4
- package/src/repositories/shipping-method/actions.ts +17 -17
- package/src/repositories/shipping-method/index.ts +6 -6
- package/src/repositories/shopping-list/actions.ts +1 -1
- package/src/repositories/shopping-list/index.ts +9 -1
- package/src/repositories/subscription.ts +2 -4
- package/src/server.ts +3 -2
- package/src/services/abstract.ts +7 -7
- package/src/services/as-associate-order.test.ts +1 -1
- package/src/services/cart-discount.test.ts +1 -1
- package/src/services/cart.test.ts +15 -15
- package/src/services/category.test.ts +1 -1
- package/src/services/customer.test.ts +4 -4
- package/src/services/customer.ts +1 -1
- package/src/services/index.ts +20 -14
- package/src/services/inventory-entry.test.ts +5 -5
- package/src/services/my-cart.test.ts +2 -2
- package/src/services/my-customer.test.ts +2 -2
- package/src/services/order.test.ts +8 -8
- package/src/services/product-projection.test.ts +5 -5
- package/src/services/product-projection.ts +12 -14
- package/src/services/product.test.ts +1 -1
- package/src/services/quote-request.test.ts +59 -0
- package/src/services/quote-request.ts +16 -0
- package/src/services/quote-staged.ts +16 -0
- package/src/services/quote.ts +16 -0
- package/src/services/standalone-price.test.ts +4 -4
- package/src/services/state.test.ts +1 -1
- package/src/services/store.test.ts +2 -2
- package/src/services/tax-category.test.ts +1 -1
- package/src/shipping.ts +3 -3
- package/src/storage/in-memory.ts +55 -63
- package/src/testing/customer.ts +1 -1
- package/src/types.ts +51 -31
- package/src/repositories/quote-request.ts +0 -17
- package/src/repositories/quote.ts +0 -14
- package/src/repositories/staged-quote.ts +0 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@labdigital/commercetools-mock",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.47.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Michael van Tellingen",
|
|
6
6
|
"type": "module",
|
|
@@ -19,54 +19,46 @@
|
|
|
19
19
|
"src"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"
|
|
23
|
-
"
|
|
22
|
+
"@biomejs/biome": "^1.9.4",
|
|
23
|
+
"basic-auth": "2.0.1",
|
|
24
|
+
"body-parser": "1.20.2",
|
|
24
25
|
"decimal.js": "10.4.3",
|
|
25
|
-
"deep-equal": "
|
|
26
|
-
"express": "
|
|
27
|
-
"light-my-request": "
|
|
28
|
-
"lodash.isequal": "
|
|
29
|
-
"morgan": "
|
|
30
|
-
"msw": "
|
|
31
|
-
"uuid": "
|
|
32
|
-
"zod": "
|
|
33
|
-
"zod-validation-error": "
|
|
26
|
+
"deep-equal": "2.2.3",
|
|
27
|
+
"express": "4.21.1",
|
|
28
|
+
"light-my-request": "5.11.1",
|
|
29
|
+
"lodash.isequal": "4.5.0",
|
|
30
|
+
"morgan": "1.10.0",
|
|
31
|
+
"msw": "2.5.0",
|
|
32
|
+
"uuid": "9.0.1",
|
|
33
|
+
"zod": "3.22.4",
|
|
34
|
+
"zod-validation-error": "3.0.2"
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
36
|
-
"@changesets/changelog-github": "
|
|
37
|
-
"@changesets/cli": "
|
|
38
|
-
"@commercetools/platform-sdk": "
|
|
39
|
-
"@
|
|
40
|
-
"@types/
|
|
41
|
-
"@types/
|
|
42
|
-
"@types/
|
|
43
|
-
"@types/express": "
|
|
44
|
-
"@types/
|
|
45
|
-
"@types/
|
|
46
|
-
"@types/
|
|
47
|
-
"@types/
|
|
48
|
-
"@types/
|
|
49
|
-
"@types/
|
|
50
|
-
"@types/uuid": "^9.0.8",
|
|
51
|
-
"@typescript-eslint/eslint-plugin": "^7.0.2",
|
|
52
|
-
"@typescript-eslint/parser": "^7.0.2",
|
|
37
|
+
"@changesets/changelog-github": "0.5.0",
|
|
38
|
+
"@changesets/cli": "2.27.1",
|
|
39
|
+
"@commercetools/platform-sdk": "8.8.0",
|
|
40
|
+
"@types/basic-auth": "1.1.8",
|
|
41
|
+
"@types/body-parser": "1.19.5",
|
|
42
|
+
"@types/deep-equal": "1.0.4",
|
|
43
|
+
"@types/express": "4.17.21",
|
|
44
|
+
"@types/express-serve-static-core": "4.17.43",
|
|
45
|
+
"@types/lodash.isequal": "4.5.8",
|
|
46
|
+
"@types/morgan": "1.9.9",
|
|
47
|
+
"@types/node": "20.16.14",
|
|
48
|
+
"@types/qs": "6.9.11",
|
|
49
|
+
"@types/supertest": "6.0.2",
|
|
50
|
+
"@types/uuid": "9.0.8",
|
|
53
51
|
"@vitest/coverage-v8": "3.0.2",
|
|
54
|
-
"esbuild": "
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"supertest": "^6.3.4",
|
|
65
|
-
"timekeeper": "^2.3.1",
|
|
66
|
-
"ts-node": "^10.9.2",
|
|
67
|
-
"tslib": "^2.8.0",
|
|
68
|
-
"tsup": "^8.0.2",
|
|
69
|
-
"typescript": "^5.6.3",
|
|
52
|
+
"esbuild": "0.20.1",
|
|
53
|
+
"fishery": "2.2.2",
|
|
54
|
+
"got": "14.2.0",
|
|
55
|
+
"husky": "9.0.11",
|
|
56
|
+
"supertest": "6.3.4",
|
|
57
|
+
"timekeeper": "2.3.1",
|
|
58
|
+
"ts-node": "10.9.2",
|
|
59
|
+
"tslib": "2.8.0",
|
|
60
|
+
"tsup": "8.0.2",
|
|
61
|
+
"typescript": "5.8.3",
|
|
70
62
|
"vitest": "3.0.2"
|
|
71
63
|
},
|
|
72
64
|
"engines": {
|
|
@@ -79,10 +71,11 @@
|
|
|
79
71
|
"scripts": {
|
|
80
72
|
"build": "tsup",
|
|
81
73
|
"build:server": "esbuild src/server.ts --bundle --outfile=dist/server.js --platform=node",
|
|
82
|
-
"check": "
|
|
83
|
-
"format": "
|
|
84
|
-
"lint": "
|
|
74
|
+
"check": "biome check && tsc",
|
|
75
|
+
"format": "biome format --fix",
|
|
76
|
+
"lint": "biome check",
|
|
85
77
|
"publish:ci": "pnpm build && pnpm changeset publish",
|
|
78
|
+
"publish:version": "pnpm changeset version && pnpm format",
|
|
86
79
|
"start": "tsup src/server.ts --watch --onSuccess 'node dist/server'",
|
|
87
80
|
"test": "vitest run",
|
|
88
81
|
"test:ci": "vitest run --coverage"
|
package/src/ctMock.ts
CHANGED
|
@@ -182,12 +182,11 @@ export class CommercetoolsMock {
|
|
|
182
182
|
message: err.message,
|
|
183
183
|
errors: [err.info],
|
|
184
184
|
});
|
|
185
|
-
} else {
|
|
186
|
-
console.error(err);
|
|
187
|
-
return resp.status(500).send({
|
|
188
|
-
error: err.message,
|
|
189
|
-
});
|
|
190
185
|
}
|
|
186
|
+
console.error(err);
|
|
187
|
+
return resp.status(500).send({
|
|
188
|
+
error: err.message,
|
|
189
|
+
});
|
|
191
190
|
});
|
|
192
191
|
|
|
193
192
|
return app;
|
|
@@ -210,7 +209,7 @@ export class CommercetoolsMock {
|
|
|
210
209
|
const headers = copyHeaders(request.headers);
|
|
211
210
|
|
|
212
211
|
const res = await inject(app)
|
|
213
|
-
.post(url.pathname
|
|
212
|
+
.post(`${url.pathname}?${url.searchParams.toString()}`)
|
|
214
213
|
.body(body)
|
|
215
214
|
.headers(headers)
|
|
216
215
|
.end();
|
|
@@ -225,7 +224,7 @@ export class CommercetoolsMock {
|
|
|
225
224
|
const headers = copyHeaders(request.headers);
|
|
226
225
|
|
|
227
226
|
const res = await inject(app)
|
|
228
|
-
.get(url.pathname
|
|
227
|
+
.get(`${url.pathname}?${url.searchParams.toString()}`)
|
|
229
228
|
.body(body)
|
|
230
229
|
.headers(headers)
|
|
231
230
|
.end();
|
|
@@ -256,7 +255,7 @@ export class CommercetoolsMock {
|
|
|
256
255
|
const headers = copyHeaders(request.headers);
|
|
257
256
|
|
|
258
257
|
const res = await inject(app)
|
|
259
|
-
.get(url.pathname
|
|
258
|
+
.get(`${url.pathname}?${url.searchParams.toString()}`)
|
|
260
259
|
.body(body)
|
|
261
260
|
.headers(headers)
|
|
262
261
|
.end();
|
|
@@ -271,7 +270,7 @@ export class CommercetoolsMock {
|
|
|
271
270
|
const headers = copyHeaders(request.headers);
|
|
272
271
|
|
|
273
272
|
const res = await inject(app)
|
|
274
|
-
.post(url.pathname
|
|
273
|
+
.post(`${url.pathname}?${url.searchParams.toString()}`)
|
|
275
274
|
.body(body)
|
|
276
275
|
.headers(headers)
|
|
277
276
|
.end();
|
|
@@ -286,7 +285,7 @@ export class CommercetoolsMock {
|
|
|
286
285
|
const headers = copyHeaders(request.headers);
|
|
287
286
|
|
|
288
287
|
const res = await inject(app)
|
|
289
|
-
.delete(url.pathname
|
|
288
|
+
.delete(`${url.pathname}?${url.searchParams.toString()}`)
|
|
290
289
|
.body(body)
|
|
291
290
|
.headers(headers)
|
|
292
291
|
.end();
|
|
@@ -307,10 +306,9 @@ export class CommercetoolsMock {
|
|
|
307
306
|
if (_globalListeners.length > 0) {
|
|
308
307
|
if (this._mswServer !== undefined) {
|
|
309
308
|
throw new Error("Server already started");
|
|
310
|
-
} else {
|
|
311
|
-
process.emitWarning("Server wasn't stopped properly, clearing");
|
|
312
|
-
_globalListeners.forEach((listener) => listener.close());
|
|
313
309
|
}
|
|
310
|
+
process.emitWarning("Server wasn't stopped properly, clearing");
|
|
311
|
+
_globalListeners.forEach((listener) => listener.close());
|
|
314
312
|
}
|
|
315
313
|
|
|
316
314
|
const server = setupServer();
|
package/src/index.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { InvalidTokenError } from "@commercetools/platform-sdk";
|
|
2
2
|
import got from "got";
|
|
3
3
|
import { setupServer } from "msw/node";
|
|
4
4
|
import { afterEach, beforeAll, expect, test } from "vitest";
|
|
@@ -23,12 +23,12 @@ test("node:fetch client", async () => {
|
|
|
23
23
|
});
|
|
24
24
|
ctMock.registerHandlers(mswServer);
|
|
25
25
|
|
|
26
|
-
const authHeader =
|
|
26
|
+
const authHeader = `Basic ${Buffer.from("foo:bar").toString("base64")}`;
|
|
27
27
|
let response = await fetch("https://localhost:8080/oauth/token", {
|
|
28
28
|
method: "POST",
|
|
29
29
|
headers: {
|
|
30
30
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
31
|
-
|
|
31
|
+
Authorization: authHeader,
|
|
32
32
|
},
|
|
33
33
|
body: new URLSearchParams({
|
|
34
34
|
grant_type: "client_credentials",
|
|
@@ -109,7 +109,7 @@ test("Options.validateCredentials: true (error)", async () => {
|
|
|
109
109
|
"https://api.europe-west1.gcp.commercetools.com/my-project/orders",
|
|
110
110
|
{
|
|
111
111
|
headers: {
|
|
112
|
-
Authorization:
|
|
112
|
+
Authorization: "Bearer foobar",
|
|
113
113
|
},
|
|
114
114
|
responseType: "json",
|
|
115
115
|
throwHttpErrors: false,
|
|
@@ -130,7 +130,7 @@ test("Options.validateCredentials: false", async () => {
|
|
|
130
130
|
"https://api.europe-west1.gcp.commercetools.com/my-project/orders",
|
|
131
131
|
{
|
|
132
132
|
headers: {
|
|
133
|
-
Authorization:
|
|
133
|
+
Authorization: "Bearer foobar",
|
|
134
134
|
},
|
|
135
135
|
responseType: "json",
|
|
136
136
|
},
|
|
@@ -13,8 +13,8 @@ describe("Predicate filter", () => {
|
|
|
13
13
|
nested: {
|
|
14
14
|
numberProperty: 1234,
|
|
15
15
|
objectProperty: {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
stringProperty: "foobar",
|
|
17
|
+
booleanProperty: true,
|
|
18
18
|
"45c652f2-76e8-48fd-ab64-d11ad99d6631": {
|
|
19
19
|
stringProperty: "foobar",
|
|
20
20
|
uuidProperty: "3a57cc78-db08-4cd3-b778-d59b3326c435",
|
|
@@ -95,60 +95,60 @@ describe("Predicate filter", () => {
|
|
|
95
95
|
expect(match(`stringProperty="foobar"`)).toBeTruthy();
|
|
96
96
|
expect(match(`stringProperty!="foobar"`)).toBeFalsy();
|
|
97
97
|
|
|
98
|
-
expect(match(
|
|
98
|
+
expect(match("stringProperty=:val", { val: "foobar" })).toBeTruthy();
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
test("booleanProperty = true", async () => {
|
|
102
|
-
expect(match(
|
|
103
|
-
expect(match(
|
|
102
|
+
expect(match("booleanProperty != true")).toBeFalsy();
|
|
103
|
+
expect(match("booleanProperty = true")).toBeTruthy();
|
|
104
104
|
|
|
105
|
-
expect(match(
|
|
105
|
+
expect(match("booleanProperty=:val", { val: true })).toBeTruthy();
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
test('stringProperty matches ignore case "foobar"', async () => {
|
|
109
109
|
expect(match(`stringProperty="FOObar"`)).toBeFalsy();
|
|
110
110
|
expect(match(`stringProperty matches ignore case "FOObar"`)).toBeTruthy();
|
|
111
111
|
expect(
|
|
112
|
-
match(
|
|
112
|
+
match("stringProperty matches ignore case :val", { val: "fooBar" }),
|
|
113
113
|
).toBeTruthy();
|
|
114
114
|
});
|
|
115
115
|
|
|
116
116
|
test("numberProperty = 1234", async () => {
|
|
117
|
-
expect(match(
|
|
118
|
-
expect(match(
|
|
119
|
-
expect(match(
|
|
120
|
-
expect(match(
|
|
117
|
+
expect(match("numberProperty=1234")).toBeTruthy();
|
|
118
|
+
expect(match("numberProperty = 1234")).toBeTruthy();
|
|
119
|
+
expect(match("numberProperty=1230")).toBeFalsy();
|
|
120
|
+
expect(match("numberProperty = 1230")).toBeFalsy();
|
|
121
121
|
|
|
122
|
-
expect(match(
|
|
122
|
+
expect(match("numberProperty=:val", { val: 1234 })).toBeTruthy();
|
|
123
123
|
});
|
|
124
124
|
|
|
125
125
|
test("numberProperty > ...", async () => {
|
|
126
|
-
expect(match(
|
|
127
|
-
expect(match(
|
|
126
|
+
expect(match("numberProperty > 1233")).toBeTruthy();
|
|
127
|
+
expect(match("numberProperty > 1234")).toBeFalsy();
|
|
128
128
|
});
|
|
129
129
|
|
|
130
130
|
test("numberProperty >= ...", async () => {
|
|
131
|
-
expect(match(
|
|
132
|
-
expect(match(
|
|
131
|
+
expect(match("numberProperty >= 1234")).toBeTruthy();
|
|
132
|
+
expect(match("numberProperty >= 1235")).toBeFalsy();
|
|
133
133
|
});
|
|
134
134
|
|
|
135
135
|
test("numberProperty < ...", async () => {
|
|
136
|
-
expect(match(
|
|
137
|
-
expect(match(
|
|
136
|
+
expect(match("numberProperty < 1235")).toBeTruthy();
|
|
137
|
+
expect(match("numberProperty < 1234")).toBeFalsy();
|
|
138
138
|
});
|
|
139
139
|
|
|
140
140
|
test("numberProperty <= ...", async () => {
|
|
141
|
-
expect(match(
|
|
142
|
-
expect(match(
|
|
143
|
-
expect(match(
|
|
141
|
+
expect(match("numberProperty <= 1235")).toBeTruthy();
|
|
142
|
+
expect(match("numberProperty <= 1234")).toBeTruthy();
|
|
143
|
+
expect(match("numberProperty <= 1233")).toBeFalsy();
|
|
144
144
|
});
|
|
145
145
|
|
|
146
146
|
test("numberPropery in (...)", async () => {
|
|
147
|
-
expect(match(
|
|
147
|
+
expect(match("numberProperty in (1233, 1234, 1235)")).toBeTruthy();
|
|
148
148
|
});
|
|
149
149
|
|
|
150
150
|
test("numberPropery in (...) single value", async () => {
|
|
151
|
-
expect(match(
|
|
151
|
+
expect(match("numberProperty in (1234)")).toBeTruthy();
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
test("arrayProperty contains all (...)", async () => {
|
|
@@ -159,17 +159,17 @@ describe("Predicate filter", () => {
|
|
|
159
159
|
});
|
|
160
160
|
|
|
161
161
|
test("arrayProperty is empty", async () => {
|
|
162
|
-
expect(match(
|
|
163
|
-
expect(match(
|
|
164
|
-
expect(match(
|
|
162
|
+
expect(match("arrayProperty is empty")).toBeFalsy();
|
|
163
|
+
expect(match("arrayProperty is not empty")).toBeTruthy();
|
|
164
|
+
expect(match("emptyArrayProperty is empty")).toBeTruthy();
|
|
165
165
|
});
|
|
166
166
|
|
|
167
167
|
test("property is defined", async () => {
|
|
168
|
-
expect(match(
|
|
169
|
-
expect(match(
|
|
168
|
+
expect(match("notDefined is defined")).toBeFalsy();
|
|
169
|
+
expect(match("notDefined is not defined")).toBeTruthy();
|
|
170
170
|
|
|
171
|
-
expect(match(
|
|
172
|
-
expect(match(
|
|
171
|
+
expect(match("arrayProperty is defined")).toBeTruthy();
|
|
172
|
+
expect(match("arrayProperty is not defined")).toBeFalsy();
|
|
173
173
|
});
|
|
174
174
|
|
|
175
175
|
test("arrayProperty contains any (...)", async () => {
|
|
@@ -186,14 +186,14 @@ describe("Predicate filter", () => {
|
|
|
186
186
|
expect(match(`nested(array(stringProperty="foobar"))`)).toBeFalsy();
|
|
187
187
|
|
|
188
188
|
// Different comparison operators
|
|
189
|
-
expect(match(
|
|
190
|
-
expect(match(
|
|
191
|
-
expect(match(
|
|
192
|
-
expect(match(
|
|
193
|
-
expect(match(
|
|
194
|
-
expect(match(
|
|
195
|
-
expect(match(
|
|
196
|
-
expect(match(
|
|
189
|
+
expect(match("nested(array(numberProperty>=2345))")).toBeTruthy();
|
|
190
|
+
expect(match("nested(array(numberProperty>=2346))")).toBeFalsy();
|
|
191
|
+
expect(match("nested(array(numberProperty>2344))")).toBeTruthy();
|
|
192
|
+
expect(match("nested(array(numberProperty>2345))")).toBeFalsy();
|
|
193
|
+
expect(match("nested(array(numberProperty<=1234))")).toBeTruthy();
|
|
194
|
+
expect(match("nested(array(numberProperty<=1233))")).toBeFalsy();
|
|
195
|
+
expect(match("nested(array(numberProperty<1235))")).toBeTruthy();
|
|
196
|
+
expect(match("nested(array(numberProperty<1234))")).toBeFalsy();
|
|
197
197
|
|
|
198
198
|
// One level deeper
|
|
199
199
|
expect(
|
|
@@ -246,57 +246,57 @@ describe("Predicate filter", () => {
|
|
|
246
246
|
test("geolocation within circle (...)", async () => {
|
|
247
247
|
expect(
|
|
248
248
|
match(
|
|
249
|
-
|
|
249
|
+
"geoLocation within circle(5.121310867198959, 52.09068804569714, 2500)",
|
|
250
250
|
),
|
|
251
251
|
).toBeTruthy();
|
|
252
252
|
expect(
|
|
253
253
|
match(
|
|
254
|
-
|
|
254
|
+
"geoLocation within circle(5.121310867198959, 52.09068804569714, 2400)",
|
|
255
255
|
),
|
|
256
256
|
).toBeFalsy();
|
|
257
257
|
});
|
|
258
258
|
|
|
259
259
|
test("negate any other conditional expression", async () => {
|
|
260
|
-
expect(match(
|
|
261
|
-
expect(match(
|
|
262
|
-
expect(match(
|
|
263
|
-
expect(match(
|
|
264
|
-
|
|
265
|
-
expect(match(
|
|
266
|
-
expect(match(
|
|
267
|
-
expect(match(
|
|
260
|
+
expect(match("numberProperty = 1234")).toBeTruthy();
|
|
261
|
+
expect(match("not (numberProperty = 1234)")).toBeFalsy();
|
|
262
|
+
expect(match("not (numberProperty = 1235)")).toBeTruthy();
|
|
263
|
+
expect(match("not (numberProperty = 1235)")).toBeTruthy();
|
|
264
|
+
|
|
265
|
+
expect(match("nested(numberProperty=1234))")).toBeTruthy();
|
|
266
|
+
expect(match("nested(not(numberProperty=1230)))")).toBeTruthy();
|
|
267
|
+
expect(match("nested(not(numberProperty=1234)))")).toBeFalsy();
|
|
268
268
|
});
|
|
269
269
|
|
|
270
270
|
test("and clause (implicit)", async () => {
|
|
271
271
|
expect(
|
|
272
|
-
match([`stringProperty="foobar"`,
|
|
272
|
+
match([`stringProperty="foobar"`, "numberProperty=1234"]),
|
|
273
273
|
).toBeTruthy();
|
|
274
274
|
|
|
275
275
|
expect(
|
|
276
|
-
match([`stringProperty="foobar"`,
|
|
276
|
+
match([`stringProperty="foobar"`, "numberProperty=1111"]),
|
|
277
277
|
).toBeFalsy();
|
|
278
278
|
});
|
|
279
279
|
|
|
280
280
|
test("and clause (explicit)", async () => {
|
|
281
|
-
expect(match(
|
|
282
|
-
expect(match(
|
|
281
|
+
expect(match("numberProperty>1233 and numberProperty<1235")).toBeTruthy();
|
|
282
|
+
expect(match("numberProperty>1233 and numberProperty<1234")).toBeFalsy();
|
|
283
283
|
});
|
|
284
284
|
|
|
285
285
|
test("or clause", async () => {
|
|
286
286
|
expect(
|
|
287
287
|
match(
|
|
288
|
-
|
|
288
|
+
"numberProperty=1231 or numberProperty>54312 or numberProperty=1234",
|
|
289
289
|
),
|
|
290
290
|
).toBeTruthy();
|
|
291
|
-
expect(match(
|
|
292
|
-
expect(match(
|
|
293
|
-
expect(match(
|
|
291
|
+
expect(match("numberProperty=1231 or numberProperty=1234")).toBeTruthy();
|
|
292
|
+
expect(match("numberProperty=1231 or (numberProperty=1234)")).toBeTruthy();
|
|
293
|
+
expect(match("numberProperty=1233 or numberProperty=1235")).toBeFalsy();
|
|
294
294
|
});
|
|
295
295
|
|
|
296
296
|
test("or / and clause mixed", async () => {
|
|
297
297
|
expect(
|
|
298
298
|
match(
|
|
299
|
-
|
|
299
|
+
"numberProperty=1234 and (numberProperty=1230 or (numberProperty=1234 or numberProperty=1235))",
|
|
300
300
|
),
|
|
301
301
|
).toBeTruthy();
|
|
302
302
|
});
|
|
@@ -308,10 +308,10 @@ describe("Predicate filter", () => {
|
|
|
308
308
|
|
|
309
309
|
test("nested attribute access", async () => {
|
|
310
310
|
expect(
|
|
311
|
-
match(
|
|
311
|
+
match("nested(objectProperty(booleanProperty != true))"),
|
|
312
312
|
).toBeFalsy();
|
|
313
313
|
expect(
|
|
314
|
-
match(
|
|
314
|
+
match("nested(objectProperty(booleanProperty != false))"),
|
|
315
315
|
).toBeTruthy();
|
|
316
316
|
});
|
|
317
317
|
|
|
@@ -329,11 +329,11 @@ describe("Predicate filter", () => {
|
|
|
329
329
|
// })
|
|
330
330
|
|
|
331
331
|
test("invalid predicate", async () => {
|
|
332
|
-
expect(() => match(
|
|
333
|
-
expect(() => match(
|
|
332
|
+
expect(() => match("stringProperty=nomatch")).toThrow(PredicateError);
|
|
333
|
+
expect(() => match("stringProperty=nomatch")).toThrow(
|
|
334
334
|
"Invalid input 'n', expected input parameter or primitive value (line 1, column 16)",
|
|
335
335
|
);
|
|
336
|
-
expect(() => match(
|
|
336
|
+
expect(() => match("stringProperty")).toThrow(PredicateError);
|
|
337
337
|
});
|
|
338
338
|
|
|
339
339
|
test("uuid as field name", async () => {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* See https://docs.commercetools.com/api/predicates/query
|
|
6
6
|
*/
|
|
7
7
|
import { haversineDistance } from "./haversine";
|
|
8
|
-
import { Lexer, Parser
|
|
8
|
+
import { type ITokenPosition, Lexer, Parser } from "./parser";
|
|
9
9
|
|
|
10
10
|
export class PredicateError {
|
|
11
11
|
message: string;
|
|
@@ -34,10 +34,9 @@ export const matchesPredicate = (
|
|
|
34
34
|
const func = generateMatchFunc(item);
|
|
35
35
|
return func(target, variables ?? {});
|
|
36
36
|
});
|
|
37
|
-
} else {
|
|
38
|
-
const func = generateMatchFunc(predicate);
|
|
39
|
-
return func(target, variables ?? {});
|
|
40
37
|
}
|
|
38
|
+
const func = generateMatchFunc(predicate);
|
|
39
|
+
return func(target, variables ?? {});
|
|
41
40
|
};
|
|
42
41
|
|
|
43
42
|
export const parseQueryExpression = (
|
|
@@ -47,9 +46,8 @@ export const parseQueryExpression = (
|
|
|
47
46
|
const callbacks = predicate.map((item) => generateMatchFunc(item));
|
|
48
47
|
return (target: any, variables: VariableMap) =>
|
|
49
48
|
callbacks.every((callback) => callback(target, variables));
|
|
50
|
-
} else {
|
|
51
|
-
return generateMatchFunc(predicate);
|
|
52
49
|
}
|
|
50
|
+
return generateMatchFunc(predicate);
|
|
53
51
|
};
|
|
54
52
|
|
|
55
53
|
type TypeSymbol = {
|
|
@@ -177,7 +175,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
177
175
|
(t) =>
|
|
178
176
|
({
|
|
179
177
|
type: "boolean",
|
|
180
|
-
value: t.token.match === "true"
|
|
178
|
+
value: t.token.match === "true",
|
|
181
179
|
pos: t.token.strpos(),
|
|
182
180
|
}) as TypeSymbol,
|
|
183
181
|
)
|
|
@@ -209,7 +207,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
209
207
|
(t) =>
|
|
210
208
|
({
|
|
211
209
|
type: "int",
|
|
212
|
-
value: parseInt(t.token.match, 10),
|
|
210
|
+
value: Number.parseInt(t.token.match, 10),
|
|
213
211
|
pos: t.token.strpos(),
|
|
214
212
|
}) as TypeSymbol,
|
|
215
213
|
)
|
|
@@ -219,7 +217,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
219
217
|
(t) =>
|
|
220
218
|
({
|
|
221
219
|
type: "float",
|
|
222
|
-
value: parseFloat(t.token.match),
|
|
220
|
+
value: Number.parseFloat(t.token.match),
|
|
223
221
|
pos: t.token.strpos(),
|
|
224
222
|
}) as TypeSymbol,
|
|
225
223
|
)
|
|
@@ -242,9 +240,8 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
242
240
|
const expr: any = parser.parse({ terminals: [bp - 1] });
|
|
243
241
|
if (Array.isArray(expr)) {
|
|
244
242
|
return [left, ...expr];
|
|
245
|
-
} else {
|
|
246
|
-
return [left, expr];
|
|
247
243
|
}
|
|
244
|
+
return [left, expr];
|
|
248
245
|
})
|
|
249
246
|
.nud("(", 100, (t) => {
|
|
250
247
|
const expr: any = parser.parse({ terminals: [")"] });
|
|
@@ -262,17 +259,16 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
262
259
|
}
|
|
263
260
|
return false;
|
|
264
261
|
});
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return expr(value, vars);
|
|
262
|
+
}
|
|
263
|
+
const value = resolveValue(obj, left);
|
|
264
|
+
if (value) {
|
|
265
|
+
if (Array.isArray(value)) {
|
|
266
|
+
return value.some((item) => expr(item, vars));
|
|
273
267
|
}
|
|
274
|
-
|
|
268
|
+
|
|
269
|
+
return expr(value, vars);
|
|
275
270
|
}
|
|
271
|
+
return false;
|
|
276
272
|
};
|
|
277
273
|
})
|
|
278
274
|
.bp(")", 0)
|
|
@@ -290,14 +286,13 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
290
286
|
}
|
|
291
287
|
return value === other;
|
|
292
288
|
});
|
|
293
|
-
} else {
|
|
294
|
-
const resolvedValue = resolveValue(obj, left);
|
|
295
|
-
const resolvedSymbol = resolveSymbol(expr, vars);
|
|
296
|
-
if (Array.isArray(resolvedValue)) {
|
|
297
|
-
return !!resolvedValue.some((elem) => elem === resolvedSymbol);
|
|
298
|
-
}
|
|
299
|
-
return resolvedValue === resolvedSymbol;
|
|
300
289
|
}
|
|
290
|
+
const resolvedValue = resolveValue(obj, left);
|
|
291
|
+
const resolvedSymbol = resolveSymbol(expr, vars);
|
|
292
|
+
if (Array.isArray(resolvedValue)) {
|
|
293
|
+
return !!resolvedValue.some((elem) => elem === resolvedSymbol);
|
|
294
|
+
}
|
|
295
|
+
return resolvedValue === resolvedSymbol;
|
|
301
296
|
};
|
|
302
297
|
})
|
|
303
298
|
.led("!=", 20, ({ left, bp }) => {
|
|
@@ -353,12 +348,11 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
353
348
|
const val = resolveValue(obj, left);
|
|
354
349
|
return val.length === 0;
|
|
355
350
|
};
|
|
356
|
-
} else {
|
|
357
|
-
return (obj: any, vars: VariableMap) => {
|
|
358
|
-
const val = resolveValue(obj, left);
|
|
359
|
-
return val.length !== 0;
|
|
360
|
-
};
|
|
361
351
|
}
|
|
352
|
+
return (obj: any, vars: VariableMap) => {
|
|
353
|
+
const val = resolveValue(obj, left);
|
|
354
|
+
return val.length !== 0;
|
|
355
|
+
};
|
|
362
356
|
}
|
|
363
357
|
case "defined": {
|
|
364
358
|
if (!invert) {
|
|
@@ -366,12 +360,11 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
366
360
|
const val = resolveValue(obj, left);
|
|
367
361
|
return val !== undefined;
|
|
368
362
|
};
|
|
369
|
-
} else {
|
|
370
|
-
return (obj: any, vars: VariableMap) => {
|
|
371
|
-
const val = resolveValue(obj, left);
|
|
372
|
-
return val === undefined;
|
|
373
|
-
};
|
|
374
363
|
}
|
|
364
|
+
return (obj: any, vars: VariableMap) => {
|
|
365
|
+
const val = resolveValue(obj, left);
|
|
366
|
+
return val === undefined;
|
|
367
|
+
};
|
|
375
368
|
}
|
|
376
369
|
default: {
|
|
377
370
|
throw new Error("Unexpected");
|
|
@@ -463,9 +456,8 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
463
456
|
const array = expr.map((item: TypeSymbol) => resolveSymbol(item, vars));
|
|
464
457
|
if (keyword.type === "ALL") {
|
|
465
458
|
return array.every((item: any) => value.includes(item));
|
|
466
|
-
} else {
|
|
467
|
-
return array.some((item: any) => value.includes(item));
|
|
468
459
|
}
|
|
460
|
+
return array.some((item: any) => value.includes(item));
|
|
469
461
|
};
|
|
470
462
|
})
|
|
471
463
|
|
|
@@ -478,9 +470,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
478
470
|
const column = lines[lines.length - 1].length;
|
|
479
471
|
|
|
480
472
|
throw new PredicateError(
|
|
481
|
-
`Unexpected end of input, expected SphereIdentifierChar, comparison
|
|
482
|
-
`operator, not, in, contains, is, within or matches` +
|
|
483
|
-
` (line ${lines.length}, column ${column})`,
|
|
473
|
+
`Unexpected end of input, expected SphereIdentifierChar, comparison operator, not, in, contains, is, within or matches (line ${lines.length}, column ${column})`,
|
|
484
474
|
);
|
|
485
475
|
}
|
|
486
476
|
return result;
|
|
@@ -138,6 +138,24 @@ describe("Product search filter", () => {
|
|
|
138
138
|
},
|
|
139
139
|
}).isMatch,
|
|
140
140
|
).toBeTruthy();
|
|
141
|
+
|
|
142
|
+
expect(
|
|
143
|
+
match({
|
|
144
|
+
exact: {
|
|
145
|
+
field: "variants.sku",
|
|
146
|
+
values: ["MYSKU", "OTHER"],
|
|
147
|
+
},
|
|
148
|
+
}).isMatch,
|
|
149
|
+
).toBeTruthy();
|
|
150
|
+
|
|
151
|
+
expect(
|
|
152
|
+
match({
|
|
153
|
+
exact: {
|
|
154
|
+
field: "variants.sku",
|
|
155
|
+
values: ["OTHER"],
|
|
156
|
+
},
|
|
157
|
+
}).isMatch,
|
|
158
|
+
).toBeFalsy();
|
|
141
159
|
});
|
|
142
160
|
|
|
143
161
|
test("by attribute value", async () => {
|