@labdigital/commercetools-mock 0.5.13 → 0.5.14

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.
Files changed (104) hide show
  1. package/README.md +6 -2
  2. package/dist/commercetools-mock.cjs.development.js +3058 -1645
  3. package/dist/commercetools-mock.cjs.development.js.map +1 -1
  4. package/dist/commercetools-mock.cjs.production.min.js +1 -1
  5. package/dist/commercetools-mock.cjs.production.min.js.map +1 -1
  6. package/dist/commercetools-mock.esm.js +3058 -1645
  7. package/dist/commercetools-mock.esm.js.map +1 -1
  8. package/dist/ctMock.d.ts +1 -0
  9. package/dist/repositories/abstract.d.ts +9 -7
  10. package/dist/repositories/cart-discount.d.ts +9 -0
  11. package/dist/repositories/cart.d.ts +16 -3
  12. package/dist/repositories/category.d.ts +18 -0
  13. package/dist/repositories/channel.d.ts +6 -0
  14. package/dist/repositories/custom-object.d.ts +2 -2
  15. package/dist/repositories/customer-group.d.ts +11 -0
  16. package/dist/repositories/customer.d.ts +2 -2
  17. package/dist/repositories/discount-code.d.ts +8 -0
  18. package/dist/repositories/errors.d.ts +2 -2
  19. package/dist/repositories/extension.d.ts +8 -0
  20. package/dist/repositories/inventory-entry.d.ts +2 -2
  21. package/dist/repositories/order.d.ts +2 -2
  22. package/dist/repositories/payment.d.ts +4 -3
  23. package/dist/repositories/product-projection.d.ts +2 -2
  24. package/dist/repositories/product-type.d.ts +5 -4
  25. package/dist/repositories/product.d.ts +2 -2
  26. package/dist/repositories/project.d.ts +8 -0
  27. package/dist/repositories/shipping-method.d.ts +7 -5
  28. package/dist/repositories/shopping-list.d.ts +2 -2
  29. package/dist/repositories/state.d.ts +5 -4
  30. package/dist/repositories/store.d.ts +6 -3
  31. package/dist/repositories/subscription.d.ts +6 -0
  32. package/dist/repositories/tax-category.d.ts +6 -5
  33. package/dist/repositories/type.d.ts +5 -3
  34. package/dist/repositories/zone.d.ts +8 -0
  35. package/dist/services/abstract.d.ts +4 -3
  36. package/dist/services/cart-discount.d.ts +9 -0
  37. package/dist/services/category.d.ts +9 -0
  38. package/dist/services/channel.d.ts +9 -0
  39. package/dist/services/customer-group.d.ts +9 -0
  40. package/dist/services/discount-code.d.ts +9 -0
  41. package/dist/services/extension.d.ts +9 -0
  42. package/dist/services/my-cart.d.ts +11 -0
  43. package/dist/services/project.d.ts +11 -0
  44. package/dist/services/subscription.d.ts +9 -0
  45. package/dist/services/zone.d.ts +9 -0
  46. package/dist/storage.d.ts +10 -1
  47. package/dist/types.d.ts +2 -1
  48. package/package.json +20 -20
  49. package/src/ctMock.ts +44 -17
  50. package/src/oauth/server.ts +3 -1
  51. package/src/repositories/abstract.ts +39 -33
  52. package/src/repositories/cart-discount.ts +140 -0
  53. package/src/repositories/cart.ts +247 -3
  54. package/src/repositories/category.ts +140 -0
  55. package/src/repositories/channel.ts +23 -0
  56. package/src/repositories/custom-object.ts +2 -2
  57. package/src/repositories/customer-group.ts +42 -0
  58. package/src/repositories/customer.ts +2 -2
  59. package/src/repositories/discount-code.ts +143 -0
  60. package/src/repositories/errors.ts +7 -2
  61. package/src/repositories/extension.ts +65 -0
  62. package/src/repositories/inventory-entry.ts +2 -2
  63. package/src/repositories/order.ts +2 -2
  64. package/src/repositories/payment.ts +10 -6
  65. package/src/repositories/product-projection.ts +2 -2
  66. package/src/repositories/product-type.ts +57 -4
  67. package/src/repositories/product.ts +4 -2
  68. package/src/repositories/project.ts +150 -0
  69. package/src/repositories/shipping-method.ts +149 -13
  70. package/src/repositories/shopping-list.ts +2 -2
  71. package/src/repositories/state.ts +48 -4
  72. package/src/repositories/store.ts +69 -4
  73. package/src/repositories/subscription.ts +50 -0
  74. package/src/repositories/tax-category.ts +80 -6
  75. package/src/repositories/type.ts +133 -3
  76. package/src/repositories/zone.ts +77 -0
  77. package/src/server.ts +6 -1
  78. package/src/services/abstract.ts +16 -15
  79. package/src/services/cart-discount.ts +17 -0
  80. package/src/services/cart.test.ts +314 -3
  81. package/src/services/category.test.ts +37 -0
  82. package/src/services/category.ts +17 -0
  83. package/src/services/channel.ts +17 -0
  84. package/src/services/custom-object.test.ts +3 -3
  85. package/src/services/customer-group.ts +17 -0
  86. package/src/services/discount-code.ts +17 -0
  87. package/src/services/extension.ts +17 -0
  88. package/src/services/inventory-entry.test.ts +3 -3
  89. package/src/services/my-cart.test.ts +93 -0
  90. package/src/services/my-cart.ts +44 -0
  91. package/src/services/my-payment.test.ts +2 -2
  92. package/src/services/order.test.ts +4 -4
  93. package/src/services/payment.test.ts +2 -2
  94. package/src/services/product-projection.test.ts +1 -5
  95. package/src/services/product-type.test.ts +2 -2
  96. package/src/services/product.test.ts +6 -2
  97. package/src/services/project.ts +42 -0
  98. package/src/services/shipping-method.test.ts +3 -3
  99. package/src/services/state.test.ts +2 -2
  100. package/src/services/subscription.ts +17 -0
  101. package/src/services/tax-category.test.ts +3 -3
  102. package/src/services/zone.ts +17 -0
  103. package/src/storage.ts +69 -1
  104. package/src/types.ts +2 -1
@@ -1,8 +1,22 @@
1
- import { Type, TypeDraft, ReferenceTypeId } from '@commercetools/platform-sdk'
1
+ import {
2
+ Type,
3
+ TypeDraft,
4
+ ReferenceTypeId,
5
+ TypeUpdateAction,
6
+ FieldDefinition,
7
+ TypeSetDescriptionAction,
8
+ TypeChangeNameAction,
9
+ TypeAddFieldDefinitionAction,
10
+ TypeChangeEnumValueLabelAction,
11
+ TypeAddEnumValueAction,
12
+ TypeChangeFieldDefinitionOrderAction,
13
+ TypeRemoveFieldDefinitionAction,
14
+ } from '@commercetools/platform-sdk'
15
+ import { Writable } from 'types'
2
16
  import { getBaseResourceProperties } from '../helpers'
3
- import AbstractRepository from './abstract'
17
+ import { AbstractResourceRepository } from './abstract'
4
18
 
5
- export class TypeRepository extends AbstractRepository {
19
+ export class TypeRepository extends AbstractResourceRepository {
6
20
  getTypeId(): ReferenceTypeId {
7
21
  return 'type'
8
22
  }
@@ -19,4 +33,120 @@ export class TypeRepository extends AbstractRepository {
19
33
  this.save(projectKey, resource)
20
34
  return resource
21
35
  }
36
+ actions: Partial<
37
+ Record<
38
+ TypeUpdateAction['action'],
39
+ (projectKey: string, resource: Writable<Type>, action: any) => void
40
+ >
41
+ > = {
42
+ addFieldDefinition: (
43
+ projectKey: string,
44
+ resource: Writable<Type>,
45
+ { fieldDefinition }: TypeAddFieldDefinitionAction
46
+ ) => {
47
+ resource.fieldDefinitions.push(fieldDefinition)
48
+ },
49
+ removeFieldDefinition: (
50
+ projectKey: string,
51
+ resource: Writable<Type>,
52
+ { fieldName }: TypeRemoveFieldDefinitionAction
53
+ ) => {
54
+ resource.fieldDefinitions = resource.fieldDefinitions.filter(f => {
55
+ return f.name !== fieldName
56
+ })
57
+ },
58
+ setDescription: (
59
+ projectKey: string,
60
+ resource: Writable<Type>,
61
+ { description }: TypeSetDescriptionAction
62
+ ) => {
63
+ resource.description = description
64
+ },
65
+ changeName: (
66
+ projectKey: string,
67
+ resource: Writable<Type>,
68
+ { name }: TypeChangeNameAction
69
+ ) => {
70
+ resource.name = name
71
+ },
72
+ changeFieldDefinitionOrder: (
73
+ projectKey: string,
74
+ resource: Writable<Type>,
75
+ { fieldNames }: TypeChangeFieldDefinitionOrderAction
76
+ ) => {
77
+ const fields = new Map(
78
+ resource.fieldDefinitions.map(item => [item.name, item])
79
+ )
80
+ const result: FieldDefinition[] = []
81
+ let current = resource.fieldDefinitions
82
+
83
+ fieldNames.forEach(fieldName => {
84
+ const field = fields.get(fieldName)
85
+ if (field === undefined) {
86
+ throw new Error('New field')
87
+ }
88
+ result.push(field)
89
+
90
+ // Remove from current items
91
+ current = current.filter(f => {
92
+ return f.name !== fieldName
93
+ })
94
+ })
95
+
96
+ resource.fieldDefinitions = result
97
+ // Add fields which were not specified in the order as last items. Not
98
+ // sure if this follows commercetools
99
+ resource.fieldDefinitions.push(...current)
100
+ },
101
+ addEnumValue: (
102
+ projectKey: string,
103
+ resource: Writable<Type>,
104
+ { fieldName, value }: TypeAddEnumValueAction
105
+ ) => {
106
+ resource.fieldDefinitions.forEach(field => {
107
+ if (field.name == fieldName) {
108
+ // TODO, should be done better i suppose
109
+ if (field.type.name == 'Enum') {
110
+ field.type.values.push(value)
111
+ } else if (
112
+ field.type.name == 'Set' &&
113
+ field.type.elementType.name == 'Enum'
114
+ ) {
115
+ field.type.elementType.values.push(value)
116
+ } else {
117
+ throw new Error('Type is not a Enum (or Set of Enum)')
118
+ }
119
+ }
120
+ })
121
+ },
122
+ changeEnumValueLabel: (
123
+ projectKey: string,
124
+ resource: Writable<Type>,
125
+ { fieldName, value }: TypeChangeEnumValueLabelAction
126
+ ) => {
127
+ resource.fieldDefinitions.forEach(field => {
128
+ if (field.name == fieldName) {
129
+ // TODO, should be done better i suppose
130
+ if (field.type.name == 'Enum') {
131
+ field.type.values.forEach(v => {
132
+ if (v.key == value.key) {
133
+ v.label = value.label
134
+ }
135
+ })
136
+ } else if (
137
+ field.type.name == 'Set' &&
138
+ field.type.elementType.name == 'Enum'
139
+ ) {
140
+ field.type.elementType.values.forEach(v => {
141
+ if (v.key == value.key) {
142
+ v.label = value.label
143
+ }
144
+ })
145
+ } else {
146
+ throw new Error('Type is not a Enum (or Set of Enum)')
147
+ }
148
+ }
149
+ })
150
+ },
151
+ }
22
152
  }
@@ -0,0 +1,77 @@
1
+ import {
2
+ ReferenceTypeId,
3
+ Zone,
4
+ ZoneAddLocationAction,
5
+ ZoneChangeNameAction,
6
+ ZoneDraft,
7
+ ZoneRemoveLocationAction,
8
+ ZoneSetDescriptionAction,
9
+ ZoneSetKeyAction,
10
+ ZoneUpdateAction,
11
+ } from '@commercetools/platform-sdk'
12
+ import { Writable } from 'types'
13
+ import { getBaseResourceProperties } from '../helpers'
14
+ import { AbstractResourceRepository } from './abstract'
15
+
16
+ export class ZoneRepository extends AbstractResourceRepository {
17
+ getTypeId(): ReferenceTypeId {
18
+ return 'zone'
19
+ }
20
+
21
+ create(projectKey: string, draft: ZoneDraft): Zone {
22
+ const resource: Zone = {
23
+ ...getBaseResourceProperties(),
24
+ key: draft.key,
25
+ locations: draft.locations || [],
26
+ name: draft.name,
27
+ description: draft.description,
28
+ }
29
+ this.save(projectKey, resource)
30
+ return resource
31
+ }
32
+
33
+ actions: Partial<
34
+ Record<
35
+ ZoneUpdateAction['action'],
36
+ (projectKey: string, resource: Writable<Zone>, action: any) => void
37
+ >
38
+ > = {
39
+ addLocation: (
40
+ projectKey: string,
41
+ resource: Writable<Zone>,
42
+ { location }: ZoneAddLocationAction
43
+ ) => {
44
+ resource.locations.push(location)
45
+ },
46
+ removeLocation: (
47
+ projectKey: string,
48
+ resource: Writable<Zone>,
49
+ { location }: ZoneRemoveLocationAction
50
+ ) => {
51
+ resource.locations = resource.locations.filter(loc => {
52
+ return !(loc.country == location.country && loc.state == location.state)
53
+ })
54
+ },
55
+ changeName: (
56
+ projectKey: string,
57
+ resource: Writable<Zone>,
58
+ { name }: ZoneChangeNameAction
59
+ ) => {
60
+ resource.name = name
61
+ },
62
+ setDescription: (
63
+ projectKey: string,
64
+ resource: Writable<Zone>,
65
+ { description }: ZoneSetDescriptionAction
66
+ ) => {
67
+ resource.description = description
68
+ },
69
+ setKey: (
70
+ projectKey: string,
71
+ resource: Writable<Zone>,
72
+ { key }: ZoneSetKeyAction
73
+ ) => {
74
+ resource.key = key
75
+ },
76
+ }
77
+ }
package/src/server.ts CHANGED
@@ -1,4 +1,9 @@
1
1
  import { CommercetoolsMock } from './index'
2
2
 
3
3
  const instance = new CommercetoolsMock()
4
- instance.runServer(3000)
4
+
5
+ let port = 3000
6
+
7
+ if (process.env.HTTP_SERVER_PORT) port = parseInt(process.env.HTTP_SERVER_PORT)
8
+
9
+ instance.runServer(port)
@@ -1,12 +1,13 @@
1
- import { QueryParams } from './../repositories/abstract'
2
1
  import { Update } from '@commercetools/platform-sdk'
3
2
  import { ParsedQs } from 'qs'
4
3
  import { Request, Response, Router } from 'express'
5
- import AbstractRepository from '../repositories/abstract'
4
+ import { AbstractResourceRepository } from '../repositories/abstract'
6
5
 
7
6
  export default abstract class AbstractService {
8
7
  protected abstract getBasePath(): string
9
- public abstract repository: AbstractRepository
8
+ public abstract repository: AbstractResourceRepository
9
+
10
+ createStatusCode = 201
10
11
 
11
12
  constructor(parent: Router) {
12
13
  this.registerRoutes(parent)
@@ -44,7 +45,12 @@ export default abstract class AbstractService {
44
45
  }
45
46
 
46
47
  getWithId(request: Request, response: Response) {
47
- return this._expandWithId(request, response, request.params['id'])
48
+ const result = this._expandWithId(request, request.params['id'])
49
+ if (!result) {
50
+ return response.status(404).send()
51
+ }
52
+ console.log(JSON.stringify(result, null, 4))
53
+ return response.status(200).send(result)
48
54
  }
49
55
 
50
56
  getWithKey(request: Request, response: Response) {
@@ -78,7 +84,8 @@ export default abstract class AbstractService {
78
84
  post(request: Request, response: Response) {
79
85
  const draft = request.body
80
86
  const resource = this.repository.create(request.params.projectKey, draft)
81
- return this._expandWithId(request, response, resource.id)
87
+ const result = this._expandWithId(request, resource.id)
88
+ return response.status(this.createStatusCode).send(result)
82
89
  }
83
90
 
84
91
  postWithId(request: Request, response: Response) {
@@ -101,25 +108,19 @@ export default abstract class AbstractService {
101
108
  updateRequest.actions
102
109
  )
103
110
 
104
- return this._expandWithId(request, response, updatedResource.id)
111
+ const result = this._expandWithId(request, updatedResource.id)
112
+ return response.status(200).send(result)
105
113
  }
106
114
 
107
115
  postWithKey(request: Request, response: Response) {
108
116
  return response.status(500).send('Not implemented')
109
117
  }
110
118
 
111
- protected _expandWithId(
112
- request: Request,
113
- response: Response,
114
- resourceId: string
115
- ) {
119
+ protected _expandWithId(request: Request, resourceId: string) {
116
120
  const result = this.repository.get(request.params.projectKey, resourceId, {
117
121
  expand: this._parseParam(request.query.expand),
118
122
  })
119
- if (!result) {
120
- return response.status(404).send('Not found')
121
- }
122
- return response.status(200).send(result)
123
+ return result
123
124
  }
124
125
 
125
126
  // No idea what i'm doing
@@ -0,0 +1,17 @@
1
+ import { Router } from 'express'
2
+ import AbstractService from './abstract'
3
+ import { AbstractStorage } from '../storage'
4
+ import { CartDiscountRepository } from '../repositories/cart-discount'
5
+
6
+ export class CartDiscountService extends AbstractService {
7
+ public repository: CartDiscountRepository
8
+
9
+ constructor(parent: Router, storage: AbstractStorage) {
10
+ super(parent)
11
+ this.repository = new CartDiscountRepository(storage)
12
+ }
13
+
14
+ getBasePath() {
15
+ return 'cart-discounts'
16
+ }
17
+ }
@@ -1,6 +1,12 @@
1
- import { Cart } from '@commercetools/platform-sdk'
1
+ import {
2
+ Address,
3
+ Cart,
4
+ CentPrecisionMoney,
5
+ ProductDraft,
6
+ } from '@commercetools/platform-sdk'
2
7
  import supertest from 'supertest'
3
8
  import { CommercetoolsMock } from '../index'
9
+ import assert from 'assert'
4
10
 
5
11
  describe('Carts Query', () => {
6
12
  const ctMock = new CommercetoolsMock()
@@ -32,7 +38,7 @@ describe('Carts Query', () => {
32
38
  },
33
39
  ],
34
40
  })
35
- expect(response.status).toBe(200)
41
+ expect(response.status).toBe(201)
36
42
 
37
43
  response = await supertest(ctMock.app)
38
44
  .post('/dummy/carts')
@@ -48,7 +54,7 @@ describe('Carts Query', () => {
48
54
  },
49
55
  },
50
56
  })
51
- expect(response.status).toBe(200)
57
+ expect(response.status).toBe(201)
52
58
  })
53
59
 
54
60
  test('no filter', async () => {
@@ -69,3 +75,308 @@ describe('Carts Query', () => {
69
75
  expect(myCart.custom?.type.obj?.description?.en).toBe('Test Type')
70
76
  })
71
77
  })
78
+
79
+ describe('Order Update Actions', () => {
80
+ const ctMock = new CommercetoolsMock()
81
+ let cart: Cart | undefined
82
+ const productDraft: ProductDraft = {
83
+ name: {
84
+ 'nl-NL': 'test product',
85
+ },
86
+ productType: {
87
+ typeId: 'product-type',
88
+ id: 'some-uuid',
89
+ },
90
+ masterVariant: {
91
+ sku: '1337',
92
+ prices: [
93
+ {
94
+ value: {
95
+ type: 'centPrecision',
96
+ currencyCode: 'EUR',
97
+ centAmount: 14900,
98
+ fractionDigits: 2,
99
+ } as CentPrecisionMoney,
100
+ },
101
+ ],
102
+
103
+ attributes: [
104
+ {
105
+ name: 'test',
106
+ value: 'test',
107
+ },
108
+ ],
109
+ },
110
+ variants: [
111
+ {
112
+ sku: '1338',
113
+ prices: [
114
+ {
115
+ value: {
116
+ type: 'centPrecision',
117
+ currencyCode: 'EUR',
118
+ centAmount: 14900,
119
+ fractionDigits: 2,
120
+ } as CentPrecisionMoney,
121
+ },
122
+ ],
123
+ attributes: [
124
+ {
125
+ name: 'test2',
126
+ value: 'test2',
127
+ },
128
+ ],
129
+ },
130
+ ],
131
+ slug: {
132
+ 'nl-NL': 'test-product',
133
+ },
134
+ publish: true,
135
+ }
136
+
137
+ beforeEach(async () => {
138
+ let response = await supertest(ctMock.app)
139
+ .post('/dummy/carts')
140
+ .send({
141
+ currency: 'EUR',
142
+ })
143
+ expect(response.status).toBe(201)
144
+ cart = response.body
145
+ })
146
+
147
+ afterEach(() => {
148
+ ctMock.clear()
149
+ })
150
+
151
+ test('no update', async () => {
152
+ assert(cart, 'cart not created')
153
+
154
+ const response = await supertest(ctMock.app)
155
+ .post(`/dummy/carts/${cart.id}`)
156
+ .send({
157
+ version: 1,
158
+ actions: [{ action: 'setLocale', locale: 'nl-NL' }],
159
+ })
160
+ expect(response.status).toBe(200)
161
+ expect(response.body.version).toBe(2)
162
+ expect(response.body.locale).toBe('nl-NL')
163
+
164
+ const responseAgain = await supertest(ctMock.app)
165
+ .post(`/dummy/carts/${cart.id}`)
166
+ .send({
167
+ version: 2,
168
+ actions: [{ action: 'setLocale', locale: 'nl-NL' }],
169
+ })
170
+ expect(responseAgain.status).toBe(200)
171
+ expect(responseAgain.body.version).toBe(2)
172
+ expect(responseAgain.body.locale).toBe('nl-NL')
173
+ })
174
+
175
+ test('addLineItem', async () => {
176
+ const product = await supertest(ctMock.app)
177
+ .post(`/dummy/products`)
178
+ .send(productDraft)
179
+ .then(x => x.body)
180
+
181
+ assert(cart, 'cart not created')
182
+ assert(product, 'product not created')
183
+
184
+ const response = await supertest(ctMock.app)
185
+ .post(`/dummy/carts/${cart.id}`)
186
+ .send({
187
+ version: 1,
188
+ actions: [
189
+ {
190
+ action: 'addLineItem',
191
+ productId: product.id,
192
+ variantId: product.masterData.current.variants[0].id,
193
+ },
194
+ ],
195
+ })
196
+ expect(response.status).toBe(200)
197
+ expect(response.body.version).toBe(2)
198
+ expect(response.body.lineItems).toHaveLength(1)
199
+ expect(response.body.totalPrice.centAmount).toEqual(14900)
200
+ })
201
+
202
+ test('addLineItem by SKU', async () => {
203
+ const product = await supertest(ctMock.app)
204
+ .post(`/dummy/products`)
205
+ .send(productDraft)
206
+ .then(x => x.body)
207
+
208
+ assert(cart, 'cart not created')
209
+ assert(product, 'product not created')
210
+
211
+ const response = await supertest(ctMock.app)
212
+ .post(`/dummy/carts/${cart.id}`)
213
+ .send({
214
+ version: 1,
215
+ actions: [{ action: 'addLineItem', sku: '1337', quantity: 2 }],
216
+ })
217
+ expect(response.status).toBe(200)
218
+ expect(response.body.version).toBe(2)
219
+ expect(response.body.lineItems).toHaveLength(1)
220
+ expect(response.body.totalPrice.centAmount).toEqual(29800)
221
+ })
222
+
223
+ test('addLineItem unknown product', async () => {
224
+ assert(cart, 'cart not created')
225
+
226
+ const response = await supertest(ctMock.app)
227
+ .post(`/dummy/carts/${cart.id}`)
228
+ .send({
229
+ version: 1,
230
+ actions: [{ action: 'addLineItem', productId: '123', variantId: 1 }],
231
+ })
232
+ expect(response.status).toBe(400)
233
+ expect(response.body.message).toBe("A product with ID '123' not found.")
234
+ })
235
+
236
+ test('removeLineItem', async () => {
237
+ const product = await supertest(ctMock.app)
238
+ .post(`/dummy/products`)
239
+ .send(productDraft)
240
+ .then(x => x.body)
241
+
242
+ assert(cart, 'cart not created')
243
+ assert(product, 'product not created')
244
+
245
+ const updatedCart = await supertest(ctMock.app)
246
+ .post(`/dummy/carts/${cart.id}`)
247
+ .send({
248
+ version: 1,
249
+ actions: [
250
+ {
251
+ action: 'addLineItem',
252
+ productId: product.id,
253
+ variantId: product.masterData.current.variants[0].id,
254
+ },
255
+ ],
256
+ })
257
+ const lineItem = updatedCart.body.lineItems[0]
258
+ assert(lineItem, 'lineItem not created')
259
+
260
+ expect(updatedCart.body.lineItems).toHaveLength(1)
261
+
262
+ const response = await supertest(ctMock.app)
263
+ .post(`/dummy/carts/${cart.id}`)
264
+ .send({
265
+ version: updatedCart.body.version,
266
+ actions: [{ action: 'removeLineItem', lineItemId: lineItem.id }],
267
+ })
268
+ expect(response.status).toBe(200)
269
+ expect(response.body.version).toBe(3)
270
+ expect(response.body.lineItems).toHaveLength(0)
271
+ })
272
+
273
+ test('removeLineItem decrease quantity', async () => {
274
+ const product = await supertest(ctMock.app)
275
+ .post(`/dummy/products`)
276
+ .send(productDraft)
277
+ .then(x => x.body)
278
+
279
+ assert(cart, 'cart not created')
280
+ assert(product, 'product not created')
281
+
282
+ const updatedCart = await supertest(ctMock.app)
283
+ .post(`/dummy/carts/${cart.id}`)
284
+ .send({
285
+ version: 1,
286
+ actions: [
287
+ {
288
+ action: 'addLineItem',
289
+ productId: product.id,
290
+ variantId: product.masterData.current.variants[0].id,
291
+ quantity: 2,
292
+ },
293
+ ],
294
+ })
295
+ const lineItem = updatedCart.body.lineItems[0]
296
+ assert(lineItem, 'lineItem not created')
297
+
298
+ expect(updatedCart.body.lineItems).toHaveLength(1)
299
+ expect(updatedCart.body.lineItems[0].quantity).toBe(2)
300
+
301
+ const response = await supertest(ctMock.app)
302
+ .post(`/dummy/carts/${cart.id}`)
303
+ .send({
304
+ version: updatedCart.body.version,
305
+ actions: [
306
+ { action: 'removeLineItem', lineItemId: lineItem.id, quantity: 1 },
307
+ ],
308
+ })
309
+ expect(response.status).toBe(200)
310
+ expect(response.body.version).toBe(3)
311
+ expect(response.body.lineItems).toHaveLength(1)
312
+ expect(response.body.lineItems[0].quantity).toBe(1)
313
+ })
314
+
315
+ test('setBillingAddress', async () => {
316
+ assert(cart, 'cart not created')
317
+
318
+ const address: Address = {
319
+ streetName: 'Street name',
320
+ city: 'Utrecht',
321
+ country: 'NL',
322
+ }
323
+
324
+ const response = await supertest(ctMock.app)
325
+ .post(`/dummy/carts/${cart.id}`)
326
+ .send({
327
+ version: 1,
328
+ actions: [{ action: 'setBillingAddress', address }],
329
+ })
330
+ expect(response.status).toBe(200)
331
+ expect(response.body.version).toBe(2)
332
+ expect(response.body.billingAddress).toEqual(address)
333
+ })
334
+
335
+ test('setCountry', async () => {
336
+ assert(cart, 'cart not created')
337
+
338
+ const response = await supertest(ctMock.app)
339
+ .post(`/dummy/carts/${cart.id}`)
340
+ .send({
341
+ version: 1,
342
+ actions: [{ action: 'setCountry', country: 'NL' }],
343
+ })
344
+ expect(response.status).toBe(200)
345
+ expect(response.body.version).toBe(2)
346
+ expect(response.body.country).toBe('NL')
347
+ })
348
+
349
+ test('setCustomerEmail', async () => {
350
+ assert(cart, 'cart not created')
351
+
352
+ const response = await supertest(ctMock.app)
353
+ .post(`/dummy/carts/${cart.id}`)
354
+ .send({
355
+ version: 1,
356
+ actions: [{ action: 'setCustomerEmail', email: 'john@doe.com' }],
357
+ })
358
+ expect(response.status).toBe(200)
359
+ expect(response.body.version).toBe(2)
360
+ expect(response.body.customerEmail).toBe('john@doe.com')
361
+ })
362
+
363
+ test('setShippingAddress', async () => {
364
+ assert(cart, 'cart not created')
365
+
366
+ const address: Address = {
367
+ streetName: 'Street name',
368
+ city: 'Utrecht',
369
+ country: 'NL',
370
+ }
371
+
372
+ const response = await supertest(ctMock.app)
373
+ .post(`/dummy/carts/${cart.id}`)
374
+ .send({
375
+ version: 1,
376
+ actions: [{ action: 'setShippingAddress', address }],
377
+ })
378
+ expect(response.status).toBe(200)
379
+ expect(response.body.version).toBe(2)
380
+ expect(response.body.shippingAddress).toEqual(address)
381
+ })
382
+ })
@@ -0,0 +1,37 @@
1
+ import { Category } from '@commercetools/platform-sdk'
2
+ import supertest from 'supertest'
3
+ import { CommercetoolsMock } from '../index'
4
+
5
+ describe('Categories Query', () => {
6
+ const ctMock = new CommercetoolsMock()
7
+
8
+ beforeEach(async () => {
9
+ let response
10
+ response = await supertest(ctMock.app)
11
+ .post('/dummy/categories')
12
+ .send({
13
+ name: {
14
+ en: 'Top hat',
15
+ },
16
+ slug: {
17
+ en: 'top-hat',
18
+ },
19
+ orderHint: '0.1',
20
+ })
21
+ expect(response.status).toBe(201)
22
+ })
23
+
24
+ test('no filter', async () => {
25
+ const response = await supertest(ctMock.app)
26
+ .get('/dummy/categories')
27
+ .query({})
28
+ .send()
29
+
30
+ expect(response.status).toBe(200)
31
+ expect(response.body.count).toBe(1)
32
+
33
+ const category = response.body.results[0] as Category
34
+
35
+ expect(category.name.en).toBe('Top hat')
36
+ })
37
+ })