@labdigital/commercetools-mock 1.8.1 → 1.9.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@labdigital/commercetools-mock",
3
3
  "author": "Michael van Tellingen",
4
- "version": "1.8.1",
4
+ "version": "1.9.0",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",
@@ -1,14 +1,215 @@
1
- import type { BusinessUnit } from '@commercetools/platform-sdk'
1
+ import {
2
+ type Associate,
3
+ type BusinessUnit,
4
+ type BusinessUnitAddAddressAction,
5
+ type BusinessUnitAddAssociateAction,
6
+ type BusinessUnitAddStoreAction,
7
+ type BusinessUnitChangeAddressAction,
8
+ type BusinessUnitChangeNameAction,
9
+ type BusinessUnitChangeParentUnitAction,
10
+ type BusinessUnitDraft,
11
+ type BusinessUnitSetAssociatesAction,
12
+ type BusinessUnitSetContactEmailAction,
13
+ type BusinessUnitSetStoreModeAction,
14
+ type Company,
15
+ type Division,
16
+ BusinessUnitChangeStatusAction,
17
+ CompanyDraft,
18
+ DivisionDraft,
19
+ } from '@commercetools/platform-sdk'
2
20
  import {
3
21
  AbstractResourceRepository,
4
22
  type RepositoryContext,
5
23
  } from './abstract.js'
24
+ import { getBaseResourceProperties } from '../helpers.js'
25
+ import {
26
+ createAddress,
27
+ createAssociate,
28
+ createCustomFields,
29
+ getBusinessUnitKeyReference,
30
+ getStoreKeyReference,
31
+ } from './helpers.js'
32
+ import { Writable } from '../types.js'
6
33
 
7
34
  export class BusinessUnitRepository extends AbstractResourceRepository<'business-unit'> {
8
35
  getTypeId() {
9
36
  return 'business-unit' as const
10
37
  }
11
- create(context: RepositoryContext, draft: any): BusinessUnit {
12
- throw new Error('Method not implemented.')
38
+
39
+ private _isCompanyDraft(draft: BusinessUnitDraft): draft is CompanyDraft {
40
+ return draft.unitType === 'Company'
41
+ }
42
+
43
+ private _isDivisionDraft(draft: BusinessUnitDraft): draft is DivisionDraft {
44
+ return draft.unitType === 'Division'
45
+ }
46
+
47
+ create(context: RepositoryContext, draft: BusinessUnitDraft): BusinessUnit {
48
+ const resource = {
49
+ ...getBaseResourceProperties(),
50
+ key: draft.key,
51
+ status: draft.status,
52
+ stores: draft.stores?.map((s) =>
53
+ getStoreKeyReference(s, context.projectKey, this._storage)
54
+ ),
55
+ storeMode: draft.storeMode,
56
+ name: draft.name,
57
+ contactEmail: draft.contactEmail,
58
+ addresses: draft.addresses?.map((a) =>
59
+ createAddress(a, context.projectKey, this._storage)
60
+ ),
61
+ custom: createCustomFields(
62
+ draft.custom,
63
+ context.projectKey,
64
+ this._storage
65
+ ),
66
+ shippingAddressIds: draft.shippingAddresses,
67
+ defaultShippingAddressId: draft.defaultShippingAddress,
68
+ billingAddressIds: draft.billingAddresses,
69
+ associateMode: draft.associateMode,
70
+ associates: draft.associates?.map((a) =>
71
+ createAssociate(a, context.projectKey, this._storage)
72
+ ),
73
+ }
74
+
75
+ if (this._isDivisionDraft(draft)) {
76
+ const division = {
77
+ ...resource,
78
+ parentUnit: getBusinessUnitKeyReference(
79
+ draft.parentUnit,
80
+ context.projectKey,
81
+ this._storage
82
+ ),
83
+ } as Division
84
+
85
+ this.saveNew(context, division)
86
+ return division
87
+ } else if (this._isCompanyDraft(draft)) {
88
+ const company = resource as Company
89
+
90
+ this.saveNew(context, company)
91
+ return company
92
+ }
93
+
94
+ throw new Error('Invalid business unit type')
95
+ }
96
+
97
+ actions = {
98
+ addAddress: (
99
+ context: RepositoryContext,
100
+ resource: Writable<BusinessUnit>,
101
+ { address }: BusinessUnitAddAddressAction
102
+ ) => {
103
+ const newAddress = createAddress(
104
+ address,
105
+ context.projectKey,
106
+ this._storage
107
+ )
108
+ if (newAddress) {
109
+ resource.addresses.push(newAddress)
110
+ }
111
+ },
112
+ addAssociate: (
113
+ context: RepositoryContext,
114
+ resource: Writable<BusinessUnit>,
115
+ { associate }: BusinessUnitAddAssociateAction
116
+ ) => {
117
+ const newAssociate = createAssociate(
118
+ associate,
119
+ context.projectKey,
120
+ this._storage
121
+ )
122
+ if (newAssociate) {
123
+ resource.associates.push(newAssociate)
124
+ }
125
+ },
126
+ setAssociates: (
127
+ context: RepositoryContext,
128
+ resource: Writable<BusinessUnit>,
129
+ { associates }: BusinessUnitSetAssociatesAction
130
+ ) => {
131
+ const newAssociates = associates
132
+ .map((a) => createAssociate(a, context.projectKey, this._storage))
133
+ .filter((a): a is Writable<Associate> => a !== undefined)
134
+ resource.associates = newAssociates || undefined
135
+ },
136
+ setContactEmail: (
137
+ context: RepositoryContext,
138
+ resource: Writable<BusinessUnit>,
139
+ { contactEmail }: BusinessUnitSetContactEmailAction
140
+ ) => {
141
+ resource.contactEmail = contactEmail
142
+ },
143
+ setStoreMode: (
144
+ context: RepositoryContext,
145
+ resource: Writable<BusinessUnit>,
146
+ { storeMode }: BusinessUnitSetStoreModeAction
147
+ ) => {
148
+ resource.storeMode = storeMode
149
+ },
150
+ changeAssociateMode: (
151
+ context: RepositoryContext,
152
+ resource: Writable<BusinessUnit>,
153
+ { storeMode }: BusinessUnitSetStoreModeAction
154
+ ) => {
155
+ resource.associateMode = storeMode
156
+ },
157
+ changeName: (
158
+ context: RepositoryContext,
159
+ resource: Writable<BusinessUnit>,
160
+ { name }: BusinessUnitChangeNameAction
161
+ ) => {
162
+ resource.name = name
163
+ },
164
+ changeAddress: (
165
+ context: RepositoryContext,
166
+ resource: Writable<BusinessUnit>,
167
+ { address }: BusinessUnitChangeAddressAction
168
+ ) => {
169
+ const newAddress = createAddress(
170
+ address,
171
+ context.projectKey,
172
+ this._storage
173
+ )
174
+ if (newAddress) {
175
+ resource.addresses.push(newAddress)
176
+ }
177
+ },
178
+ addStore: (
179
+ context: RepositoryContext,
180
+ resource: Writable<BusinessUnit>,
181
+ { store }: BusinessUnitAddStoreAction
182
+ ) => {
183
+ const newStore = getStoreKeyReference(
184
+ store,
185
+ context.projectKey,
186
+ this._storage
187
+ )
188
+ if (newStore) {
189
+ if (!resource.stores) {
190
+ resource.stores = []
191
+ }
192
+
193
+ resource.stores.push(newStore)
194
+ }
195
+ },
196
+ changeParentUnit: (
197
+ context: RepositoryContext,
198
+ resource: Writable<BusinessUnit>,
199
+ { parentUnit }: BusinessUnitChangeParentUnitAction
200
+ ) => {
201
+ resource.parentUnit = getBusinessUnitKeyReference(
202
+ parentUnit,
203
+ context.projectKey,
204
+ this._storage
205
+ )
206
+ },
207
+ changeStatus: (
208
+ context: RepositoryContext,
209
+ resource: Writable<BusinessUnit>,
210
+ { status }: BusinessUnitChangeStatusAction
211
+ ) => {
212
+ resource.status = status
213
+ },
13
214
  }
14
215
  }
@@ -5,6 +5,7 @@ import type {
5
5
  CartDiscountChangeTargetAction,
6
6
  CartDiscountDraft,
7
7
  CartDiscountSetCustomFieldAction,
8
+ CartDiscountSetCustomTypeAction,
8
9
  CartDiscountSetDescriptionAction,
9
10
  CartDiscountSetKeyAction,
10
11
  CartDiscountSetValidFromAction,
@@ -162,7 +163,6 @@ export class CartDiscountRepository extends AbstractResourceRepository<'cart-dis
162
163
  ) => {
163
164
  resource.target = target
164
165
  },
165
-
166
166
  setCustomField: (
167
167
  context: RepositoryContext,
168
168
  resource: Writable<CartDiscount>,
@@ -190,5 +190,30 @@ export class CartDiscountRepository extends AbstractResourceRepository<'cart-dis
190
190
  resource.custom.fields[name] = value
191
191
  }
192
192
  },
193
+ setCustomType: (
194
+ context: RepositoryContext,
195
+ resource: Writable<CartDiscount>,
196
+ { type, fields }: CartDiscountSetCustomTypeAction
197
+ ) => {
198
+ if (!type) {
199
+ resource.custom = undefined
200
+ } else {
201
+ const resolvedType = this._storage.getByResourceIdentifier(
202
+ context.projectKey,
203
+ type
204
+ )
205
+ if (!resolvedType) {
206
+ throw new Error(`Type ${type} not found`)
207
+ }
208
+
209
+ resource.custom = {
210
+ type: {
211
+ typeId: 'type',
212
+ id: resolvedType.id,
213
+ },
214
+ fields: fields || {},
215
+ }
216
+ }
217
+ },
193
218
  }
194
219
  }
@@ -1,24 +1,34 @@
1
- import type {
2
- Address,
3
- BaseAddress,
4
- CentPrecisionMoney,
5
- CustomFields,
6
- CustomFieldsDraft,
7
- HighPrecisionMoney,
8
- HighPrecisionMoneyDraft,
9
- InvalidJsonInputError,
10
- Price,
11
- PriceDraft,
12
- Reference,
13
- ReferencedResourceNotFoundError,
14
- ResourceIdentifier,
15
- Store,
16
- StoreKeyReference,
17
- StoreReference,
18
- StoreResourceIdentifier,
19
- Type,
20
- TypedMoney,
21
- _Money,
1
+ import {
2
+ AssociateRoleReference,
3
+ type Address,
4
+ type Associate,
5
+ type AssociateDraft,
6
+ type AssociateRoleAssignment,
7
+ type AssociateRoleAssignmentDraft,
8
+ type AssociateRoleKeyReference,
9
+ type AssociateRoleResourceIdentifier,
10
+ type BaseAddress,
11
+ type CentPrecisionMoney,
12
+ type CustomFields,
13
+ type CustomFieldsDraft,
14
+ type HighPrecisionMoney,
15
+ type HighPrecisionMoneyDraft,
16
+ type InvalidJsonInputError,
17
+ type Price,
18
+ type PriceDraft,
19
+ type Reference,
20
+ type ReferencedResourceNotFoundError,
21
+ type ResourceIdentifier,
22
+ type Store,
23
+ type StoreKeyReference,
24
+ type StoreReference,
25
+ type StoreResourceIdentifier,
26
+ type Type,
27
+ type TypedMoney,
28
+ type _Money,
29
+ BusinessUnitResourceIdentifier,
30
+ BusinessUnitKeyReference,
31
+ BusinessUnitReference,
22
32
  } from '@commercetools/platform-sdk'
23
33
  import type { Request } from 'express'
24
34
  import { v4 as uuidv4 } from 'uuid'
@@ -219,3 +229,90 @@ export const getRepositoryContext = (request: Request): RepositoryContext => ({
219
229
  projectKey: request.params.projectKey,
220
230
  storeKey: request.params.storeKey,
221
231
  })
232
+
233
+ export const createAssociate = (
234
+ a: AssociateDraft,
235
+ projectKey: string,
236
+ storage: AbstractStorage
237
+ ): Associate | undefined => {
238
+ if (!a) return undefined
239
+
240
+ if (!a.associateRoleAssignments) {
241
+ throw new Error('AssociateRoleAssignments is required')
242
+ }
243
+
244
+ return {
245
+ customer: getReferenceFromResourceIdentifier(
246
+ a.customer,
247
+ projectKey,
248
+ storage
249
+ ),
250
+ associateRoleAssignments: a.associateRoleAssignments?.map(
251
+ (a: AssociateRoleAssignmentDraft): AssociateRoleAssignment => ({
252
+ associateRole: getAssociateRoleKeyReference(
253
+ a.associateRole,
254
+ projectKey,
255
+ storage
256
+ ),
257
+ inheritance: a.inheritance as string,
258
+ })
259
+ ),
260
+ roles: a.roles as string[],
261
+ }
262
+ }
263
+
264
+ export const getAssociateRoleKeyReference = (
265
+ id: AssociateRoleResourceIdentifier,
266
+ projectKey: string,
267
+ storage: AbstractStorage
268
+ ): AssociateRoleKeyReference => {
269
+ if (id.key) {
270
+ return {
271
+ typeId: 'associate-role',
272
+ key: id.key,
273
+ }
274
+ }
275
+
276
+ const value = getReferenceFromResourceIdentifier<AssociateRoleReference>(
277
+ id,
278
+ projectKey,
279
+ storage
280
+ )
281
+
282
+ if (!value.obj?.key) {
283
+ throw new Error('No associate-role found for reference')
284
+ }
285
+
286
+ return {
287
+ typeId: 'associate-role',
288
+ key: value.obj?.key,
289
+ }
290
+ }
291
+
292
+ export const getBusinessUnitKeyReference = (
293
+ id: BusinessUnitResourceIdentifier,
294
+ projectKey: string,
295
+ storage: AbstractStorage
296
+ ): BusinessUnitKeyReference => {
297
+ if (id.key) {
298
+ return {
299
+ typeId: 'business-unit',
300
+ key: id.key,
301
+ }
302
+ }
303
+
304
+ const value = getReferenceFromResourceIdentifier<BusinessUnitReference>(
305
+ id,
306
+ projectKey,
307
+ storage
308
+ )
309
+
310
+ if (!value.obj?.key) {
311
+ throw new Error('No business-unit found for reference')
312
+ }
313
+
314
+ return {
315
+ typeId: 'business-unit',
316
+ key: value.obj?.key,
317
+ }
318
+ }
@@ -0,0 +1,42 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from 'vitest'
2
+ import { CommercetoolsMock } from '../ctMock.js'
3
+ import { BusinessUnit } from '@commercetools/platform-sdk'
4
+ import supertest from 'supertest'
5
+
6
+ describe('Business units query', () => {
7
+ const ctMock = new CommercetoolsMock()
8
+ let businessUnit: BusinessUnit | undefined
9
+
10
+ beforeEach(async () => {
11
+ const response = await supertest(ctMock.app)
12
+ .post('/dummy/business-units')
13
+ .send({
14
+ key: 'example-business-unit',
15
+ status: 'Active',
16
+ name: 'Example Business Unit',
17
+ unitType: 'Company',
18
+ })
19
+
20
+ expect(response.status).toBe(201)
21
+
22
+ businessUnit = response.body as BusinessUnit
23
+ })
24
+
25
+ afterEach(() => {
26
+ ctMock.clear()
27
+ })
28
+
29
+ test('no filter', async () => {
30
+ const response = await supertest(ctMock.app)
31
+ .get('/dummy/business-units')
32
+ .query('{}')
33
+ .send()
34
+
35
+ expect(response.status).toBe(200)
36
+ expect(response.body.count).toBe(1)
37
+
38
+ const businessUnit = response.body.results[0] as BusinessUnit
39
+
40
+ expect(businessUnit.key).toBe('example-business-unit')
41
+ })
42
+ })
@@ -0,0 +1,17 @@
1
+ import { Router } from 'express'
2
+ import { BusinessUnitRepository } from '../repositories/business-unit.js'
3
+ import AbstractService from './abstract.js'
4
+
5
+ export class BusinessUnitServices extends AbstractService {
6
+ public repository: BusinessUnitRepository
7
+
8
+ constructor(parent: Router, repository: BusinessUnitRepository) {
9
+ super(parent)
10
+
11
+ this.repository = repository
12
+ }
13
+
14
+ protected getBasePath(): string {
15
+ return 'business-units'
16
+ }
17
+ }
@@ -359,4 +359,22 @@ describe('Cart Discounts Update Actions', () => {
359
359
  })
360
360
  expect(response.status).toBe(400)
361
361
  })
362
+
363
+ test('remove all custom fields', async () => {
364
+ assert(cartDiscount, 'cart discount not created')
365
+
366
+ const response = await supertest(ctMock.app)
367
+ .post(`/dummy/cart-discounts/${cartDiscount.id}`)
368
+ .send({
369
+ version: 1,
370
+ actions: [
371
+ {
372
+ action: 'setCustomType',
373
+ },
374
+ ],
375
+ })
376
+ expect(response.status).toBe(200)
377
+ expect(response.body.version).toBe(2)
378
+ expect(response.body.custom).toBeUndefined()
379
+ })
362
380
  })
@@ -1,4 +1,5 @@
1
- import { AssociateRoleServices } from './associate-roles'
1
+ import { AssociateRoleServices } from './associate-roles.js'
2
+ import { BusinessUnitServices } from './business-units.js'
2
3
  import { CartService } from './cart.js'
3
4
  import { CartDiscountService } from './cart-discount.js'
4
5
  import { CategoryServices } from './category.js'
@@ -32,6 +33,7 @@ import { AttributeGroupService } from './attribute-group.js'
32
33
 
33
34
  export const createServices = (router: any, repos: any) => ({
34
35
  'associate-role': new AssociateRoleServices(router, repos['associate-role']),
36
+ 'business-unit': new BusinessUnitServices(router, repos['business-unit']),
35
37
  category: new CategoryServices(router, repos['category']),
36
38
  cart: new CartService(router, repos['cart'], repos['order']),
37
39
  'cart-discount': new CartDiscountService(router, repos['cart-discount']),
@@ -0,0 +1,52 @@
1
+ import type { Project } from '@commercetools/platform-sdk'
2
+ import supertest from 'supertest'
3
+ import { afterAll, afterEach, beforeAll, describe, expect, test } from 'vitest'
4
+ import { CommercetoolsMock } from '../index.js'
5
+
6
+ const ctMock = new CommercetoolsMock()
7
+
8
+ describe('Project', () => {
9
+ beforeAll(() => {
10
+ ctMock.start()
11
+ })
12
+
13
+ afterEach(() => {
14
+ ctMock.clear()
15
+ })
16
+
17
+ afterAll(() => {
18
+ ctMock.stop()
19
+ })
20
+
21
+ test('Get project by key', async () => {
22
+ const response = await supertest(ctMock.app).get('/dummy/')
23
+
24
+ expect(response.status).toBe(200)
25
+ expect(response.body).toEqual({
26
+ version: 1,
27
+ carts: {
28
+ countryTaxRateFallbackEnabled: false,
29
+ deleteDaysAfterLastModification: 90,
30
+ },
31
+ countries: [],
32
+ createdAt: '2018-10-04T11:32:12.603Z',
33
+ currencies: [],
34
+ key: 'dummy',
35
+ languages: [],
36
+ messages: {
37
+ deleteDaysAfterCreation: 15,
38
+ enabled: false,
39
+ },
40
+ name: '',
41
+ searchIndexing: {
42
+ orders: {
43
+ status: 'Deactivated',
44
+ },
45
+ products: {
46
+ status: 'Deactivated',
47
+ },
48
+ },
49
+ trialUntil: '2018-12',
50
+ } as Project)
51
+ })
52
+ })