@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,63 +2,71 @@ import type {
|
|
|
2
2
|
Customer,
|
|
3
3
|
CustomerChangePassword,
|
|
4
4
|
CustomerToken,
|
|
5
|
-
MyCustomerDraft,
|
|
6
5
|
} from "@commercetools/platform-sdk";
|
|
7
|
-
import supertest from "supertest";
|
|
8
6
|
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
7
|
+
import { customerDraftFactory } from "#src/testing/index.ts";
|
|
9
8
|
import { CommercetoolsMock, getBaseResourceProperties } from "../index.ts";
|
|
10
9
|
import { hashPassword } from "../lib/password.ts";
|
|
11
10
|
|
|
12
11
|
const ctMock = new CommercetoolsMock();
|
|
13
12
|
|
|
14
13
|
describe("Me", () => {
|
|
14
|
+
const customerFactory = customerDraftFactory(ctMock);
|
|
15
|
+
|
|
15
16
|
afterEach(() => {
|
|
16
17
|
ctMock.clear();
|
|
17
18
|
});
|
|
18
19
|
|
|
19
20
|
test("Create me", async () => {
|
|
20
|
-
const draft
|
|
21
|
+
const draft = customerFactory.build({
|
|
21
22
|
email: "test@example.org",
|
|
22
23
|
password: "p4ssw0rd",
|
|
23
|
-
};
|
|
24
|
+
});
|
|
24
25
|
|
|
25
|
-
const response = await
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const response = await ctMock.app.inject({
|
|
27
|
+
method: "POST",
|
|
28
|
+
url: "/dummy/me/signup",
|
|
29
|
+
payload: draft,
|
|
30
|
+
});
|
|
28
31
|
|
|
29
|
-
expect(response.
|
|
30
|
-
expect(response.
|
|
32
|
+
expect(response.statusCode).toBe(201);
|
|
33
|
+
expect(response.json()).toEqual({
|
|
31
34
|
customer: {
|
|
32
|
-
|
|
35
|
+
email: "test@example.org",
|
|
33
36
|
password: "cDRzc3cwcmQ=",
|
|
34
|
-
lowercaseEmail:
|
|
37
|
+
lowercaseEmail: "test@example.org",
|
|
35
38
|
authenticationMode: "Password",
|
|
36
39
|
version: 1,
|
|
37
40
|
isEmailVerified: false,
|
|
38
|
-
addresses:
|
|
41
|
+
addresses: expect.anything(),
|
|
39
42
|
billingAddressIds: [],
|
|
40
43
|
shippingAddressIds: [],
|
|
41
44
|
id: expect.anything(),
|
|
42
45
|
createdAt: expect.anything(),
|
|
46
|
+
createdBy: expect.anything(),
|
|
43
47
|
lastModifiedAt: expect.anything(),
|
|
48
|
+
lastModifiedBy: expect.anything(),
|
|
44
49
|
stores: [],
|
|
50
|
+
customerGroupAssignments: [],
|
|
51
|
+
firstName: "John",
|
|
52
|
+
lastName: "Doe",
|
|
45
53
|
},
|
|
46
54
|
});
|
|
47
55
|
});
|
|
48
56
|
|
|
49
57
|
test("Get me", async () => {
|
|
50
|
-
const
|
|
58
|
+
const customer = await customerFactory.create({
|
|
51
59
|
email: "test@example.org",
|
|
52
60
|
password: "p4ssw0rd",
|
|
53
|
-
};
|
|
54
|
-
const createResponse = await supertest(ctMock.app)
|
|
55
|
-
.post("/dummy/me/signup")
|
|
56
|
-
.send(draft);
|
|
61
|
+
});
|
|
57
62
|
|
|
58
|
-
const response = await
|
|
63
|
+
const response = await ctMock.app.inject({
|
|
64
|
+
method: "GET",
|
|
65
|
+
url: "/dummy/me",
|
|
66
|
+
});
|
|
59
67
|
|
|
60
|
-
expect(response.
|
|
61
|
-
expect(response.
|
|
68
|
+
expect(response.statusCode).toBe(200);
|
|
69
|
+
expect(response.json()).toEqual(customer);
|
|
62
70
|
});
|
|
63
71
|
});
|
|
64
72
|
|
|
@@ -68,7 +76,7 @@ describe("/me", () => {
|
|
|
68
76
|
});
|
|
69
77
|
|
|
70
78
|
beforeEach(() => {
|
|
71
|
-
ctMock.project("dummy").
|
|
79
|
+
ctMock.project("dummy").unsafeAdd("customer", {
|
|
72
80
|
id: "123",
|
|
73
81
|
createdAt: "2021-03-18T14:00:00.000Z",
|
|
74
82
|
version: 2,
|
|
@@ -79,18 +87,26 @@ describe("/me", () => {
|
|
|
79
87
|
authenticationMode: "password",
|
|
80
88
|
custom: { type: { typeId: "type", id: "" }, fields: {} },
|
|
81
89
|
stores: [],
|
|
90
|
+
shippingAddressIds: [],
|
|
91
|
+
billingAddressIds: [],
|
|
92
|
+
customerGroupAssignments: [],
|
|
82
93
|
});
|
|
83
94
|
});
|
|
84
95
|
|
|
85
96
|
test("Get me", async () => {
|
|
86
|
-
const response = await
|
|
97
|
+
const response = await ctMock.app.inject({
|
|
98
|
+
method: "GET",
|
|
99
|
+
url: "/dummy/me",
|
|
100
|
+
});
|
|
87
101
|
|
|
88
|
-
expect(response.
|
|
89
|
-
expect(response.
|
|
102
|
+
expect(response.statusCode).toBe(200);
|
|
103
|
+
expect(response.json()).toEqual({
|
|
90
104
|
id: "123",
|
|
91
105
|
createdAt: "2021-03-18T14:00:00.000Z",
|
|
106
|
+
createdBy: expect.anything(),
|
|
92
107
|
version: 2,
|
|
93
108
|
lastModifiedAt: "2021-03-18T14:00:00.000Z",
|
|
109
|
+
lastModifiedBy: expect.anything(),
|
|
94
110
|
email: "foo@example.org",
|
|
95
111
|
addresses: [],
|
|
96
112
|
isEmailVerified: true,
|
|
@@ -103,18 +119,26 @@ describe("/me", () => {
|
|
|
103
119
|
},
|
|
104
120
|
},
|
|
105
121
|
stores: [],
|
|
122
|
+
shippingAddressIds: [],
|
|
123
|
+
billingAddressIds: [],
|
|
124
|
+
customerGroupAssignments: [],
|
|
106
125
|
});
|
|
107
126
|
});
|
|
108
127
|
|
|
109
128
|
test("Delete me", async () => {
|
|
110
|
-
const response = await
|
|
129
|
+
const response = await ctMock.app.inject({
|
|
130
|
+
method: "DELETE",
|
|
131
|
+
url: "/dummy/me",
|
|
132
|
+
});
|
|
111
133
|
|
|
112
|
-
expect(response.
|
|
113
|
-
expect(response.
|
|
134
|
+
expect(response.statusCode).toBe(200);
|
|
135
|
+
expect(response.json()).toEqual({
|
|
114
136
|
id: "123",
|
|
115
137
|
createdAt: "2021-03-18T14:00:00.000Z",
|
|
138
|
+
createdBy: expect.anything(),
|
|
116
139
|
version: 2,
|
|
117
140
|
lastModifiedAt: "2021-03-18T14:00:00.000Z",
|
|
141
|
+
lastModifiedBy: expect.anything(),
|
|
118
142
|
email: "foo@example.org",
|
|
119
143
|
addresses: [],
|
|
120
144
|
isEmailVerified: true,
|
|
@@ -127,10 +151,16 @@ describe("/me", () => {
|
|
|
127
151
|
},
|
|
128
152
|
},
|
|
129
153
|
stores: [],
|
|
154
|
+
shippingAddressIds: [],
|
|
155
|
+
billingAddressIds: [],
|
|
156
|
+
customerGroupAssignments: [],
|
|
130
157
|
});
|
|
131
158
|
|
|
132
|
-
const newResponse = await
|
|
133
|
-
|
|
159
|
+
const newResponse = await ctMock.app.inject({
|
|
160
|
+
method: "GET",
|
|
161
|
+
url: "/dummy/me",
|
|
162
|
+
});
|
|
163
|
+
expect(newResponse.statusCode).toBe(404);
|
|
134
164
|
});
|
|
135
165
|
|
|
136
166
|
test("Change my password", async () => {
|
|
@@ -144,8 +174,11 @@ describe("/me", () => {
|
|
|
144
174
|
authenticationMode: "Password", //default in Commercetools
|
|
145
175
|
version: 1,
|
|
146
176
|
stores: [],
|
|
177
|
+
shippingAddressIds: [],
|
|
178
|
+
billingAddressIds: [],
|
|
179
|
+
customerGroupAssignments: [],
|
|
147
180
|
};
|
|
148
|
-
ctMock.project("dummy").
|
|
181
|
+
ctMock.project("dummy").unsafeAdd("customer", customer);
|
|
149
182
|
|
|
150
183
|
const draft: CustomerChangePassword = {
|
|
151
184
|
id: customer.id,
|
|
@@ -153,11 +186,13 @@ describe("/me", () => {
|
|
|
153
186
|
newPassword: "newP4ssw0rd",
|
|
154
187
|
currentPassword: "p4ssw0rd",
|
|
155
188
|
};
|
|
156
|
-
const response = await
|
|
157
|
-
|
|
158
|
-
|
|
189
|
+
const response = await ctMock.app.inject({
|
|
190
|
+
method: "POST",
|
|
191
|
+
url: "/dummy/me/password",
|
|
192
|
+
payload: draft,
|
|
193
|
+
});
|
|
159
194
|
|
|
160
|
-
expect(response.
|
|
195
|
+
expect(response.statusCode).toBe(200);
|
|
161
196
|
});
|
|
162
197
|
|
|
163
198
|
test("Fail to change password", async () => {
|
|
@@ -167,12 +202,14 @@ describe("/me", () => {
|
|
|
167
202
|
newPassword: "newP4ssw0rd",
|
|
168
203
|
currentPassword: "p4ssw0rd",
|
|
169
204
|
};
|
|
170
|
-
const response = await
|
|
171
|
-
|
|
172
|
-
|
|
205
|
+
const response = await ctMock.app.inject({
|
|
206
|
+
method: "POST",
|
|
207
|
+
url: "/dummy/me/password",
|
|
208
|
+
payload: draft,
|
|
209
|
+
});
|
|
173
210
|
|
|
174
|
-
expect(response.
|
|
175
|
-
expect(response.
|
|
211
|
+
expect(response.statusCode).toBe(400);
|
|
212
|
+
expect(response.json()).toEqual({
|
|
176
213
|
message: "Account with the given credentials not found.",
|
|
177
214
|
statusCode: 400,
|
|
178
215
|
errors: [
|
|
@@ -195,34 +232,43 @@ describe("/me", () => {
|
|
|
195
232
|
authenticationMode: "Password", //default in Commercetools
|
|
196
233
|
version: 1,
|
|
197
234
|
stores: [],
|
|
235
|
+
shippingAddressIds: [],
|
|
236
|
+
billingAddressIds: [],
|
|
237
|
+
customerGroupAssignments: [],
|
|
198
238
|
};
|
|
199
|
-
ctMock.project("dummy").
|
|
239
|
+
ctMock.project("dummy").unsafeAdd("customer", customer);
|
|
200
240
|
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
241
|
+
const tokenResponse = await ctMock.app.inject({
|
|
242
|
+
method: "POST",
|
|
243
|
+
url: "/dummy/customers/password-token",
|
|
244
|
+
payload: {
|
|
204
245
|
email: "user@example.com",
|
|
205
|
-
}
|
|
206
|
-
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
const token = tokenResponse.json() as CustomerToken;
|
|
207
249
|
|
|
208
|
-
const response = await
|
|
209
|
-
|
|
210
|
-
|
|
250
|
+
const response = await ctMock.app.inject({
|
|
251
|
+
method: "POST",
|
|
252
|
+
url: "/dummy/me/password/reset",
|
|
253
|
+
payload: {
|
|
211
254
|
tokenValue: token.value,
|
|
212
255
|
newPassword: "somethingNew",
|
|
213
|
-
}
|
|
214
|
-
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
expect(response.statusCode).toBe(200);
|
|
215
259
|
});
|
|
216
260
|
|
|
217
261
|
test("fail reset password flow", async () => {
|
|
218
|
-
const response = await
|
|
219
|
-
|
|
220
|
-
|
|
262
|
+
const response = await ctMock.app.inject({
|
|
263
|
+
method: "POST",
|
|
264
|
+
url: "/dummy/me/password/reset",
|
|
265
|
+
payload: {
|
|
221
266
|
tokenValue: "invalid-token",
|
|
222
267
|
newPassword: "somethingNew",
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
expect(response.
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
expect(response.statusCode).toBe(400);
|
|
271
|
+
expect(response.json()).toEqual({
|
|
226
272
|
message: `The Customer with ID 'Token(invalid-token)' was not found.`,
|
|
227
273
|
statusCode: 400,
|
|
228
274
|
errors: [
|
|
@@ -245,32 +291,41 @@ describe("/me", () => {
|
|
|
245
291
|
authenticationMode: "Password", //default in Commercetools
|
|
246
292
|
version: 1,
|
|
247
293
|
stores: [],
|
|
294
|
+
shippingAddressIds: [],
|
|
295
|
+
billingAddressIds: [],
|
|
296
|
+
customerGroupAssignments: [],
|
|
248
297
|
};
|
|
249
|
-
ctMock.project("dummy").
|
|
298
|
+
ctMock.project("dummy").unsafeAdd("customer", customer);
|
|
250
299
|
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
300
|
+
const tokenResponse = await ctMock.app.inject({
|
|
301
|
+
method: "POST",
|
|
302
|
+
url: "/dummy/customers/email-token",
|
|
303
|
+
payload: {
|
|
254
304
|
id: "customer-uuid",
|
|
255
|
-
}
|
|
256
|
-
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
const token = tokenResponse.json() as CustomerToken;
|
|
257
308
|
|
|
258
|
-
const response = await
|
|
259
|
-
|
|
260
|
-
|
|
309
|
+
const response = await ctMock.app.inject({
|
|
310
|
+
method: "POST",
|
|
311
|
+
url: "/dummy/me/email/confirm",
|
|
312
|
+
payload: {
|
|
261
313
|
tokenValue: token.value,
|
|
262
|
-
}
|
|
263
|
-
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
expect(response.statusCode).toBe(200);
|
|
264
317
|
});
|
|
265
318
|
|
|
266
319
|
test("fail verify email flow", async () => {
|
|
267
|
-
const response = await
|
|
268
|
-
|
|
269
|
-
|
|
320
|
+
const response = await ctMock.app.inject({
|
|
321
|
+
method: "POST",
|
|
322
|
+
url: "/dummy/me/email/confirm",
|
|
323
|
+
payload: {
|
|
270
324
|
tokenValue: "invalid-token",
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
expect(response.
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
expect(response.statusCode).toBe(400);
|
|
328
|
+
expect(response.json()).toEqual({
|
|
274
329
|
message: `The Customer with ID 'Token(invalid-token)' was not found.`,
|
|
275
330
|
statusCode: 400,
|
|
276
331
|
errors: [
|
|
@@ -283,31 +338,41 @@ describe("/me", () => {
|
|
|
283
338
|
});
|
|
284
339
|
|
|
285
340
|
test("setCustomField", async () => {
|
|
286
|
-
const response = await
|
|
287
|
-
|
|
288
|
-
|
|
341
|
+
const response = await ctMock.app.inject({
|
|
342
|
+
method: "POST",
|
|
343
|
+
url: "/dummy/me",
|
|
344
|
+
payload: {
|
|
289
345
|
version: 2,
|
|
290
346
|
actions: [{ action: "setCustomField", name: "foobar", value: true }],
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
expect(response.
|
|
294
|
-
expect(response.
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
expect(response.statusCode).toBe(200);
|
|
350
|
+
expect(response.json().version).toBe(3);
|
|
351
|
+
expect(response.json().custom.fields.foobar).toBe(true);
|
|
295
352
|
});
|
|
296
353
|
|
|
297
354
|
test("deleteMe", async () => {
|
|
298
|
-
const response = await
|
|
299
|
-
|
|
300
|
-
|
|
355
|
+
const response = await ctMock.app.inject({
|
|
356
|
+
method: "DELETE",
|
|
357
|
+
url: "/dummy/me",
|
|
358
|
+
});
|
|
359
|
+
expect(response.statusCode).toBe(200);
|
|
360
|
+
expect(response.json().id).toBeDefined();
|
|
301
361
|
});
|
|
302
362
|
|
|
303
363
|
test("signIn with invalid credentials", async () => {
|
|
304
|
-
const response = await
|
|
305
|
-
|
|
306
|
-
|
|
364
|
+
const response = await ctMock.app.inject({
|
|
365
|
+
method: "POST",
|
|
366
|
+
url: "/dummy/me/login",
|
|
367
|
+
payload: {
|
|
368
|
+
email: "nonexistent@example.com",
|
|
369
|
+
password: "wrongpassword",
|
|
370
|
+
},
|
|
307
371
|
});
|
|
308
372
|
|
|
309
|
-
expect(response.
|
|
310
|
-
expect(response.
|
|
373
|
+
expect(response.statusCode).toBe(400);
|
|
374
|
+
expect(response.json()).toEqual({
|
|
375
|
+
statusCode: 400,
|
|
311
376
|
message: "Account with the given credentials not found.",
|
|
312
377
|
errors: [
|
|
313
378
|
{
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type {
|
|
2
|
+
MyCustomerChangePassword,
|
|
3
|
+
MyCustomerDraft,
|
|
4
|
+
MyCustomerEmailVerify,
|
|
5
|
+
MyCustomerResetPassword,
|
|
6
|
+
MyCustomerSignin,
|
|
7
|
+
ResourceNotFoundError,
|
|
8
|
+
Update,
|
|
9
|
+
} from "@commercetools/platform-sdk";
|
|
10
|
+
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
|
|
11
|
+
import { CommercetoolsError } from "#src/exceptions.ts";
|
|
4
12
|
import { updateRequestSchema } from "#src/schemas/update-request.ts";
|
|
5
13
|
import { validateData } from "#src/validate.ts";
|
|
6
14
|
import { hashPassword } from "../lib/password.ts";
|
|
@@ -11,7 +19,7 @@ import AbstractService from "./abstract.ts";
|
|
|
11
19
|
export class MyCustomerService extends AbstractService {
|
|
12
20
|
public repository: MyCustomerRepository;
|
|
13
21
|
|
|
14
|
-
constructor(parent:
|
|
22
|
+
constructor(parent: FastifyInstance, repository: MyCustomerRepository) {
|
|
15
23
|
super(parent);
|
|
16
24
|
this.repository = repository;
|
|
17
25
|
}
|
|
@@ -20,126 +28,187 @@ export class MyCustomerService extends AbstractService {
|
|
|
20
28
|
return "me";
|
|
21
29
|
}
|
|
22
30
|
|
|
23
|
-
registerRoutes(parent:
|
|
31
|
+
registerRoutes(parent: FastifyInstance) {
|
|
24
32
|
// Overwrite this function to be able to handle /me path.
|
|
25
33
|
const basePath = this.getBasePath();
|
|
26
|
-
|
|
34
|
+
parent.register(
|
|
35
|
+
(instance, opts, done) => {
|
|
36
|
+
this.extraRoutes(instance);
|
|
27
37
|
|
|
28
|
-
|
|
38
|
+
instance.get("", this.getMe.bind(this));
|
|
39
|
+
instance.post("", this.updateMe.bind(this));
|
|
40
|
+
instance.delete("", this.deleteMe.bind(this));
|
|
29
41
|
|
|
30
|
-
|
|
31
|
-
router.post("", this.updateMe.bind(this));
|
|
32
|
-
router.delete("", this.deleteMe.bind(this));
|
|
42
|
+
instance.post("/signup", this.signUp.bind(this));
|
|
33
43
|
|
|
34
|
-
|
|
44
|
+
instance.post("/login", this.signIn.bind(this));
|
|
45
|
+
instance.post("/password", this.changePassword.bind(this));
|
|
46
|
+
instance.post("/password/reset", this.resetPassword.bind(this));
|
|
47
|
+
instance.post("/email/confirm", this.emailConfirm.bind(this));
|
|
35
48
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
parent.use(`/${basePath}`, router);
|
|
49
|
+
done();
|
|
50
|
+
},
|
|
51
|
+
{ prefix: `/${basePath}` },
|
|
52
|
+
);
|
|
42
53
|
}
|
|
43
54
|
|
|
44
|
-
getMe(
|
|
45
|
-
|
|
55
|
+
async getMe(
|
|
56
|
+
request: FastifyRequest<{ Params: Record<string, string> }>,
|
|
57
|
+
reply: FastifyReply,
|
|
58
|
+
) {
|
|
59
|
+
const resource = await this.repository.getMe(getRepositoryContext(request));
|
|
46
60
|
if (!resource) {
|
|
47
|
-
|
|
48
|
-
|
|
61
|
+
throw new CommercetoolsError<ResourceNotFoundError>(
|
|
62
|
+
{
|
|
63
|
+
code: "ResourceNotFound",
|
|
64
|
+
message: "The Resource was not found.",
|
|
65
|
+
},
|
|
66
|
+
404,
|
|
67
|
+
);
|
|
49
68
|
}
|
|
50
|
-
|
|
69
|
+
return reply.status(200).send(resource);
|
|
51
70
|
}
|
|
52
71
|
|
|
53
|
-
updateMe(
|
|
54
|
-
|
|
72
|
+
async updateMe(
|
|
73
|
+
request: FastifyRequest<{
|
|
74
|
+
Params: Record<string, string>;
|
|
75
|
+
Querystring: Record<string, any>;
|
|
76
|
+
}>,
|
|
77
|
+
reply: FastifyReply,
|
|
78
|
+
) {
|
|
79
|
+
const resource = await this.repository.getMe(getRepositoryContext(request));
|
|
55
80
|
|
|
56
81
|
if (!resource) {
|
|
57
|
-
|
|
58
|
-
|
|
82
|
+
throw new CommercetoolsError<ResourceNotFoundError>(
|
|
83
|
+
{
|
|
84
|
+
code: "ResourceNotFound",
|
|
85
|
+
message: "The Resource was not found.",
|
|
86
|
+
},
|
|
87
|
+
404,
|
|
88
|
+
);
|
|
59
89
|
}
|
|
60
90
|
const updateRequest = validateData<Update>(
|
|
61
91
|
request.body,
|
|
62
92
|
updateRequestSchema,
|
|
63
93
|
);
|
|
64
|
-
const updatedResource = this.repository.processUpdateActions(
|
|
94
|
+
const updatedResource = await this.repository.processUpdateActions(
|
|
65
95
|
getRepositoryContext(request),
|
|
66
96
|
resource,
|
|
67
97
|
updateRequest.version,
|
|
68
98
|
updateRequest.actions,
|
|
69
99
|
);
|
|
70
100
|
|
|
71
|
-
const result = this._expandWithId(request, updatedResource.id);
|
|
72
|
-
|
|
101
|
+
const result = await this._expandWithId(request, updatedResource.id);
|
|
102
|
+
return reply.status(200).send(result);
|
|
73
103
|
}
|
|
74
104
|
|
|
75
|
-
deleteMe(
|
|
76
|
-
|
|
105
|
+
async deleteMe(
|
|
106
|
+
request: FastifyRequest<{ Params: Record<string, string> }>,
|
|
107
|
+
reply: FastifyReply,
|
|
108
|
+
) {
|
|
109
|
+
const resource = await this.repository.deleteMe(
|
|
110
|
+
getRepositoryContext(request),
|
|
111
|
+
);
|
|
77
112
|
if (!resource) {
|
|
78
|
-
|
|
79
|
-
|
|
113
|
+
throw new CommercetoolsError<ResourceNotFoundError>(
|
|
114
|
+
{
|
|
115
|
+
code: "ResourceNotFound",
|
|
116
|
+
message: "The Resource was not found.",
|
|
117
|
+
},
|
|
118
|
+
404,
|
|
119
|
+
);
|
|
80
120
|
}
|
|
81
121
|
|
|
82
|
-
|
|
122
|
+
return reply.status(200).send(resource);
|
|
83
123
|
}
|
|
84
124
|
|
|
85
|
-
signUp(
|
|
125
|
+
async signUp(
|
|
126
|
+
request: FastifyRequest<{
|
|
127
|
+
Params: Record<string, string>;
|
|
128
|
+
Querystring: Record<string, any>;
|
|
129
|
+
Body: MyCustomerDraft;
|
|
130
|
+
}>,
|
|
131
|
+
reply: FastifyReply,
|
|
132
|
+
) {
|
|
86
133
|
const draft = request.body;
|
|
87
|
-
const resource = this.repository.create(
|
|
134
|
+
const resource = await this.repository.create(
|
|
88
135
|
getRepositoryContext(request),
|
|
89
136
|
draft,
|
|
90
137
|
);
|
|
91
|
-
const result = this._expandWithId(request, resource.id);
|
|
92
|
-
|
|
138
|
+
const result = await this._expandWithId(request, resource.id);
|
|
139
|
+
return reply.status(this.createStatusCode).send({ customer: result });
|
|
93
140
|
}
|
|
94
141
|
|
|
95
|
-
changePassword(
|
|
96
|
-
|
|
142
|
+
async changePassword(
|
|
143
|
+
request: FastifyRequest<{
|
|
144
|
+
Params: Record<string, string>;
|
|
145
|
+
Body: MyCustomerChangePassword;
|
|
146
|
+
}>,
|
|
147
|
+
reply: FastifyReply,
|
|
148
|
+
) {
|
|
149
|
+
const customer = await this.repository.changePassword(
|
|
97
150
|
getRepositoryContext(request),
|
|
98
151
|
request.body,
|
|
99
152
|
);
|
|
100
153
|
|
|
101
|
-
|
|
154
|
+
return reply.status(200).send(customer);
|
|
102
155
|
}
|
|
103
156
|
|
|
104
|
-
resetPassword(
|
|
105
|
-
|
|
157
|
+
async resetPassword(
|
|
158
|
+
request: FastifyRequest<{
|
|
159
|
+
Params: Record<string, string>;
|
|
160
|
+
Body: MyCustomerResetPassword;
|
|
161
|
+
}>,
|
|
162
|
+
reply: FastifyReply,
|
|
163
|
+
) {
|
|
164
|
+
const customer = await this.repository.passwordReset(
|
|
106
165
|
getRepositoryContext(request),
|
|
107
166
|
request.body,
|
|
108
167
|
);
|
|
109
168
|
|
|
110
|
-
|
|
169
|
+
return reply.status(200).send(customer);
|
|
111
170
|
}
|
|
112
171
|
|
|
113
|
-
emailConfirm(
|
|
114
|
-
|
|
172
|
+
async emailConfirm(
|
|
173
|
+
request: FastifyRequest<{
|
|
174
|
+
Params: Record<string, string>;
|
|
175
|
+
Body: MyCustomerEmailVerify;
|
|
176
|
+
}>,
|
|
177
|
+
reply: FastifyReply,
|
|
178
|
+
) {
|
|
179
|
+
const customer = await this.repository.confirmEmail(
|
|
115
180
|
getRepositoryContext(request),
|
|
116
181
|
request.body,
|
|
117
182
|
);
|
|
118
183
|
|
|
119
|
-
|
|
184
|
+
return reply.status(200).send(customer);
|
|
120
185
|
}
|
|
121
186
|
|
|
122
|
-
signIn(
|
|
123
|
-
|
|
187
|
+
async signIn(
|
|
188
|
+
request: FastifyRequest<{
|
|
189
|
+
Params: Record<string, string>;
|
|
190
|
+
Body: MyCustomerSignin;
|
|
191
|
+
}>,
|
|
192
|
+
reply: FastifyReply,
|
|
193
|
+
) {
|
|
194
|
+
const body = request.body;
|
|
195
|
+
const { email, password } = body;
|
|
124
196
|
const encodedPassword = hashPassword(password);
|
|
125
197
|
|
|
126
|
-
const result = this.repository.query(getRepositoryContext(request), {
|
|
198
|
+
const result = await this.repository.query(getRepositoryContext(request), {
|
|
127
199
|
where: [`email = "${email}"`, `password = "${encodedPassword}"`],
|
|
128
200
|
});
|
|
129
201
|
|
|
130
202
|
if (result.count === 0) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
],
|
|
139
|
-
});
|
|
140
|
-
return;
|
|
203
|
+
throw new CommercetoolsError<any>(
|
|
204
|
+
{
|
|
205
|
+
code: "InvalidCredentials",
|
|
206
|
+
message: "Account with the given credentials not found.",
|
|
207
|
+
},
|
|
208
|
+
400,
|
|
209
|
+
);
|
|
141
210
|
}
|
|
142
211
|
|
|
143
|
-
|
|
212
|
+
return reply.status(200).send({ customer: result.results[0] });
|
|
144
213
|
}
|
|
145
214
|
}
|