@labdigital/commercetools-mock 2.66.0 → 3.0.0-beta.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/README.md +31 -8
- package/dist/abstract-BKFcva6S.mjs +1044 -0
- package/dist/abstract-BKFcva6S.mjs.map +1 -0
- package/dist/config-BcNSzPZz.d.mts +1718 -0
- package/dist/index.d.mts +50 -1633
- package/dist/index.mjs +3769 -2653
- package/dist/index.mjs.map +1 -1
- package/dist/storage/sqlite.d.mts +59 -0
- package/dist/storage/sqlite.mjs +234 -0
- package/dist/storage/sqlite.mjs.map +1 -0
- package/package.json +26 -29
- package/src/ctMock.ts +125 -136
- package/src/helpers.ts +14 -6
- package/src/index.ts +5 -0
- package/src/lib/masking.ts +4 -5
- package/src/lib/product-review-statistics.test.ts +257 -294
- package/src/lib/review-statistics.ts +17 -4
- package/src/oauth/helpers.ts +7 -4
- package/src/oauth/server.test.ts +102 -62
- package/src/oauth/server.ts +215 -213
- package/src/oauth/store.ts +20 -6
- package/src/orderSearch.ts +3 -3
- package/src/product-projection-search.ts +38 -20
- package/src/product-search-availability.test.ts +31 -52
- package/src/product-search.ts +19 -10
- package/src/projectAPI.ts +6 -22
- package/src/repositories/abstract.ts +182 -48
- package/src/repositories/as-associate.test.ts +19 -19
- package/src/repositories/associate-role.ts +12 -23
- package/src/repositories/attribute-group.test.ts +23 -23
- package/src/repositories/attribute-group.ts +6 -4
- package/src/repositories/business-unit.test.ts +63 -57
- package/src/repositories/business-unit.ts +107 -55
- package/src/repositories/cart/actions.ts +96 -65
- package/src/repositories/cart/helpers.ts +15 -11
- package/src/repositories/cart/index.test.ts +136 -30
- package/src/repositories/cart/index.ts +76 -59
- package/src/repositories/cart-discount/actions.ts +12 -44
- package/src/repositories/cart-discount/index.ts +20 -8
- package/src/repositories/category/actions.ts +27 -27
- package/src/repositories/category/index.test.ts +13 -9
- package/src/repositories/category/index.ts +40 -23
- package/src/repositories/channel.test.ts +53 -51
- package/src/repositories/channel.ts +12 -22
- package/src/repositories/custom-object.ts +34 -25
- package/src/repositories/customer/actions.ts +47 -25
- package/src/repositories/customer/index.test.ts +11 -11
- package/src/repositories/customer/index.ts +65 -35
- package/src/repositories/customer-group.test.ts +44 -42
- package/src/repositories/customer-group.ts +12 -22
- package/src/repositories/discount-code/actions.ts +3 -19
- package/src/repositories/discount-code/index.ts +9 -4
- package/src/repositories/discount-group/index.ts +8 -3
- package/src/repositories/extension.test.ts +27 -27
- package/src/repositories/extension.ts +10 -5
- package/src/repositories/helpers.ts +126 -47
- package/src/repositories/inventory-entry/actions.ts +3 -24
- package/src/repositories/inventory-entry/index.ts +19 -11
- package/src/repositories/my-customer.ts +13 -12
- package/src/repositories/my-order.ts +5 -2
- package/src/repositories/order/actions.ts +84 -56
- package/src/repositories/order/index.test.ts +36 -31
- package/src/repositories/order/index.ts +83 -49
- package/src/repositories/order-edit.ts +8 -3
- package/src/repositories/payment/actions.ts +64 -44
- package/src/repositories/payment/helpers.ts +3 -3
- package/src/repositories/payment/index.ts +28 -12
- package/src/repositories/product/actions.ts +133 -98
- package/src/repositories/product/helpers.ts +29 -16
- package/src/repositories/product/index.ts +42 -25
- package/src/repositories/product-discount.ts +6 -4
- package/src/repositories/product-projection.ts +41 -21
- package/src/repositories/product-selection.ts +8 -15
- package/src/repositories/product-tailoring.ts +22 -3
- package/src/repositories/product-type.ts +45 -4
- package/src/repositories/project.ts +57 -13
- package/src/repositories/quote/actions.ts +5 -28
- package/src/repositories/quote/index.ts +29 -6
- package/src/repositories/quote-request/actions.ts +5 -28
- package/src/repositories/quote-request/index.test.ts +3 -3
- package/src/repositories/quote-request/index.ts +31 -11
- package/src/repositories/quote-staged/actions.ts +5 -28
- package/src/repositories/quote-staged/index.ts +22 -8
- package/src/repositories/recurrence-policy/index.ts +6 -4
- package/src/repositories/recurring-order/actions.ts +7 -32
- package/src/repositories/recurring-order/index.ts +8 -6
- package/src/repositories/review.test.ts +147 -142
- package/src/repositories/review.ts +31 -37
- package/src/repositories/shipping-method/actions.ts +11 -28
- package/src/repositories/shipping-method/index.ts +26 -15
- package/src/repositories/shopping-list/actions.ts +21 -31
- package/src/repositories/shopping-list/index.ts +44 -22
- package/src/repositories/standalone-price.ts +6 -4
- package/src/repositories/state.ts +15 -9
- package/src/repositories/store.ts +21 -32
- package/src/repositories/subscription.test.ts +22 -22
- package/src/repositories/subscription.ts +8 -3
- package/src/repositories/tax-category/index.ts +8 -3
- package/src/repositories/type/actions.ts +21 -3
- package/src/repositories/type/index.ts +5 -3
- package/src/repositories/zone.test.ts +112 -77
- package/src/repositories/zone.ts +5 -3
- package/src/schemas/generated/associate-role.ts +13 -0
- package/src/schemas/generated/attribute-group.ts +12 -0
- package/src/schemas/generated/business-unit.ts +38 -0
- package/src/schemas/generated/cart-discount.ts +33 -0
- package/src/schemas/generated/cart.ts +61 -0
- package/src/schemas/generated/category.ts +25 -0
- package/src/schemas/generated/channel.ts +21 -0
- package/src/schemas/generated/common.ts +1372 -0
- package/src/schemas/generated/custom-object.ts +11 -0
- package/src/schemas/generated/customer-group.ts +11 -0
- package/src/schemas/generated/customer.ts +47 -0
- package/src/schemas/generated/discount-code.ts +25 -0
- package/src/schemas/generated/discount-group.ts +13 -0
- package/src/schemas/generated/extension.ts +15 -0
- package/src/schemas/generated/index.ts +42 -0
- package/src/schemas/generated/inventory-entry.ts +20 -0
- package/src/schemas/generated/my-quote-request.ts +10 -0
- package/src/schemas/generated/order-edit.ts +18 -0
- package/src/schemas/generated/order-from-cart.ts +25 -0
- package/src/schemas/generated/payment.ts +30 -0
- package/src/schemas/generated/product-discount.ts +20 -0
- package/src/schemas/generated/product-selection.ts +18 -0
- package/src/schemas/generated/product-tailoring.ts +26 -0
- package/src/schemas/generated/product-type.ts +12 -0
- package/src/schemas/generated/product.ts +37 -0
- package/src/schemas/generated/quote-request.ts +19 -0
- package/src/schemas/generated/quote.ts +18 -0
- package/src/schemas/generated/recurrence-policy.ts +15 -0
- package/src/schemas/generated/recurring-order.ts +19 -0
- package/src/schemas/generated/review.ts +24 -0
- package/src/schemas/generated/shipping-method.ts +24 -0
- package/src/schemas/generated/shopping-list.ts +28 -0
- package/src/schemas/generated/staged-quote.ts +18 -0
- package/src/schemas/generated/standalone-price.ts +32 -0
- package/src/schemas/generated/state.ts +20 -0
- package/src/schemas/generated/store.ts +23 -0
- package/src/schemas/generated/subscription.ts +20 -0
- package/src/schemas/generated/tax-category.ts +12 -0
- package/src/schemas/generated/type.ts +17 -0
- package/src/schemas/generated/zone.ts +12 -0
- package/src/schemas/update-request.ts +3 -5
- package/src/server.ts +32 -4
- package/src/services/abstract.ts +207 -101
- package/src/services/as-associate-cart.test.ts +28 -36
- package/src/services/as-associate-cart.ts +15 -12
- package/src/services/as-associate-order.test.ts +33 -40
- package/src/services/as-associate-order.ts +15 -12
- package/src/services/as-associate-quote-request.ts +15 -12
- package/src/services/as-associate-shopping-list.test.ts +25 -35
- package/src/services/as-associate-shopping-list.ts +15 -12
- package/src/services/as-associate.test.ts +21 -15
- package/src/services/as-associate.ts +23 -22
- package/src/services/associate-roles.test.ts +16 -22
- package/src/services/associate-roles.ts +2 -2
- package/src/services/attribute-group.test.ts +40 -44
- package/src/services/attribute-group.ts +2 -2
- package/src/services/business-units.test.ts +227 -163
- package/src/services/business-units.ts +2 -2
- package/src/services/cart-discount.test.ts +253 -187
- package/src/services/cart-discount.ts +2 -2
- package/src/services/cart.test.ts +833 -832
- package/src/services/cart.ts +31 -12
- package/src/services/category.test.ts +208 -130
- package/src/services/category.ts +2 -2
- package/src/services/channel.test.ts +39 -44
- package/src/services/channel.ts +2 -2
- package/src/services/custom-object.test.ts +103 -79
- package/src/services/custom-object.ts +106 -38
- package/src/services/customer-group.test.ts +39 -44
- package/src/services/customer-group.ts +2 -2
- package/src/services/customer.test.ts +357 -292
- package/src/services/customer.ts +70 -23
- package/src/services/discount-code.test.ts +57 -68
- package/src/services/discount-code.ts +2 -2
- package/src/services/discount-group.test.ts +111 -134
- package/src/services/discount-group.ts +2 -2
- package/src/services/draft-validation.test.ts +255 -0
- package/src/services/extension.test.ts +39 -44
- package/src/services/extension.ts +2 -2
- package/src/services/inventory-entry.test.ts +106 -87
- package/src/services/inventory-entry.ts +2 -2
- package/src/services/my-business-unit.test.ts +82 -112
- package/src/services/my-business-unit.ts +25 -19
- package/src/services/my-cart.test.ts +46 -41
- package/src/services/my-cart.ts +32 -28
- package/src/services/my-customer.test.ts +153 -88
- package/src/services/my-customer.ts +130 -61
- package/src/services/my-order.ts +15 -12
- package/src/services/my-payment.test.ts +30 -24
- package/src/services/my-payment.ts +2 -2
- package/src/services/my-shopping-list.ts +2 -2
- package/src/services/order.test.ts +332 -276
- package/src/services/order.ts +45 -27
- package/src/services/payment.test.ts +31 -29
- package/src/services/payment.ts +2 -2
- package/src/services/product-discount.test.ts +39 -46
- package/src/services/product-discount.ts +2 -2
- package/src/services/product-projection.test.ts +176 -166
- package/src/services/product-projection.ts +31 -15
- package/src/services/product-selection.test.ts +17 -9
- package/src/services/product-selection.ts +2 -2
- package/src/services/product-type.test.ts +80 -21
- package/src/services/product-type.ts +2 -2
- package/src/services/product.test.ts +569 -534
- package/src/services/product.ts +14 -7
- package/src/services/project.test.ts +22 -12
- package/src/services/project.ts +28 -13
- package/src/services/quote-request.test.ts +36 -39
- package/src/services/quote-request.ts +2 -2
- package/src/services/quote-staged.ts +2 -2
- package/src/services/quote.ts +2 -2
- package/src/services/recurrence-policy.test.ts +114 -139
- package/src/services/recurrence-policy.ts +2 -2
- package/src/services/recurring-order.test.ts +149 -194
- package/src/services/recurring-order.ts +2 -2
- package/src/services/reviews.test.ts +127 -106
- package/src/services/reviews.ts +2 -2
- package/src/services/shipping-method.test.ts +96 -125
- package/src/services/shipping-method.ts +24 -12
- package/src/services/shopping-list.test.ts +183 -141
- package/src/services/shopping-list.ts +2 -2
- package/src/services/standalone-price.test.ts +60 -46
- package/src/services/standalone-price.ts +2 -2
- package/src/services/state.test.ts +20 -25
- package/src/services/state.ts +2 -2
- package/src/services/store.test.ts +26 -45
- package/src/services/store.ts +2 -2
- package/src/services/subscription.test.ts +39 -44
- package/src/services/subscription.ts +2 -2
- package/src/services/tax-category.test.ts +33 -36
- package/src/services/tax-category.ts +2 -2
- package/src/services/type.test.ts +45 -44
- package/src/services/type.ts +2 -2
- package/src/services/zone.test.ts +40 -44
- package/src/services/zone.ts +2 -2
- package/src/shipping.ts +41 -11
- package/src/storage/abstract.ts +248 -17
- package/src/storage/in-memory.ts +147 -290
- package/src/storage/sqlite.ts +429 -0
- package/src/storage/storage-map.ts +75 -0
- package/src/storage/storage.test-helpers.ts +97 -0
- package/src/storage/storage.test.ts +802 -0
- package/src/testing/associate-role.ts +28 -0
- package/src/testing/attribute-group.ts +27 -0
- package/src/testing/business-unit.ts +9 -8
- package/src/testing/cart-discount.ts +34 -0
- package/src/testing/cart.ts +20 -0
- package/src/testing/category.ts +25 -0
- package/src/testing/channel.ts +23 -0
- package/src/testing/custom-object.ts +27 -0
- package/src/testing/customer-group.ts +26 -0
- package/src/testing/customer.ts +36 -33
- package/src/testing/discount-code.ts +29 -0
- package/src/testing/discount-group.ts +27 -0
- package/src/testing/extension.ts +32 -0
- package/src/testing/index.ts +33 -0
- package/src/testing/inventory-entry.ts +26 -0
- package/src/testing/order.ts +27 -0
- package/src/testing/payment.ts +23 -0
- package/src/testing/product-discount.ts +33 -0
- package/src/testing/product-selection.ts +28 -0
- package/src/testing/product-type.ts +27 -0
- package/src/testing/product.ts +38 -0
- package/src/testing/quote-request.ts +29 -0
- package/src/testing/recurrence-policy.ts +33 -0
- package/src/testing/recurring-order.ts +32 -0
- package/src/testing/review.ts +24 -0
- package/src/testing/shipping-method.ts +31 -0
- package/src/testing/shopping-list.ts +25 -0
- package/src/testing/standalone-price.ts +31 -0
- package/src/testing/state.ts +21 -0
- package/src/testing/store.ts +26 -0
- package/src/testing/subscription.ts +38 -0
- package/src/testing/tax-category.ts +27 -0
- package/src/testing/type.ts +9 -6
- package/src/testing/zone.ts +22 -0
- package/src/validate.test.ts +122 -0
- package/src/validate.ts +78 -7
- package/src/.env +0 -0
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
FacetResults,
|
|
3
3
|
FilteredFacetResult,
|
|
4
4
|
InvalidInputError,
|
|
5
|
+
InvalidOperationError,
|
|
5
6
|
Product,
|
|
6
7
|
ProductProjection,
|
|
7
8
|
ProductProjectionPagedSearchResponse,
|
|
@@ -59,19 +60,22 @@ export class ProductProjectionSearch {
|
|
|
59
60
|
this._reviewStatisticsService = new ReviewStatisticsService(config.storage);
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
search(
|
|
63
|
+
async search(
|
|
63
64
|
projectKey: string,
|
|
64
65
|
params: ProductProjectionSearchParams,
|
|
65
|
-
): ProductProjectionPagedSearchResponse {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
.map((r) =>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
): Promise<ProductProjectionPagedSearchResponse> {
|
|
67
|
+
const allProducts = await this._storage.all(projectKey, "product");
|
|
68
|
+
let resources = await Promise.all(
|
|
69
|
+
allProducts.map((r) =>
|
|
70
|
+
this.transform(r, params.staged ?? false, projectKey),
|
|
71
|
+
),
|
|
72
|
+
);
|
|
73
|
+
resources = resources.filter((p) => {
|
|
74
|
+
if (!(params.staged ?? false)) {
|
|
75
|
+
return p.published;
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
});
|
|
75
79
|
|
|
76
80
|
const markMatchingVariant = params.markMatchingVariants ?? false;
|
|
77
81
|
|
|
@@ -126,8 +130,10 @@ export class ProductProjectionSearch {
|
|
|
126
130
|
|
|
127
131
|
// Expand the resources
|
|
128
132
|
if (params.expand !== undefined) {
|
|
129
|
-
resources =
|
|
130
|
-
|
|
133
|
+
resources = await Promise.all(
|
|
134
|
+
resources.map((resource) =>
|
|
135
|
+
this._storage.expand(projectKey, resource, params.expand),
|
|
136
|
+
),
|
|
131
137
|
);
|
|
132
138
|
}
|
|
133
139
|
|
|
@@ -140,8 +146,8 @@ export class ProductProjectionSearch {
|
|
|
140
146
|
const results = resources.slice(offset, offset + limit);
|
|
141
147
|
|
|
142
148
|
return {
|
|
143
|
-
count:
|
|
144
|
-
total:
|
|
149
|
+
count: results.length,
|
|
150
|
+
total: totalResults,
|
|
145
151
|
offset: offset,
|
|
146
152
|
limit: limit,
|
|
147
153
|
results: results,
|
|
@@ -149,18 +155,18 @@ export class ProductProjectionSearch {
|
|
|
149
155
|
};
|
|
150
156
|
}
|
|
151
157
|
|
|
152
|
-
transform(
|
|
158
|
+
async transform(
|
|
153
159
|
product: Product,
|
|
154
160
|
staged: boolean,
|
|
155
161
|
projectKey: string,
|
|
156
|
-
): ProductProjection {
|
|
162
|
+
): Promise<ProductProjection> {
|
|
157
163
|
const obj = !staged
|
|
158
164
|
? product.masterData.current
|
|
159
165
|
: product.masterData.staged;
|
|
160
166
|
|
|
161
167
|
// Calculate review statistics for this product
|
|
162
168
|
const reviewRatingStatistics =
|
|
163
|
-
this._reviewStatisticsService.calculateProductReviewStatistics(
|
|
169
|
+
await this._reviewStatisticsService.calculateProductReviewStatistics(
|
|
164
170
|
projectKey,
|
|
165
171
|
product.id,
|
|
166
172
|
);
|
|
@@ -311,7 +317,13 @@ export class ProductProjectionSearch {
|
|
|
311
317
|
}
|
|
312
318
|
}
|
|
313
319
|
} else {
|
|
314
|
-
throw new
|
|
320
|
+
throw new CommercetoolsError<InvalidOperationError>(
|
|
321
|
+
{
|
|
322
|
+
code: "InvalidOperation",
|
|
323
|
+
message: "not supported",
|
|
324
|
+
},
|
|
325
|
+
400,
|
|
326
|
+
);
|
|
315
327
|
}
|
|
316
328
|
|
|
317
329
|
return {
|
|
@@ -358,7 +370,13 @@ export class ProductProjectionSearch {
|
|
|
358
370
|
mean: numValues > 0 ? mean(values) : 0,
|
|
359
371
|
};
|
|
360
372
|
}
|
|
361
|
-
throw new
|
|
373
|
+
throw new CommercetoolsError<InvalidOperationError>(
|
|
374
|
+
{
|
|
375
|
+
code: "InvalidOperation",
|
|
376
|
+
message: "not supported",
|
|
377
|
+
},
|
|
378
|
+
400,
|
|
379
|
+
);
|
|
362
380
|
}) || [];
|
|
363
381
|
const data: RangeFacetResult = {
|
|
364
382
|
type: "range",
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
InventoryEntryDraft,
|
|
3
|
-
ProductDraft,
|
|
4
2
|
ProductPagedSearchResponse,
|
|
5
3
|
ProductSearchRequest,
|
|
6
4
|
} from "@commercetools/platform-sdk";
|
|
7
|
-
import supertest from "supertest";
|
|
8
5
|
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
6
|
+
import { channelDraftFactory } from "#src/testing/channel.ts";
|
|
7
|
+
import { inventoryEntryDraftFactory } from "#src/testing/inventory-entry.ts";
|
|
8
|
+
import { productDraftFactory } from "#src/testing/product.ts";
|
|
9
|
+
import { productTypeDraftFactory } from "#src/testing/product-type.ts";
|
|
9
10
|
import { CommercetoolsMock } from "./index.ts";
|
|
10
11
|
|
|
11
12
|
describe("Product Search - Availability Filtering", () => {
|
|
@@ -13,25 +14,13 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
13
14
|
let productId: string;
|
|
14
15
|
|
|
15
16
|
beforeEach(async () => {
|
|
16
|
-
|
|
17
|
-
const productTypeDraft = {
|
|
18
|
-
name: "Test Product Type",
|
|
19
|
-
key: "test-type",
|
|
20
|
-
description: "Test Product Type",
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
await supertest(ctMock.app)
|
|
24
|
-
.post("/dummy/product-types")
|
|
25
|
-
.send(productTypeDraft);
|
|
17
|
+
const productType = await productTypeDraftFactory(ctMock).create();
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
const productDraft: ProductDraft = {
|
|
29
|
-
name: { "en-US": "Test Product" },
|
|
19
|
+
const product = await productDraftFactory(ctMock).create({
|
|
30
20
|
productType: {
|
|
31
21
|
typeId: "product-type",
|
|
32
|
-
|
|
22
|
+
id: productType.id,
|
|
33
23
|
},
|
|
34
|
-
slug: { "en-US": "test-product" },
|
|
35
24
|
masterVariant: {
|
|
36
25
|
sku: "TEST-SKU-001",
|
|
37
26
|
},
|
|
@@ -40,25 +29,23 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
40
29
|
sku: "TEST-SKU-002",
|
|
41
30
|
},
|
|
42
31
|
],
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const productResponse = await supertest(ctMock.app)
|
|
46
|
-
.post("/dummy/products")
|
|
47
|
-
.send(productDraft);
|
|
32
|
+
});
|
|
48
33
|
|
|
49
|
-
productId =
|
|
34
|
+
productId = product.id;
|
|
50
35
|
|
|
51
36
|
// Publish the product
|
|
52
|
-
await
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
37
|
+
await ctMock.app.inject({
|
|
38
|
+
method: "POST",
|
|
39
|
+
url: `/dummy/products/${productId}`,
|
|
40
|
+
payload: {
|
|
41
|
+
version: product.version,
|
|
56
42
|
actions: [{ action: "publish" }],
|
|
57
|
-
}
|
|
43
|
+
},
|
|
44
|
+
});
|
|
58
45
|
});
|
|
59
46
|
|
|
60
|
-
afterEach(() => {
|
|
61
|
-
ctMock.clear();
|
|
47
|
+
afterEach(async () => {
|
|
48
|
+
await ctMock.clear();
|
|
62
49
|
});
|
|
63
50
|
|
|
64
51
|
async function createInventoryEntry(
|
|
@@ -66,7 +53,7 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
66
53
|
quantityOnStock: number,
|
|
67
54
|
channelId?: string,
|
|
68
55
|
) {
|
|
69
|
-
|
|
56
|
+
await inventoryEntryDraftFactory(ctMock).create({
|
|
70
57
|
sku,
|
|
71
58
|
quantityOnStock,
|
|
72
59
|
...(channelId && {
|
|
@@ -75,9 +62,7 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
75
62
|
id: channelId,
|
|
76
63
|
},
|
|
77
64
|
}),
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
await supertest(ctMock.app).post("/dummy/inventory").send(inventoryEntry);
|
|
65
|
+
});
|
|
81
66
|
}
|
|
82
67
|
|
|
83
68
|
async function searchProducts(
|
|
@@ -90,15 +75,16 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
90
75
|
},
|
|
91
76
|
};
|
|
92
77
|
|
|
93
|
-
const response = await
|
|
94
|
-
|
|
95
|
-
|
|
78
|
+
const response = await ctMock.app.inject({
|
|
79
|
+
method: "POST",
|
|
80
|
+
url: "/dummy/products/search",
|
|
81
|
+
payload: searchRequest,
|
|
82
|
+
});
|
|
96
83
|
|
|
97
|
-
return response.
|
|
84
|
+
return response.json();
|
|
98
85
|
}
|
|
99
86
|
|
|
100
87
|
test("should filter products by variants.availability.isOnStock = true", async () => {
|
|
101
|
-
// Create inventory with stock for one variant
|
|
102
88
|
await createInventoryEntry("TEST-SKU-001", 10);
|
|
103
89
|
|
|
104
90
|
const result = await searchProducts({
|
|
@@ -116,7 +102,6 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
116
102
|
});
|
|
117
103
|
|
|
118
104
|
test("should filter products by variants.availability.isOnStock = false", async () => {
|
|
119
|
-
// Create inventory with zero stock
|
|
120
105
|
await createInventoryEntry("TEST-SKU-001", 0);
|
|
121
106
|
|
|
122
107
|
const result = await searchProducts({
|
|
@@ -126,7 +111,6 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
126
111
|
},
|
|
127
112
|
});
|
|
128
113
|
|
|
129
|
-
// Should find the product because it's not on stock
|
|
130
114
|
expect(result.results).toHaveLength(1);
|
|
131
115
|
expect(
|
|
132
116
|
result.results[0].productProjection?.masterVariant?.availability
|
|
@@ -135,9 +119,9 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
135
119
|
});
|
|
136
120
|
|
|
137
121
|
test("should filter products by variants.availability.isOnStockForChannel", async () => {
|
|
138
|
-
const
|
|
122
|
+
const channel = await channelDraftFactory(ctMock).create();
|
|
123
|
+
const channelId = channel.id;
|
|
139
124
|
|
|
140
|
-
// Create inventory for specific channel
|
|
141
125
|
await createInventoryEntry("TEST-SKU-001", 5, channelId);
|
|
142
126
|
|
|
143
127
|
const result = await searchProducts({
|
|
@@ -155,10 +139,10 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
155
139
|
});
|
|
156
140
|
|
|
157
141
|
test("should not find products when filtering by non-matching channel", async () => {
|
|
158
|
-
const
|
|
159
|
-
const
|
|
142
|
+
const channel = await channelDraftFactory(ctMock).create();
|
|
143
|
+
const channelId = channel.id;
|
|
144
|
+
const otherChannelId = "non-existent-channel-id";
|
|
160
145
|
|
|
161
|
-
// Create inventory for specific channel
|
|
162
146
|
await createInventoryEntry("TEST-SKU-001", 5, channelId);
|
|
163
147
|
|
|
164
148
|
const result = await searchProducts({
|
|
@@ -172,8 +156,6 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
172
156
|
});
|
|
173
157
|
|
|
174
158
|
test("should handle products without inventory entries", async () => {
|
|
175
|
-
// Don't create any inventory entries
|
|
176
|
-
|
|
177
159
|
const result = await searchProducts({
|
|
178
160
|
exact: {
|
|
179
161
|
field: "variants.availability.isOnStock",
|
|
@@ -181,7 +163,6 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
181
163
|
},
|
|
182
164
|
});
|
|
183
165
|
|
|
184
|
-
// Should find the product because it has no stock
|
|
185
166
|
expect(result.results).toHaveLength(1);
|
|
186
167
|
expect(
|
|
187
168
|
result.results[0].productProjection?.masterVariant?.availability
|
|
@@ -190,7 +171,6 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
190
171
|
});
|
|
191
172
|
|
|
192
173
|
test("should work with OR queries for availability", async () => {
|
|
193
|
-
// Create inventory with stock
|
|
194
174
|
await createInventoryEntry("TEST-SKU-001", 10);
|
|
195
175
|
|
|
196
176
|
const result = await searchProducts({
|
|
@@ -210,7 +190,6 @@ describe("Product Search - Availability Filtering", () => {
|
|
|
210
190
|
],
|
|
211
191
|
});
|
|
212
192
|
|
|
213
|
-
// Should find the product regardless of stock status
|
|
214
193
|
expect(result.results).toHaveLength(1);
|
|
215
194
|
});
|
|
216
195
|
|
package/src/product-search.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
InvalidInputError,
|
|
3
|
+
InventoryEntry,
|
|
3
4
|
Product,
|
|
4
5
|
ProductPagedSearchResponse,
|
|
5
6
|
ProductProjection,
|
|
@@ -26,13 +27,19 @@ export class ProductSearch {
|
|
|
26
27
|
this._storage = config.storage;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
search(
|
|
30
|
+
async search(
|
|
30
31
|
projectKey: string,
|
|
31
32
|
params: ProductSearchRequest,
|
|
32
|
-
): ProductPagedSearchResponse {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
): Promise<ProductPagedSearchResponse> {
|
|
34
|
+
const inventoryEntries = await this._storage.all(
|
|
35
|
+
projectKey,
|
|
36
|
+
"inventory-entry",
|
|
37
|
+
);
|
|
38
|
+
const availabilityBySku = inventoryEntries.reduce(
|
|
39
|
+
(
|
|
40
|
+
acc: Map<string, ProductSearchVariantAvailability>,
|
|
41
|
+
entry: InventoryEntry,
|
|
42
|
+
) => {
|
|
36
43
|
const existingEntry = acc.get(entry.sku);
|
|
37
44
|
|
|
38
45
|
acc.set(entry.sku, {
|
|
@@ -46,18 +53,20 @@ export class ProductSearch {
|
|
|
46
53
|
});
|
|
47
54
|
|
|
48
55
|
return acc;
|
|
49
|
-
},
|
|
56
|
+
},
|
|
57
|
+
new Map<string, ProductSearchVariantAvailability>(),
|
|
58
|
+
);
|
|
50
59
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
.map((r) =>
|
|
60
|
+
const allProducts = await this._storage.all(projectKey, "product");
|
|
61
|
+
let productResources = allProducts
|
|
62
|
+
.map((r: Product) =>
|
|
54
63
|
this.transformProduct(
|
|
55
64
|
r,
|
|
56
65
|
params.productProjectionParameters?.staged ?? false,
|
|
57
66
|
availabilityBySku,
|
|
58
67
|
),
|
|
59
68
|
)
|
|
60
|
-
.filter((p) => {
|
|
69
|
+
.filter((p: ProductProjection) => {
|
|
61
70
|
if (!(params.productProjectionParameters?.staged ?? false)) {
|
|
62
71
|
return p.published;
|
|
63
72
|
}
|
package/src/projectAPI.ts
CHANGED
|
@@ -21,25 +21,13 @@ export class ProjectAPI {
|
|
|
21
21
|
this._repositories = repositories;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
typeId: T,
|
|
26
|
-
resource: ResourceMap[T],
|
|
27
|
-
) {
|
|
28
|
-
process.emitWarning(
|
|
29
|
-
"ctMock.add() is deprecated, create resources via regular create endpoints " +
|
|
30
|
-
"or if you are really sure, use unsafeAdd() (but be aware of potential state issues)",
|
|
31
|
-
"DeprecationWarning",
|
|
32
|
-
);
|
|
33
|
-
this.unsafeAdd(typeId, resource);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
unsafeAdd<T extends keyof RepositoryMap & keyof ResourceMap>(
|
|
24
|
+
async unsafeAdd<T extends keyof RepositoryMap & keyof ResourceMap>(
|
|
37
25
|
typeId: T,
|
|
38
26
|
resource: ResourceMap[T],
|
|
39
27
|
) {
|
|
40
28
|
const repository = this._repositories[typeId];
|
|
41
29
|
if (repository) {
|
|
42
|
-
this._storage.add(this.projectKey, typeId, {
|
|
30
|
+
await this._storage.add(this.projectKey, typeId, {
|
|
43
31
|
...getBaseResourceProperties(),
|
|
44
32
|
...resource,
|
|
45
33
|
});
|
|
@@ -48,17 +36,13 @@ export class ProjectAPI {
|
|
|
48
36
|
}
|
|
49
37
|
}
|
|
50
38
|
|
|
51
|
-
get<RT extends ResourceType>(
|
|
39
|
+
async get<RT extends ResourceType>(
|
|
52
40
|
typeId: RT,
|
|
53
41
|
id: string,
|
|
54
42
|
params?: GetParams,
|
|
55
|
-
): ResourceMap[RT] {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
typeId,
|
|
59
|
-
id,
|
|
60
|
-
params,
|
|
61
|
-
) as ResourceMap[RT];
|
|
43
|
+
): Promise<ResourceMap[RT]> {
|
|
44
|
+
const result = await this._storage.get(this.projectKey, typeId, id, params);
|
|
45
|
+
return result as ResourceMap[RT];
|
|
62
46
|
}
|
|
63
47
|
|
|
64
48
|
// TODO: Not sure if we want to expose this...
|