@labdigital/commercetools-mock 0.10.1 → 0.12.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.global.js +123 -2
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +123 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +123 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/repositories/product.ts +178 -3
- package/src/repositories/project.ts +1 -0
- package/src/repositories/state.ts +8 -0
- package/src/services/product.test.ts +109 -1
- package/src/services/project.ts +2 -2
package/package.json
CHANGED
|
@@ -7,11 +7,14 @@ import {
|
|
|
7
7
|
ProductPublishAction,
|
|
8
8
|
ProductSetAttributeAction,
|
|
9
9
|
ProductSetDescriptionAction,
|
|
10
|
+
ProductAddExternalImageAction,
|
|
11
|
+
ProductRemoveImageAction,
|
|
10
12
|
ProductSetKeyAction,
|
|
11
13
|
ProductTypeReference,
|
|
12
14
|
ProductUpdateAction,
|
|
13
15
|
ProductVariant,
|
|
14
16
|
ProductVariantDraft,
|
|
17
|
+
ProductMoveImageToPositionAction,
|
|
15
18
|
} from '@commercetools/platform-sdk'
|
|
16
19
|
import { v4 as uuidv4 } from 'uuid'
|
|
17
20
|
import { Writable } from '../types'
|
|
@@ -183,6 +186,181 @@ export class ProductRepository extends AbstractResourceRepository<'product'> {
|
|
|
183
186
|
resource.key = key
|
|
184
187
|
return resource
|
|
185
188
|
},
|
|
189
|
+
addExternalImage: (
|
|
190
|
+
context: RepositoryContext,
|
|
191
|
+
resource: Writable<Product>,
|
|
192
|
+
{ variantId, sku, image, staged }: ProductAddExternalImageAction
|
|
193
|
+
) => {
|
|
194
|
+
const addImg = (data: Writable<ProductData>) => {
|
|
195
|
+
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
196
|
+
data,
|
|
197
|
+
variantId,
|
|
198
|
+
sku
|
|
199
|
+
)
|
|
200
|
+
if (!variant) {
|
|
201
|
+
throw new Error(
|
|
202
|
+
`Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (!variant.images) {
|
|
207
|
+
variant.images = []
|
|
208
|
+
} else {
|
|
209
|
+
const existingImage = variant.images.find((x) => x.url === image.url)
|
|
210
|
+
if (existingImage) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
`Cannot add image '${image.url}' because product '${resource.id}' already has that image.`
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Add image
|
|
218
|
+
variant.images.push(image)
|
|
219
|
+
|
|
220
|
+
if (isMasterVariant) {
|
|
221
|
+
data.masterVariant = variant
|
|
222
|
+
} else {
|
|
223
|
+
data.variants[variantIndex] = variant
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// If true, only the staged Attribute is set. If false, both current and
|
|
228
|
+
// staged Attribute is set. Default is true
|
|
229
|
+
const onlyStaged = staged !== undefined ? staged : true
|
|
230
|
+
|
|
231
|
+
// Write the attribute to the staged data
|
|
232
|
+
addImg(resource.masterData.staged)
|
|
233
|
+
|
|
234
|
+
// Also write to published data is isStaged = false
|
|
235
|
+
// if isStaged is false we set the attribute on both the staged and
|
|
236
|
+
// published data.
|
|
237
|
+
if (!onlyStaged) {
|
|
238
|
+
addImg(resource.masterData.current)
|
|
239
|
+
}
|
|
240
|
+
checkForStagedChanges(resource)
|
|
241
|
+
|
|
242
|
+
return resource
|
|
243
|
+
},
|
|
244
|
+
removeImage: (
|
|
245
|
+
context: RepositoryContext,
|
|
246
|
+
resource: Writable<Product>,
|
|
247
|
+
{ variantId, sku, imageUrl, staged }: ProductRemoveImageAction
|
|
248
|
+
) => {
|
|
249
|
+
const removeImg = (data: Writable<ProductData>) => {
|
|
250
|
+
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
251
|
+
data,
|
|
252
|
+
variantId,
|
|
253
|
+
sku
|
|
254
|
+
)
|
|
255
|
+
if (!variant) {
|
|
256
|
+
throw new Error(
|
|
257
|
+
`Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
|
|
258
|
+
)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const variantImages = variant.images ?? []
|
|
262
|
+
const existingImage = variantImages.find((x) => x.url === imageUrl)
|
|
263
|
+
if (!existingImage) {
|
|
264
|
+
throw new Error(
|
|
265
|
+
`Cannot remove image '${imageUrl}' because product '${resource.id}' does not have that image.`
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Remove image
|
|
270
|
+
variant.images = variantImages.filter((image) => image.url !== imageUrl)
|
|
271
|
+
|
|
272
|
+
if (isMasterVariant) {
|
|
273
|
+
data.masterVariant = variant
|
|
274
|
+
} else {
|
|
275
|
+
data.variants[variantIndex] = variant
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// If true, only the staged Attribute is set. If false, both current and
|
|
280
|
+
// staged Attribute is set. Default is true
|
|
281
|
+
const onlyStaged = staged !== undefined ? staged : true
|
|
282
|
+
|
|
283
|
+
// Write the attribute to the staged data
|
|
284
|
+
removeImg(resource.masterData.staged)
|
|
285
|
+
|
|
286
|
+
// Also write to published data is isStaged = false
|
|
287
|
+
// if isStaged is false we set the attribute on both the staged and
|
|
288
|
+
// published data.
|
|
289
|
+
if (!onlyStaged) {
|
|
290
|
+
removeImg(resource.masterData.current)
|
|
291
|
+
}
|
|
292
|
+
checkForStagedChanges(resource)
|
|
293
|
+
|
|
294
|
+
return resource
|
|
295
|
+
},
|
|
296
|
+
moveImageToPosition: (
|
|
297
|
+
context: RepositoryContext,
|
|
298
|
+
resource: Writable<Product>,
|
|
299
|
+
{
|
|
300
|
+
variantId,
|
|
301
|
+
sku,
|
|
302
|
+
imageUrl,
|
|
303
|
+
position,
|
|
304
|
+
staged,
|
|
305
|
+
}: ProductMoveImageToPositionAction
|
|
306
|
+
) => {
|
|
307
|
+
const moveImg = (data: Writable<ProductData>) => {
|
|
308
|
+
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
309
|
+
data,
|
|
310
|
+
variantId,
|
|
311
|
+
sku
|
|
312
|
+
)
|
|
313
|
+
if (!variant) {
|
|
314
|
+
throw new Error(
|
|
315
|
+
`Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const variantImages = variant.images ?? []
|
|
320
|
+
const existingImage = variantImages.find((x) => x.url === imageUrl)
|
|
321
|
+
if (!existingImage) {
|
|
322
|
+
throw new Error(
|
|
323
|
+
`Cannot move image '${imageUrl}' because product '${resource.id}' does not have that image.`
|
|
324
|
+
)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (position >= variantImages.length) {
|
|
328
|
+
throw new Error(
|
|
329
|
+
`Invalid position given. Position in images where the image should be moved. Must be between 0 and the total number of images minus 1.`
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Remove image
|
|
334
|
+
variant.images = variantImages.filter((image) => image.url !== imageUrl)
|
|
335
|
+
|
|
336
|
+
// Re-add image to the correct position
|
|
337
|
+
variant.images.splice(position, 0, existingImage)
|
|
338
|
+
|
|
339
|
+
if (isMasterVariant) {
|
|
340
|
+
data.masterVariant = variant
|
|
341
|
+
} else {
|
|
342
|
+
data.variants[variantIndex] = variant
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// If true, only the staged Attribute is set. If false, both current and
|
|
347
|
+
// staged Attribute is set. Default is true
|
|
348
|
+
const onlyStaged = staged !== undefined ? staged : true
|
|
349
|
+
|
|
350
|
+
// Write the attribute to the staged data
|
|
351
|
+
moveImg(resource.masterData.staged)
|
|
352
|
+
|
|
353
|
+
// Also write to published data is isStaged = false
|
|
354
|
+
// if isStaged is false we set the attribute on both the staged and
|
|
355
|
+
// published data.
|
|
356
|
+
if (!onlyStaged) {
|
|
357
|
+
moveImg(resource.masterData.current)
|
|
358
|
+
}
|
|
359
|
+
checkForStagedChanges(resource)
|
|
360
|
+
|
|
361
|
+
return resource
|
|
362
|
+
},
|
|
363
|
+
|
|
186
364
|
// 'changeName': () => {},
|
|
187
365
|
// 'changeSlug': () => {},
|
|
188
366
|
// 'addVariant': () => {},
|
|
@@ -202,9 +380,6 @@ export class ProductRepository extends AbstractResourceRepository<'product'> {
|
|
|
202
380
|
// 'setTaxCategory': () => {},
|
|
203
381
|
// 'setSku': () => {},
|
|
204
382
|
// 'setProductVariantKey': () => {},
|
|
205
|
-
// 'addExternalImage': () => {},
|
|
206
|
-
// 'moveImageToPosition': () => {},
|
|
207
|
-
// 'removeImage': () => {},
|
|
208
383
|
// 'setImageLabel': () => {},
|
|
209
384
|
// 'addAsset': () => {},
|
|
210
385
|
// 'removeAsset': () => {},
|
|
@@ -83,6 +83,7 @@ export class ProjectRepository extends AbstractRepository<Project> {
|
|
|
83
83
|
{ messagesConfiguration }: ProjectChangeMessagesConfigurationAction
|
|
84
84
|
) => {
|
|
85
85
|
resource.messages.enabled = messagesConfiguration.enabled
|
|
86
|
+
resource.messages.deleteDaysAfterCreation = messagesConfiguration.deleteDaysAfterCreation
|
|
86
87
|
},
|
|
87
88
|
changeProductSearchIndexingEnabled: (
|
|
88
89
|
context: RepositoryContext,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
State,
|
|
3
|
+
StateChangeInitialAction,
|
|
3
4
|
StateChangeKeyAction,
|
|
4
5
|
StateDraft,
|
|
5
6
|
StateReference,
|
|
@@ -51,6 +52,13 @@ export class StateRepository extends AbstractResourceRepository<'state'> {
|
|
|
51
52
|
) => {
|
|
52
53
|
resource.key = key
|
|
53
54
|
},
|
|
55
|
+
changeInitial: (
|
|
56
|
+
context: RepositoryContext,
|
|
57
|
+
resource: Writable<State>,
|
|
58
|
+
{initial }: StateChangeInitialAction
|
|
59
|
+
) => {
|
|
60
|
+
resource.initial = initial
|
|
61
|
+
},
|
|
54
62
|
setDescription: (
|
|
55
63
|
context: RepositoryContext,
|
|
56
64
|
resource: Writable<State>,
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Image,
|
|
3
|
+
Product,
|
|
4
|
+
ProductData,
|
|
5
|
+
ProductDraft,
|
|
6
|
+
} from '@commercetools/platform-sdk'
|
|
2
7
|
import assert from 'assert'
|
|
3
8
|
import supertest from 'supertest'
|
|
4
9
|
import { CommercetoolsMock } from '../index'
|
|
@@ -294,4 +299,107 @@ describe('Product update actions', () => {
|
|
|
294
299
|
const attr = response.body.masterData.staged.masterVariant.attributes[0]
|
|
295
300
|
expect(attr).toEqual({ name: 'test', value: 'foo' })
|
|
296
301
|
})
|
|
302
|
+
|
|
303
|
+
test('addExternalImage variant', async () => {
|
|
304
|
+
assert(productPublished, 'product not created')
|
|
305
|
+
|
|
306
|
+
const image: Image = {
|
|
307
|
+
url: 'http://example.com/image',
|
|
308
|
+
dimensions: { w: 100, h: 100 },
|
|
309
|
+
}
|
|
310
|
+
const response = await supertest(ctMock.app)
|
|
311
|
+
.post(`/dummy/products/${productPublished.id}`)
|
|
312
|
+
.send({
|
|
313
|
+
version: 1,
|
|
314
|
+
actions: [{ action: 'addExternalImage', sku: '1338', image }],
|
|
315
|
+
})
|
|
316
|
+
expect(response.status).toBe(200)
|
|
317
|
+
expect(response.body.version).toBe(2)
|
|
318
|
+
expect(response.body.masterData.staged.variants[0].images).toHaveLength(1)
|
|
319
|
+
const attr = response.body.masterData.staged.variants[0].images[0]
|
|
320
|
+
expect(attr).toEqual(image)
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
test('removeImage variant', async () => {
|
|
324
|
+
assert(productPublished, 'product not created')
|
|
325
|
+
|
|
326
|
+
const image: Image = {
|
|
327
|
+
url: 'http://example.com/image',
|
|
328
|
+
dimensions: { w: 100, h: 100 },
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
{
|
|
332
|
+
const response = await supertest(ctMock.app)
|
|
333
|
+
.post(`/dummy/products/${productPublished.id}`)
|
|
334
|
+
.send({
|
|
335
|
+
version: 1,
|
|
336
|
+
actions: [{ action: 'addExternalImage', sku: '1338', image }],
|
|
337
|
+
})
|
|
338
|
+
expect(response.status).toBe(200)
|
|
339
|
+
expect(response.body.version).toBe(2)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const response = await supertest(ctMock.app)
|
|
343
|
+
.post(`/dummy/products/${productPublished.id}`)
|
|
344
|
+
.send({
|
|
345
|
+
version: 2,
|
|
346
|
+
actions: [
|
|
347
|
+
{
|
|
348
|
+
action: 'removeImage',
|
|
349
|
+
sku: '1338',
|
|
350
|
+
imageUrl: image.url,
|
|
351
|
+
},
|
|
352
|
+
],
|
|
353
|
+
})
|
|
354
|
+
expect(response.status).toBe(200)
|
|
355
|
+
expect(response.body.version).toBe(3)
|
|
356
|
+
expect(response.body.masterData.staged.variants[0].images).toHaveLength(0)
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
test('moveImageToPosition variant', async () => {
|
|
360
|
+
assert(productPublished, 'product not created')
|
|
361
|
+
|
|
362
|
+
const image1: Image = {
|
|
363
|
+
url: 'http://example.com/image1',
|
|
364
|
+
dimensions: { w: 100, h: 100 },
|
|
365
|
+
}
|
|
366
|
+
const image2: Image = {
|
|
367
|
+
url: 'http://example.com/image2',
|
|
368
|
+
dimensions: { w: 100, h: 100 },
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
{
|
|
372
|
+
const response = await supertest(ctMock.app)
|
|
373
|
+
.post(`/dummy/products/${productPublished.id}`)
|
|
374
|
+
.send({
|
|
375
|
+
version: 1,
|
|
376
|
+
actions: [
|
|
377
|
+
{ action: 'addExternalImage', sku: '1338', image: image1 },
|
|
378
|
+
{ action: 'addExternalImage', sku: '1338', image: image2 },
|
|
379
|
+
],
|
|
380
|
+
})
|
|
381
|
+
expect(response.status).toBe(200)
|
|
382
|
+
expect(response.body.version).toBe(3)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const response = await supertest(ctMock.app)
|
|
386
|
+
.post(`/dummy/products/${productPublished.id}`)
|
|
387
|
+
.send({
|
|
388
|
+
version: 3,
|
|
389
|
+
actions: [
|
|
390
|
+
{
|
|
391
|
+
action: 'moveImageToPosition',
|
|
392
|
+
sku: '1338',
|
|
393
|
+
imageUrl: image2.url,
|
|
394
|
+
position: 0,
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
})
|
|
398
|
+
expect(response.status).toBe(200)
|
|
399
|
+
expect(response.body.version).toBe(4)
|
|
400
|
+
expect(response.body.masterData.staged.variants[0].images).toEqual([
|
|
401
|
+
{ url: 'http://example.com/image2', dimensions: { w: 100, h: 100 } },
|
|
402
|
+
{ url: 'http://example.com/image1', dimensions: { w: 100, h: 100 } },
|
|
403
|
+
])
|
|
404
|
+
})
|
|
297
405
|
})
|
package/src/services/project.ts
CHANGED
|
@@ -29,13 +29,13 @@ export class ProjectService {
|
|
|
29
29
|
return response.status(404).send({})
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
this.repository.processUpdateActions(
|
|
32
|
+
const updatedResource = this.repository.processUpdateActions(
|
|
33
33
|
getRepositoryContext(request),
|
|
34
34
|
project,
|
|
35
35
|
updateRequest.version,
|
|
36
36
|
updateRequest.actions
|
|
37
37
|
)
|
|
38
38
|
|
|
39
|
-
return response.status(200).send(
|
|
39
|
+
return response.status(200).send(updatedResource)
|
|
40
40
|
}
|
|
41
41
|
}
|