@labdigital/commercetools-mock 2.14.2 → 2.16.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 +364 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -15
- package/dist/index.d.ts +19 -15
- package/dist/index.js +364 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/repositories/customer.ts +13 -0
- package/src/repositories/payment.ts +148 -25
- package/src/repositories/shopping-list.ts +347 -16
- package/src/services/cart.test.ts +2 -2
- package/src/services/customer.test.ts +40 -0
- package/src/services/shopping-list.test.ts +352 -0
- package/src/storage/in-memory.ts +40 -2
|
@@ -330,4 +330,44 @@ describe('Customer Update Actions', () => {
|
|
|
330
330
|
},
|
|
331
331
|
])
|
|
332
332
|
})
|
|
333
|
+
|
|
334
|
+
test('setCustomerNumber', async () => {
|
|
335
|
+
assert(customer, 'customer not created')
|
|
336
|
+
|
|
337
|
+
ctMock.project('dummy').add('customer', customer)
|
|
338
|
+
|
|
339
|
+
const response = await supertest(ctMock.app)
|
|
340
|
+
.post(`/dummy/customers/${customer.id}`)
|
|
341
|
+
.send({
|
|
342
|
+
version: 1,
|
|
343
|
+
actions: [
|
|
344
|
+
{ action: 'setCustomerNumber', customerNumber: 'CUSTOMER-001' },
|
|
345
|
+
],
|
|
346
|
+
})
|
|
347
|
+
expect(response.status).toBe(200)
|
|
348
|
+
expect(response.body.version).toBe(2)
|
|
349
|
+
expect(response.body.customerNumber).toBe('CUSTOMER-001')
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
test('setCustomerNumber error when already have a customer number', async () => {
|
|
353
|
+
assert(customer, 'customer not created')
|
|
354
|
+
|
|
355
|
+
ctMock.project('dummy').add('customer', {
|
|
356
|
+
...customer,
|
|
357
|
+
customerNumber: 'CUSTOMER-002',
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
const response = await supertest(ctMock.app)
|
|
361
|
+
.post(`/dummy/customers/${customer.id}`)
|
|
362
|
+
.send({
|
|
363
|
+
version: 1,
|
|
364
|
+
actions: [
|
|
365
|
+
{ action: 'setCustomerNumber', customerNumber: 'CUSTOMER-001' },
|
|
366
|
+
],
|
|
367
|
+
})
|
|
368
|
+
expect(response.status).toBe(500)
|
|
369
|
+
expect(response.body.error).toBe(
|
|
370
|
+
'A Customer number already exists and cannot be set again.'
|
|
371
|
+
)
|
|
372
|
+
})
|
|
333
373
|
})
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Product,
|
|
3
|
+
ShoppingList,
|
|
4
|
+
ShoppingListDraft,
|
|
5
|
+
} from '@commercetools/platform-sdk'
|
|
6
|
+
import supertest from 'supertest'
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, test } from 'vitest'
|
|
8
|
+
import { CommercetoolsMock } from '../ctMock'
|
|
9
|
+
|
|
10
|
+
const shoppingList: ShoppingList = {
|
|
11
|
+
id: 'f15b4a80-7def-4381-bf6a-c66cab258a2b',
|
|
12
|
+
version: 1,
|
|
13
|
+
lineItems: [
|
|
14
|
+
{
|
|
15
|
+
addedAt: '2021-08-03T14:19:29.496Z',
|
|
16
|
+
productType: { typeId: 'product-type', id: 'product-type-id' },
|
|
17
|
+
id: '42ea3c57-aced-49ea-ae70-7005a47c7463',
|
|
18
|
+
productId: '303bf5d8-1201-4fb9-8157-ff6efb8c04b4',
|
|
19
|
+
name: {},
|
|
20
|
+
quantity: 1,
|
|
21
|
+
productSlug: {},
|
|
22
|
+
variantId: 2,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
textLineItems: [],
|
|
26
|
+
createdAt: '2021-07-22T12:23:33.472Z',
|
|
27
|
+
lastModifiedAt: '2021-08-03T14:19:29.496Z',
|
|
28
|
+
name: {},
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const product: Product = {
|
|
32
|
+
id: '303bf5d8-1201-4fb9-8157-ff6efb8c04b4',
|
|
33
|
+
createdAt: '2022-05-30T13:21:26.777Z',
|
|
34
|
+
lastModifiedAt: '2022-05-30T13:21:26.777Z',
|
|
35
|
+
version: 1,
|
|
36
|
+
productType: {
|
|
37
|
+
typeId: 'product-type',
|
|
38
|
+
id: '303bf5d8-1201-4fb9-8157-ff6efb8c04b4',
|
|
39
|
+
},
|
|
40
|
+
masterData: {
|
|
41
|
+
staged: {
|
|
42
|
+
name: {},
|
|
43
|
+
categories: [],
|
|
44
|
+
slug: {},
|
|
45
|
+
masterVariant: {
|
|
46
|
+
id: 1,
|
|
47
|
+
sku: '1',
|
|
48
|
+
},
|
|
49
|
+
variants: [],
|
|
50
|
+
searchKeywords: {},
|
|
51
|
+
},
|
|
52
|
+
current: {
|
|
53
|
+
name: {},
|
|
54
|
+
slug: {},
|
|
55
|
+
categories: [],
|
|
56
|
+
masterVariant: {
|
|
57
|
+
id: 1,
|
|
58
|
+
availability: {},
|
|
59
|
+
},
|
|
60
|
+
variants: [
|
|
61
|
+
{
|
|
62
|
+
id: 2,
|
|
63
|
+
sku: '22241940260',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
searchKeywords: {},
|
|
67
|
+
},
|
|
68
|
+
hasStagedChanges: true,
|
|
69
|
+
published: true,
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
describe('Shopping List', () => {
|
|
74
|
+
const ctMock = new CommercetoolsMock({
|
|
75
|
+
defaultProjectKey: 'dummy',
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
beforeEach(() => {
|
|
79
|
+
ctMock.project().add('product', product)
|
|
80
|
+
ctMock.project().add('shopping-list', shoppingList)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('Adds variant ID on lineItems when creating', async () => {
|
|
84
|
+
const draft: ShoppingListDraft = {
|
|
85
|
+
name: {},
|
|
86
|
+
lineItems: [{ sku: '22241940260' }],
|
|
87
|
+
}
|
|
88
|
+
const response = await supertest(ctMock.app)
|
|
89
|
+
.post('/dummy/shopping-lists')
|
|
90
|
+
.send(draft)
|
|
91
|
+
|
|
92
|
+
expect(response.status).toBe(201)
|
|
93
|
+
expect(response.body.lineItems[0].variantId).toBe(2)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('Expands variant on lineItems', async () => {
|
|
97
|
+
const response = await supertest(ctMock.app)
|
|
98
|
+
.get(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
99
|
+
.query({ expand: 'lineItems[*].variant' })
|
|
100
|
+
|
|
101
|
+
expect(response.status).toBe(200)
|
|
102
|
+
expect(response.body.lineItems[0].variant).toEqual({
|
|
103
|
+
id: 2,
|
|
104
|
+
sku: '22241940260',
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
describe('Shopping List Update Actions', () => {
|
|
110
|
+
const ctMock = new CommercetoolsMock({
|
|
111
|
+
defaultProjectKey: 'dummy',
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
beforeEach(() => {
|
|
115
|
+
ctMock.project().add('product', product)
|
|
116
|
+
ctMock.project().add('shopping-list', shoppingList)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
afterEach(() => {
|
|
120
|
+
ctMock.clear()
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('addLineItem by productID & variantID', async () => {
|
|
124
|
+
ctMock.clear()
|
|
125
|
+
ctMock.project().add('product', product)
|
|
126
|
+
ctMock.project().add('shopping-list', { ...shoppingList, lineItems: [] })
|
|
127
|
+
|
|
128
|
+
const response = await supertest(ctMock.app)
|
|
129
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
130
|
+
.send({
|
|
131
|
+
version: 1,
|
|
132
|
+
actions: [
|
|
133
|
+
{
|
|
134
|
+
action: 'addLineItem',
|
|
135
|
+
productId: product.id,
|
|
136
|
+
variantId: product.masterData.current.variants[0].id,
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
})
|
|
140
|
+
expect(response.status).toBe(200)
|
|
141
|
+
expect(response.body.version).toBe(2)
|
|
142
|
+
expect(response.body.lineItems).toHaveLength(1)
|
|
143
|
+
expect(response.body.lineItems[0].variantId).toEqual(2)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
test('addLineItem by productID', async () => {
|
|
147
|
+
ctMock.clear()
|
|
148
|
+
ctMock.project().add('product', product)
|
|
149
|
+
ctMock.project().add('shopping-list', { ...shoppingList, lineItems: [] })
|
|
150
|
+
|
|
151
|
+
const response = await supertest(ctMock.app)
|
|
152
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
153
|
+
.send({
|
|
154
|
+
version: 1,
|
|
155
|
+
actions: [
|
|
156
|
+
{
|
|
157
|
+
action: 'addLineItem',
|
|
158
|
+
productId: product.id,
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
})
|
|
162
|
+
expect(response.status).toBe(200)
|
|
163
|
+
expect(response.body.version).toBe(2)
|
|
164
|
+
expect(response.body.lineItems).toHaveLength(1)
|
|
165
|
+
expect(response.body.lineItems[0].variantId).toEqual(1)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
test('addLineItem by sku', async () => {
|
|
169
|
+
ctMock.clear()
|
|
170
|
+
ctMock.project().add('product', product)
|
|
171
|
+
ctMock.project().add('shopping-list', { ...shoppingList, lineItems: [] })
|
|
172
|
+
|
|
173
|
+
const response = await supertest(ctMock.app)
|
|
174
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
175
|
+
.send({
|
|
176
|
+
version: 1,
|
|
177
|
+
actions: [
|
|
178
|
+
{
|
|
179
|
+
action: 'addLineItem',
|
|
180
|
+
sku: '22241940260',
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
})
|
|
184
|
+
expect(response.status).toBe(200)
|
|
185
|
+
expect(response.body.version).toBe(2)
|
|
186
|
+
expect(response.body.lineItems).toHaveLength(1)
|
|
187
|
+
expect(response.body.lineItems[0].variantId).toEqual(2)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('addLineItem increases quantity', async () => {
|
|
191
|
+
const response = await supertest(ctMock.app)
|
|
192
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
193
|
+
.send({
|
|
194
|
+
version: 1,
|
|
195
|
+
actions: [
|
|
196
|
+
{
|
|
197
|
+
action: 'addLineItem',
|
|
198
|
+
sku: '22241940260',
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
})
|
|
202
|
+
expect(response.status).toBe(200)
|
|
203
|
+
expect(response.body.version).toBe(2)
|
|
204
|
+
expect(response.body.lineItems).toHaveLength(1)
|
|
205
|
+
expect(response.body.lineItems[0].variantId).toEqual(2)
|
|
206
|
+
expect(response.body.lineItems[0].quantity).toEqual(2)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
test('addLineItem unknown product', async () => {
|
|
210
|
+
const response = await supertest(ctMock.app)
|
|
211
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
212
|
+
.send({
|
|
213
|
+
version: 1,
|
|
214
|
+
actions: [{ action: 'addLineItem', productId: '123', variantId: 1 }],
|
|
215
|
+
})
|
|
216
|
+
expect(response.status).toBe(400)
|
|
217
|
+
expect(response.body.message).toBe("A product with ID '123' not found.")
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
test('removeLineItem', async () => {
|
|
221
|
+
const response = await supertest(ctMock.app)
|
|
222
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
223
|
+
.send({
|
|
224
|
+
version: 1,
|
|
225
|
+
actions: [
|
|
226
|
+
{
|
|
227
|
+
action: 'removeLineItem',
|
|
228
|
+
lineItemId: shoppingList.lineItems[0].id,
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
})
|
|
232
|
+
expect(response.status).toBe(200)
|
|
233
|
+
expect(response.body.version).toBe(2)
|
|
234
|
+
expect(response.body.lineItems).toHaveLength(0)
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
test('removeLineItem decreases quantity', async () => {
|
|
238
|
+
await supertest(ctMock.app)
|
|
239
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
240
|
+
.send({
|
|
241
|
+
version: 1,
|
|
242
|
+
actions: [
|
|
243
|
+
{
|
|
244
|
+
action: 'addLineItem',
|
|
245
|
+
sku: '22241940260',
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
const response = await supertest(ctMock.app)
|
|
251
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
252
|
+
.send({
|
|
253
|
+
version: 2,
|
|
254
|
+
actions: [
|
|
255
|
+
{
|
|
256
|
+
action: 'removeLineItem',
|
|
257
|
+
lineItemId: shoppingList.lineItems[0].id,
|
|
258
|
+
quantity: 1,
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
})
|
|
262
|
+
expect(response.status).toBe(200)
|
|
263
|
+
expect(response.body.version).toBe(3)
|
|
264
|
+
expect(response.body.lineItems).toHaveLength(1)
|
|
265
|
+
expect(response.body.lineItems[0].quantity).toBe(1)
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
test('changeLineItemQuantity sets quantity', async () => {
|
|
269
|
+
const response = await supertest(ctMock.app)
|
|
270
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
271
|
+
.send({
|
|
272
|
+
version: 1,
|
|
273
|
+
actions: [
|
|
274
|
+
{
|
|
275
|
+
action: 'changeLineItemQuantity',
|
|
276
|
+
lineItemId: shoppingList.lineItems[0].id,
|
|
277
|
+
quantity: 2,
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
})
|
|
281
|
+
expect(response.status).toBe(200)
|
|
282
|
+
expect(response.body.version).toBe(2)
|
|
283
|
+
expect(response.body.lineItems.length).toBe(1)
|
|
284
|
+
expect(response.body.lineItems[0].quantity).toBe(2)
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
test('changeLineItemQuantity removes line item if quantity is 0', async () => {
|
|
288
|
+
const response = await supertest(ctMock.app)
|
|
289
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
290
|
+
.send({
|
|
291
|
+
version: 1,
|
|
292
|
+
actions: [
|
|
293
|
+
{
|
|
294
|
+
action: 'changeLineItemQuantity',
|
|
295
|
+
lineItemId: shoppingList.lineItems[0].id,
|
|
296
|
+
quantity: 0,
|
|
297
|
+
},
|
|
298
|
+
],
|
|
299
|
+
})
|
|
300
|
+
expect(response.status).toBe(200)
|
|
301
|
+
expect(response.body.version).toBe(2)
|
|
302
|
+
expect(response.body.lineItems.length).toBe(0)
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
test('various setters', async () => {
|
|
306
|
+
const response = await supertest(ctMock.app)
|
|
307
|
+
.post(`/dummy/shopping-lists/${shoppingList.id}`)
|
|
308
|
+
.send({
|
|
309
|
+
version: 1,
|
|
310
|
+
actions: [
|
|
311
|
+
{
|
|
312
|
+
action: 'setKey',
|
|
313
|
+
key: 'new-key',
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
action: 'setSlug',
|
|
317
|
+
slug: 'new-slug',
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
action: 'changeName',
|
|
321
|
+
name: { en: 'new name' },
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
action: 'setDescription',
|
|
325
|
+
description: { en: 'new description' },
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
action: 'setCustomer',
|
|
329
|
+
customer: { typeId: 'customer', id: 'customer-id' },
|
|
330
|
+
},
|
|
331
|
+
{ action: 'setStore', store: { typeId: 'store', key: 'store-key' } },
|
|
332
|
+
{ action: 'setAnonymousId', anonymousId: 'new-anonymous-id' },
|
|
333
|
+
{
|
|
334
|
+
action: 'setDeleteDaysAfterLastModification',
|
|
335
|
+
deleteDaysAfterLastModification: 1,
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
})
|
|
339
|
+
expect(response.status).toBe(200)
|
|
340
|
+
expect(response.body.key).toBe('new-key')
|
|
341
|
+
expect(response.body.slug).toBe('new-slug')
|
|
342
|
+
expect(response.body.name).toEqual({ en: 'new name' })
|
|
343
|
+
expect(response.body.description).toEqual({ en: 'new description' })
|
|
344
|
+
expect(response.body.customer).toEqual({
|
|
345
|
+
typeId: 'customer',
|
|
346
|
+
id: 'customer-id',
|
|
347
|
+
})
|
|
348
|
+
expect(response.body.store).toEqual({ typeId: 'store', key: 'store-key' })
|
|
349
|
+
expect(response.body.anonymousId).toEqual('new-anonymous-id')
|
|
350
|
+
expect(response.body.deleteDaysAfterLastModification).toEqual(1)
|
|
351
|
+
})
|
|
352
|
+
})
|
package/src/storage/in-memory.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
InvalidJsonInputError,
|
|
2
3
|
ReferencedResourceNotFoundError,
|
|
4
|
+
ShoppingListLineItem,
|
|
3
5
|
type AssociateRole,
|
|
4
6
|
type AttributeGroup,
|
|
5
7
|
type BusinessUnit,
|
|
@@ -7,9 +9,9 @@ import {
|
|
|
7
9
|
type CartDiscount,
|
|
8
10
|
type Category,
|
|
9
11
|
type Channel,
|
|
12
|
+
type CustomObject,
|
|
10
13
|
type Customer,
|
|
11
14
|
type CustomerGroup,
|
|
12
|
-
type CustomObject,
|
|
13
15
|
type DiscountCode,
|
|
14
16
|
type Extension,
|
|
15
17
|
type InvalidInputError,
|
|
@@ -35,7 +37,6 @@ import {
|
|
|
35
37
|
type TaxCategory,
|
|
36
38
|
type Type,
|
|
37
39
|
type Zone,
|
|
38
|
-
InvalidJsonInputError,
|
|
39
40
|
} from '@commercetools/platform-sdk'
|
|
40
41
|
import assert from 'assert'
|
|
41
42
|
import { CommercetoolsError } from '../exceptions.js'
|
|
@@ -408,6 +409,23 @@ export class InMemoryStorage extends AbstractStorage {
|
|
|
408
409
|
private _resolveResource = (projectKey: string, obj: any, expand: string) => {
|
|
409
410
|
const params = parseExpandClause(expand)
|
|
410
411
|
|
|
412
|
+
// 'lineItems[*].variant' on ShoppingList is an exception, these variants are not references
|
|
413
|
+
if (params.index === '*') {
|
|
414
|
+
const reference = obj[params.element]
|
|
415
|
+
if (
|
|
416
|
+
params.element === 'lineItems' &&
|
|
417
|
+
params.rest?.startsWith('variant') &&
|
|
418
|
+
reference.every(
|
|
419
|
+
(item: any) =>
|
|
420
|
+
item.variant === undefined && item.variantId !== undefined
|
|
421
|
+
)
|
|
422
|
+
) {
|
|
423
|
+
reference.forEach((item: ShoppingListLineItem) => {
|
|
424
|
+
this._resolveShoppingListLineItemVariant(projectKey, item)
|
|
425
|
+
})
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
411
429
|
if (!params.index) {
|
|
412
430
|
const reference = obj[params.element]
|
|
413
431
|
if (reference === undefined) {
|
|
@@ -456,4 +474,24 @@ export class InMemoryStorage extends AbstractStorage {
|
|
|
456
474
|
}
|
|
457
475
|
}
|
|
458
476
|
}
|
|
477
|
+
private _resolveShoppingListLineItemVariant(
|
|
478
|
+
projectKey: string,
|
|
479
|
+
lineItem: ShoppingListLineItem
|
|
480
|
+
) {
|
|
481
|
+
const product = this.getByResourceIdentifier(projectKey, {
|
|
482
|
+
typeId: 'product',
|
|
483
|
+
id: lineItem.productId,
|
|
484
|
+
}) as Product | undefined
|
|
485
|
+
|
|
486
|
+
if (!product) {
|
|
487
|
+
return
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const variant = [
|
|
491
|
+
product.masterData.current.masterVariant,
|
|
492
|
+
...product.masterData.current.variants,
|
|
493
|
+
].find((e) => e.id === lineItem.variantId)
|
|
494
|
+
// @ts-ignore
|
|
495
|
+
lineItem.variant = variant
|
|
496
|
+
}
|
|
459
497
|
}
|