@labdigital/commercetools-mock 2.14.0 → 2.14.1
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 +65 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/repositories/customer.ts +72 -0
- package/src/services/customer.test.ts +154 -0
- package/src/services/my-customer.test.ts +32 -2
- package/src/services/my-customer.ts +32 -1
package/package.json
CHANGED
|
@@ -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 {
|
|
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,32 @@ 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
|
+
|
|
123
153
|
test('setCustomField', async () => {
|
|
124
154
|
const response = await supertest(ctMock.app)
|
|
125
155
|
.post(`/dummy/me`)
|
|
@@ -3,7 +3,7 @@ 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 { Customer, Update } from '@commercetools/platform-sdk'
|
|
7
7
|
|
|
8
8
|
export class MyCustomerService extends AbstractService {
|
|
9
9
|
public repository: CustomerRepository
|
|
@@ -31,6 +31,7 @@ export class MyCustomerService extends AbstractService {
|
|
|
31
31
|
router.post('/signup', this.signUp.bind(this))
|
|
32
32
|
|
|
33
33
|
router.post('/login', this.signIn.bind(this))
|
|
34
|
+
router.post('/password', this.changePassword.bind(this))
|
|
34
35
|
|
|
35
36
|
parent.use(`/${basePath}`, router)
|
|
36
37
|
}
|
|
@@ -79,6 +80,36 @@ export class MyCustomerService extends AbstractService {
|
|
|
79
80
|
return response.status(this.createStatusCode).send({ customer: result })
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
changePassword(request: Request, response: Response) {
|
|
84
|
+
const { currentPassword, newPassword } = request.body
|
|
85
|
+
const encodedPassword = hashPassword(currentPassword)
|
|
86
|
+
|
|
87
|
+
const result = this.repository.query(getRepositoryContext(request), {
|
|
88
|
+
where: [`password = "${encodedPassword}"`],
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
if (result.count === 0) {
|
|
92
|
+
return response.status(404).send({
|
|
93
|
+
message: 'Account with the given credentials not found.',
|
|
94
|
+
errors: [
|
|
95
|
+
{
|
|
96
|
+
code: 'InvalidCredentials',
|
|
97
|
+
message: 'Account with the given credentials not found.',
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const newCustomer: Customer = {
|
|
104
|
+
...result.results[0],
|
|
105
|
+
password: hashPassword(newPassword),
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this.repository.saveNew(getRepositoryContext(request), newCustomer)
|
|
109
|
+
|
|
110
|
+
return response.status(200).send(newCustomer)
|
|
111
|
+
}
|
|
112
|
+
|
|
82
113
|
signIn(request: Request, response: Response) {
|
|
83
114
|
const { email, password } = request.body
|
|
84
115
|
const encodedPassword = hashPassword(password)
|