@labdigital/commercetools-mock 2.14.0 → 2.14.2

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": "2.14.0",
4
+ "version": "2.14.2",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",
@@ -1,9 +1,14 @@
1
1
  import type {
2
2
  Customer,
3
+ CustomerChangeAddressAction,
3
4
  CustomerChangeEmailAction,
4
5
  CustomerDraft,
5
6
  CustomerSetAuthenticationModeAction,
7
+ CustomerSetCompanyNameAction,
6
8
  CustomerSetCustomFieldAction,
9
+ CustomerSetFirstNameAction,
10
+ CustomerSetLastNameAction,
11
+ CustomerSetVatIdAction,
7
12
  DuplicateFieldError,
8
13
  InvalidInputError,
9
14
  InvalidJsonInputError,
@@ -16,6 +21,7 @@ import {
16
21
  type RepositoryContext,
17
22
  } from './abstract.js'
18
23
  import { hashPassword } from '../lib/password.js'
24
+ import { createAddress } from './helpers.js'
19
25
 
20
26
  export class CustomerRepository extends AbstractResourceRepository<'customer'> {
21
27
  getTypeId() {
@@ -97,6 +103,72 @@ export class CustomerRepository extends AbstractResourceRepository<'customer'> {
97
103
  ) => {
98
104
  resource.email = email
99
105
  },
106
+ setFirstName: (
107
+ _context: RepositoryContext,
108
+ resource: Writable<Customer>,
109
+ { firstName }: CustomerSetFirstNameAction
110
+ ) => {
111
+ resource.firstName = firstName
112
+ },
113
+ setLastName: (
114
+ _context: RepositoryContext,
115
+ resource: Writable<Customer>,
116
+ { lastName }: CustomerSetLastNameAction
117
+ ) => {
118
+ resource.lastName = lastName
119
+ },
120
+ setCompanyName: (
121
+ _context: RepositoryContext,
122
+ resource: Writable<Customer>,
123
+ { companyName }: CustomerSetCompanyNameAction
124
+ ) => {
125
+ resource.companyName = companyName
126
+ },
127
+ setVatId: (
128
+ _context: RepositoryContext,
129
+ resource: Writable<Customer>,
130
+ { vatId }: CustomerSetVatIdAction
131
+ ) => {
132
+ resource.vatId = vatId
133
+ },
134
+ changeAddress: (
135
+ context: RepositoryContext,
136
+ resource: Writable<Customer>,
137
+ { addressId, addressKey, address }: CustomerChangeAddressAction
138
+ ) => {
139
+ const oldAddressIndex = resource.addresses.findIndex((a) => {
140
+ if (a.id != undefined && addressId != undefined && a.id === addressId) {
141
+ return true
142
+ }
143
+
144
+ return (
145
+ a.key != undefined && addressKey != undefined && a.key === addressKey
146
+ )
147
+ })
148
+
149
+ if (oldAddressIndex === -1) {
150
+ throw new CommercetoolsError<InvalidInputError>(
151
+ {
152
+ code: 'InvalidInput',
153
+ message: `Address with id '${addressId}' or key '${addressKey}' not found.`,
154
+ },
155
+ 400
156
+ )
157
+ }
158
+
159
+ const newAddress = createAddress(
160
+ address,
161
+ context.projectKey,
162
+ this._storage
163
+ )
164
+
165
+ if (newAddress) {
166
+ resource.addresses[oldAddressIndex] = {
167
+ id: addressId,
168
+ ...newAddress,
169
+ }
170
+ }
171
+ },
100
172
  setAuthenticationMode: (
101
173
  _context: RepositoryContext,
102
174
  resource: Writable<Customer>,
@@ -176,4 +176,158 @@ describe('Customer Update Actions', () => {
176
176
  expect(response.body.version).toBe(2)
177
177
  expect(response.body.custom.fields.isValidCouponCode).toBe(false)
178
178
  })
179
+
180
+ test('setFirstName', async () => {
181
+ assert(customer, 'customer not created')
182
+
183
+ customer = {
184
+ ...customer,
185
+ firstName: 'John',
186
+ }
187
+ ctMock.project('dummy').add('customer', customer)
188
+
189
+ const response = await supertest(ctMock.app)
190
+ .post(`/dummy/customers/${customer.id}`)
191
+ .send({
192
+ version: 1,
193
+ actions: [{ action: 'setFirstName', firstName: 'Mary' }],
194
+ })
195
+ expect(response.status).toBe(200)
196
+ expect(response.body.version).toBe(2)
197
+ expect(response.body.firstName).toBe('Mary')
198
+ })
199
+
200
+ test('setLastName', async () => {
201
+ assert(customer, 'customer not created')
202
+
203
+ customer = {
204
+ ...customer,
205
+ lastName: 'Doe',
206
+ }
207
+ ctMock.project('dummy').add('customer', customer)
208
+
209
+ const response = await supertest(ctMock.app)
210
+ .post(`/dummy/customers/${customer.id}`)
211
+ .send({
212
+ version: 1,
213
+ actions: [{ action: 'setLastName', lastName: 'Smith' }],
214
+ })
215
+ expect(response.status).toBe(200)
216
+ expect(response.body.version).toBe(2)
217
+ expect(response.body.lastName).toBe('Smith')
218
+ })
219
+
220
+ test('setCompanyName', async () => {
221
+ assert(customer, 'customer not created')
222
+
223
+ customer = {
224
+ ...customer,
225
+ companyName: 'Acme',
226
+ }
227
+ ctMock.project('dummy').add('customer', customer)
228
+
229
+ const response = await supertest(ctMock.app)
230
+ .post(`/dummy/customers/${customer.id}`)
231
+ .send({
232
+ version: 1,
233
+ actions: [{ action: 'setCompanyName', companyName: 'Acme Inc.' }],
234
+ })
235
+ expect(response.status).toBe(200)
236
+ expect(response.body.version).toBe(2)
237
+ expect(response.body.companyName).toBe('Acme Inc.')
238
+ })
239
+
240
+ test('setVatId', async () => {
241
+ assert(customer, 'customer not created')
242
+
243
+ customer = {
244
+ ...customer,
245
+ vatId: '123456789',
246
+ }
247
+ ctMock.project('dummy').add('customer', customer)
248
+
249
+ const response = await supertest(ctMock.app)
250
+ .post(`/dummy/customers/${customer.id}`)
251
+ .send({
252
+ version: 1,
253
+ actions: [{ action: 'setVatId', vatId: 'ABCD' }],
254
+ })
255
+ expect(response.status).toBe(200)
256
+ expect(response.body.version).toBe(2)
257
+ expect(response.body.vatId).toBe('ABCD')
258
+ })
259
+
260
+ test('changeAddress', async () => {
261
+ assert(customer, 'customer not created')
262
+
263
+ customer = {
264
+ ...customer,
265
+ addresses: [
266
+ {
267
+ ...getBaseResourceProperties(),
268
+ id: 'other-address-uid',
269
+ firstName: 'Foo',
270
+ lastName: 'Bar',
271
+ streetName: 'Baz Street',
272
+ streetNumber: '99',
273
+ postalCode: '12ab',
274
+ country: 'NL',
275
+ },
276
+ {
277
+ ...getBaseResourceProperties(),
278
+ id: 'address-uuid',
279
+ firstName: 'John',
280
+ lastName: 'Doe',
281
+ streetName: 'Main Street',
282
+ streetNumber: '1',
283
+ postalCode: '12345',
284
+ country: 'DE',
285
+ },
286
+ ],
287
+ defaultBillingAddressId: 'address-uuid',
288
+ }
289
+ ctMock.project('dummy').add('customer', customer)
290
+
291
+ const response = await supertest(ctMock.app)
292
+ .post(`/dummy/customers/${customer.id}`)
293
+ .send({
294
+ version: 1,
295
+ actions: [
296
+ {
297
+ action: 'changeAddress',
298
+ addressId: 'address-uuid',
299
+ address: {
300
+ firstName: 'Marie',
301
+ lastName: 'Johnson',
302
+ streetName: 'Last Street',
303
+ streetNumber: '2',
304
+ postalCode: 'ABCS',
305
+ country: 'US',
306
+ },
307
+ },
308
+ ],
309
+ })
310
+ expect(response.status).toBe(200)
311
+ expect(response.body.version).toBe(2)
312
+ expect(response.body.addresses).toMatchObject([
313
+ {
314
+ id: 'other-address-uid',
315
+ firstName: 'Foo',
316
+ lastName: 'Bar',
317
+ streetName: 'Baz Street',
318
+ streetNumber: '99',
319
+ postalCode: '12ab',
320
+ country: 'NL',
321
+ },
322
+ {
323
+ id: 'address-uuid',
324
+ firstName: 'Marie',
325
+ lastName: 'Johnson',
326
+ streetName: 'Last Street',
327
+ streetNumber: '2',
328
+ postalCode: 'ABCS',
329
+ country: 'US',
330
+ },
331
+ ])
332
+ })
179
333
  })
@@ -1,7 +1,11 @@
1
- import type { MyCustomerDraft } from '@commercetools/platform-sdk'
1
+ import type {
2
+ CustomerChangePassword,
3
+ MyCustomerDraft,
4
+ } from '@commercetools/platform-sdk'
2
5
  import supertest from 'supertest'
3
6
  import { afterEach, beforeEach, describe, expect, test } from 'vitest'
4
- import { CommercetoolsMock } from '../index.js'
7
+ import { CommercetoolsMock, getBaseResourceProperties } from '../index.js'
8
+ import { hashPassword } from '../lib/password.js'
5
9
 
6
10
  const ctMock = new CommercetoolsMock()
7
11
 
@@ -120,6 +124,55 @@ describe('/me', () => {
120
124
  expect(newResponse.status).toBe(404)
121
125
  })
122
126
 
127
+ test('Change my password', async () => {
128
+ const customer = {
129
+ ...getBaseResourceProperties(),
130
+ id: 'customer-uuid',
131
+ email: 'user@example.com',
132
+ password: hashPassword('p4ssw0rd'),
133
+ addresses: [],
134
+ isEmailVerified: true,
135
+ authenticationMode: 'Password', //default in Commercetools
136
+ version: 1,
137
+ }
138
+ ctMock.project('dummy').add('customer', customer)
139
+
140
+ const draft: CustomerChangePassword = {
141
+ id: customer.id,
142
+ version: customer.version,
143
+ newPassword: 'newP4ssw0rd',
144
+ currentPassword: 'p4ssw0rd',
145
+ }
146
+ const response = await supertest(ctMock.app)
147
+ .post('/dummy/me/password')
148
+ .send(draft)
149
+
150
+ expect(response.status).toBe(200)
151
+ })
152
+
153
+ test('Fail to change password', async () => {
154
+ const draft: CustomerChangePassword = {
155
+ id: 'foo',
156
+ version: 1,
157
+ newPassword: 'newP4ssw0rd',
158
+ currentPassword: 'p4ssw0rd',
159
+ }
160
+ const response = await supertest(ctMock.app)
161
+ .post('/dummy/me/password')
162
+ .send(draft)
163
+
164
+ expect(response.status).toBe(404)
165
+ expect(response.body).toEqual({
166
+ errors: [
167
+ {
168
+ code: 'InvalidCurrentPassword',
169
+ message: 'Account with the given credentials not found.',
170
+ },
171
+ ],
172
+ message: 'Account with the given credentials not found.',
173
+ })
174
+ })
175
+
123
176
  test('setCustomField', async () => {
124
177
  const response = await supertest(ctMock.app)
125
178
  .post(`/dummy/me`)
@@ -3,7 +3,11 @@ import { CustomerRepository } from '../repositories/customer.js'
3
3
  import { getRepositoryContext } from '../repositories/helpers.js'
4
4
  import AbstractService from './abstract.js'
5
5
  import { hashPassword } from '../lib/password.js'
6
- import { Update } from '@commercetools/platform-sdk'
6
+ import {
7
+ Customer,
8
+ Update,
9
+ InvalidCurrentPasswordError,
10
+ } from '@commercetools/platform-sdk'
7
11
 
8
12
  export class MyCustomerService extends AbstractService {
9
13
  public repository: CustomerRepository
@@ -31,6 +35,7 @@ export class MyCustomerService extends AbstractService {
31
35
  router.post('/signup', this.signUp.bind(this))
32
36
 
33
37
  router.post('/login', this.signIn.bind(this))
38
+ router.post('/password', this.changePassword.bind(this))
34
39
 
35
40
  parent.use(`/${basePath}`, router)
36
41
  }
@@ -79,6 +84,36 @@ export class MyCustomerService extends AbstractService {
79
84
  return response.status(this.createStatusCode).send({ customer: result })
80
85
  }
81
86
 
87
+ changePassword(request: Request, response: Response) {
88
+ const { currentPassword, newPassword } = request.body
89
+ const encodedPassword = hashPassword(currentPassword)
90
+
91
+ const result = this.repository.query(getRepositoryContext(request), {
92
+ where: [`password = "${encodedPassword}"`],
93
+ })
94
+
95
+ if (result.count === 0) {
96
+ return response.status(404).send({
97
+ message: 'Account with the given credentials not found.',
98
+ errors: [
99
+ {
100
+ code: 'InvalidCurrentPassword',
101
+ message: 'Account with the given credentials not found.',
102
+ } as InvalidCurrentPasswordError,
103
+ ],
104
+ })
105
+ }
106
+
107
+ const newCustomer: Customer = {
108
+ ...result.results[0],
109
+ password: hashPassword(newPassword),
110
+ }
111
+
112
+ this.repository.saveNew(getRepositoryContext(request), newCustomer)
113
+
114
+ return response.status(200).send(newCustomer)
115
+ }
116
+
82
117
  signIn(request: Request, response: Response) {
83
118
  const { email, password } = request.body
84
119
  const encodedPassword = hashPassword(password)