@go-mondo/identity-sdk 0.0.2-beta.65 → 0.0.2-beta.67
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/.release-please-manifest.json +1 -1
- package/.tsbuildinfo/cjs.json +1 -1
- package/.tsbuildinfo/esm.json +1 -1
- package/CHANGELOG.md +14 -0
- package/dist/cjs/action/schema/operations/sign-up.d.ts +2 -2
- package/dist/cjs/association/schema.d.ts +4 -4
- package/dist/cjs/authentication/settings/schema.test.js +2 -4
- package/dist/cjs/customer/users/schema.d.ts +121 -27
- package/dist/cjs/customer/users/schema.d.ts.map +1 -1
- package/dist/cjs/customer/users/schema.js +23 -8
- package/dist/cjs/customer/users/schema.test.js +520 -39
- package/dist/esm/action/schema/operations/sign-up.d.ts +2 -2
- package/dist/esm/association/schema.d.ts +4 -4
- package/dist/esm/authentication/settings/schema.test.js +2 -4
- package/dist/esm/customer/users/schema.d.ts +121 -27
- package/dist/esm/customer/users/schema.d.ts.map +1 -1
- package/dist/esm/customer/users/schema.js +22 -7
- package/dist/esm/customer/users/schema.test.js +521 -40
- package/package.json +1 -1
|
@@ -1,76 +1,274 @@
|
|
|
1
1
|
import { describe, expect, test } from 'vitest';
|
|
2
2
|
import { generateUserId } from '../schema.js';
|
|
3
|
-
import { InsertUserPayloadSchema, UserPayloadSchema, UserStatus, } from './schema.js';
|
|
3
|
+
import { InsertUserPayloadSchema, UpdateUserPayloadSchema, UserPayloadSchema, UserSchema, UserStatus, UserStatusSchema, VerifiedEmailOrPhonePropertiesSchema, UnverifiedEmailOrPhonePropertiesSchema, VerifiableAttribute, UserNamePropertiesSchema, UpdateUserNamePropertiesSchema, EmailOrPhonePropertiesSchema, UserAssociationReferenceSchema, } from './schema.js';
|
|
4
4
|
describe('Customer - User', () => {
|
|
5
|
+
describe('VerifiableAttribute', () => {
|
|
6
|
+
test('should have correct constants', () => {
|
|
7
|
+
expect(VerifiableAttribute.EMAIL).toBe('email');
|
|
8
|
+
expect(VerifiableAttribute.PHONE_NUMBER).toBe('phoneNumber');
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
describe('UserStatus', () => {
|
|
12
|
+
test('should have correct constants', () => {
|
|
13
|
+
expect(UserStatus.ACTIVE).toBe('active');
|
|
14
|
+
expect(UserStatus.SUSPENDED).toBe('suspended');
|
|
15
|
+
expect(UserStatus.UNVERIFIED).toBe('unverified');
|
|
16
|
+
});
|
|
17
|
+
test('should parse valid status values', () => {
|
|
18
|
+
expect(UserStatusSchema.safeParse('active').success).toBe(true);
|
|
19
|
+
expect(UserStatusSchema.safeParse('suspended').success).toBe(true);
|
|
20
|
+
expect(UserStatusSchema.safeParse('unverified').success).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
test('should reject invalid status values', () => {
|
|
23
|
+
expect(UserStatusSchema.safeParse('invalid').success).toBe(false);
|
|
24
|
+
expect(UserStatusSchema.safeParse('').success).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('UserNamePropertiesSchema', () => {
|
|
28
|
+
test('should parse valid name properties', () => {
|
|
29
|
+
const result = UserNamePropertiesSchema.safeParse({
|
|
30
|
+
givenName: 'John',
|
|
31
|
+
middleName: 'Robert',
|
|
32
|
+
familyName: 'Doe',
|
|
33
|
+
honorificPrefix: 'Dr.',
|
|
34
|
+
honorificSuffix: 'Jr.',
|
|
35
|
+
});
|
|
36
|
+
expect(result.success).toBe(true);
|
|
37
|
+
if (result.success) {
|
|
38
|
+
expect(result.data.givenName).toBe('John');
|
|
39
|
+
expect(result.data.familyName).toBe('Doe');
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
test('should transform null values to undefined', () => {
|
|
43
|
+
const result = UserNamePropertiesSchema.safeParse({
|
|
44
|
+
givenName: null,
|
|
45
|
+
familyName: null,
|
|
46
|
+
});
|
|
47
|
+
expect(result.success).toBe(true);
|
|
48
|
+
if (result.success) {
|
|
49
|
+
expect(result.data.givenName).toBeUndefined();
|
|
50
|
+
expect(result.data.familyName).toBeUndefined();
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
test('should allow empty object', () => {
|
|
54
|
+
const result = UserNamePropertiesSchema.safeParse({});
|
|
55
|
+
expect(result.success).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe('UpdateUserNamePropertiesSchema', () => {
|
|
59
|
+
test('should parse valid name properties', () => {
|
|
60
|
+
const result = UpdateUserNamePropertiesSchema.safeParse({
|
|
61
|
+
givenName: 'Jane',
|
|
62
|
+
familyName: 'Smith',
|
|
63
|
+
});
|
|
64
|
+
expect(result.success).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
test('should allow null values without transforming', () => {
|
|
67
|
+
const result = UpdateUserNamePropertiesSchema.safeParse({
|
|
68
|
+
givenName: null,
|
|
69
|
+
familyName: 'Smith',
|
|
70
|
+
});
|
|
71
|
+
expect(result.success).toBe(true);
|
|
72
|
+
if (result.success) {
|
|
73
|
+
expect(result.data.givenName).toBeNull();
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('VerifiedEmailOrPhonePropertiesSchema', () => {
|
|
78
|
+
test('should parse valid verified email', () => {
|
|
79
|
+
const result = VerifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
80
|
+
verifiedEmail: 'test@example.com',
|
|
81
|
+
});
|
|
82
|
+
expect(result.success).toBe(true);
|
|
83
|
+
if (result.success) {
|
|
84
|
+
expect(result.data.verifiedEmail).toBe('test@example.com');
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
test('should parse valid verified phone number', () => {
|
|
88
|
+
const result = VerifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
89
|
+
verifiedPhoneNumber: '+1234567890',
|
|
90
|
+
});
|
|
91
|
+
expect(result.success).toBe(true);
|
|
92
|
+
if (result.success) {
|
|
93
|
+
expect(result.data.verifiedPhoneNumber).toBe('+1234567890');
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
test('should parse both fields together', () => {
|
|
97
|
+
const result = VerifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
98
|
+
verifiedEmail: 'verified@example.com',
|
|
99
|
+
verifiedPhoneNumber: '+1111111111',
|
|
100
|
+
});
|
|
101
|
+
expect(result.success).toBe(true);
|
|
102
|
+
if (result.success) {
|
|
103
|
+
expect(result.data.verifiedEmail).toBe('verified@example.com');
|
|
104
|
+
expect(result.data.verifiedPhoneNumber).toBe('+1111111111');
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
test('should transform null values to undefined', () => {
|
|
108
|
+
const result = VerifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
109
|
+
verifiedEmail: null,
|
|
110
|
+
verifiedPhoneNumber: null,
|
|
111
|
+
});
|
|
112
|
+
expect(result.success).toBe(true);
|
|
113
|
+
if (result.success) {
|
|
114
|
+
expect(result.data.verifiedEmail).toBeUndefined();
|
|
115
|
+
expect(result.data.verifiedPhoneNumber).toBeUndefined();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
test('should reject invalid email format', () => {
|
|
119
|
+
const result = VerifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
120
|
+
verifiedEmail: 'not-an-email',
|
|
121
|
+
});
|
|
122
|
+
expect(result.success).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
test('should allow empty object', () => {
|
|
125
|
+
const result = VerifiedEmailOrPhonePropertiesSchema.safeParse({});
|
|
126
|
+
expect(result.success).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe('UnverifiedEmailOrPhonePropertiesSchema', () => {
|
|
130
|
+
test('should parse valid unverified email', () => {
|
|
131
|
+
const result = UnverifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
132
|
+
unverifiedEmail: 'pending@example.com',
|
|
133
|
+
});
|
|
134
|
+
expect(result.success).toBe(true);
|
|
135
|
+
if (result.success) {
|
|
136
|
+
expect(result.data.unverifiedEmail).toBe('pending@example.com');
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
test('should parse valid unverified phone number', () => {
|
|
140
|
+
const result = UnverifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
141
|
+
unverifiedPhoneNumber: '+0987654321',
|
|
142
|
+
});
|
|
143
|
+
expect(result.success).toBe(true);
|
|
144
|
+
if (result.success) {
|
|
145
|
+
expect(result.data.unverifiedPhoneNumber).toBe('+0987654321');
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
test('should parse both fields together', () => {
|
|
149
|
+
const result = UnverifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
150
|
+
unverifiedEmail: 'pending@example.com',
|
|
151
|
+
unverifiedPhoneNumber: '+2222222222',
|
|
152
|
+
});
|
|
153
|
+
expect(result.success).toBe(true);
|
|
154
|
+
if (result.success) {
|
|
155
|
+
expect(result.data.unverifiedEmail).toBe('pending@example.com');
|
|
156
|
+
expect(result.data.unverifiedPhoneNumber).toBe('+2222222222');
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
test('should transform null values to undefined', () => {
|
|
160
|
+
const result = UnverifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
161
|
+
unverifiedEmail: null,
|
|
162
|
+
unverifiedPhoneNumber: null,
|
|
163
|
+
});
|
|
164
|
+
expect(result.success).toBe(true);
|
|
165
|
+
if (result.success) {
|
|
166
|
+
expect(result.data.unverifiedEmail).toBeUndefined();
|
|
167
|
+
expect(result.data.unverifiedPhoneNumber).toBeUndefined();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
test('should reject invalid unverified email format', () => {
|
|
171
|
+
const result = UnverifiedEmailOrPhonePropertiesSchema.safeParse({
|
|
172
|
+
unverifiedEmail: 'also-not-an-email',
|
|
173
|
+
});
|
|
174
|
+
expect(result.success).toBe(false);
|
|
175
|
+
});
|
|
176
|
+
test('should allow empty object', () => {
|
|
177
|
+
const result = UnverifiedEmailOrPhonePropertiesSchema.safeParse({});
|
|
178
|
+
expect(result.success).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
describe('EmailOrPhonePropertiesSchema', () => {
|
|
182
|
+
test('should parse email and phone number', () => {
|
|
183
|
+
const result = EmailOrPhonePropertiesSchema.safeParse({
|
|
184
|
+
email: 'test@example.com',
|
|
185
|
+
phoneNumber: '+1234567890',
|
|
186
|
+
});
|
|
187
|
+
expect(result.success).toBe(true);
|
|
188
|
+
if (result.success) {
|
|
189
|
+
expect(result.data.email).toBe('test@example.com');
|
|
190
|
+
expect(result.data.phoneNumber).toBe('+1234567890');
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
test('should transform null values to undefined', () => {
|
|
194
|
+
const result = EmailOrPhonePropertiesSchema.safeParse({
|
|
195
|
+
email: null,
|
|
196
|
+
phoneNumber: null,
|
|
197
|
+
});
|
|
198
|
+
expect(result.success).toBe(true);
|
|
199
|
+
if (result.success) {
|
|
200
|
+
expect(result.data.email).toBeUndefined();
|
|
201
|
+
expect(result.data.phoneNumber).toBeUndefined();
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
});
|
|
5
205
|
describe('User Payload', () => {
|
|
6
206
|
test('should parse attributes successfully', async () => {
|
|
7
207
|
const item = {
|
|
8
208
|
foo: 'bar',
|
|
9
209
|
id: generateUserId(),
|
|
10
|
-
|
|
210
|
+
verifiedPhoneNumber: '123',
|
|
11
211
|
status: UserStatus.ACTIVE,
|
|
12
212
|
createdAt: new Date(),
|
|
13
213
|
updatedAt: new Date(),
|
|
14
214
|
};
|
|
15
215
|
const result = UserPayloadSchema.safeParse(item);
|
|
16
|
-
// Parse succeeds for valid data
|
|
17
216
|
expect(result.success).toBe(true);
|
|
18
217
|
if (result.success) {
|
|
19
218
|
expect(result.data.metadata).toBeUndefined();
|
|
20
219
|
}
|
|
21
220
|
});
|
|
22
|
-
|
|
23
|
-
describe('Insert User Payload', () => {
|
|
24
|
-
test('should parse attributes successfully', async () => {
|
|
221
|
+
test('should parse with all verified and unverified email/phone properties', async () => {
|
|
25
222
|
const item = {
|
|
26
|
-
foo: 'bar',
|
|
27
223
|
id: generateUserId(),
|
|
28
|
-
|
|
29
|
-
|
|
224
|
+
verifiedEmail: 'verified@example.com',
|
|
225
|
+
unverifiedEmail: 'pending@example.com',
|
|
226
|
+
verifiedPhoneNumber: '+1234567890',
|
|
227
|
+
unverifiedPhoneNumber: '+0987654321',
|
|
228
|
+
status: UserStatus.ACTIVE,
|
|
229
|
+
createdAt: new Date(),
|
|
230
|
+
updatedAt: new Date(),
|
|
30
231
|
};
|
|
31
|
-
const result =
|
|
32
|
-
// Parse succeeds for valid data
|
|
232
|
+
const result = UserPayloadSchema.safeParse(item);
|
|
33
233
|
expect(result.success).toBe(true);
|
|
34
234
|
if (result.success) {
|
|
35
|
-
expect(result.data.
|
|
36
|
-
expect(result.data.
|
|
235
|
+
expect(result.data.verifiedEmail).toBe('verified@example.com');
|
|
236
|
+
expect(result.data.unverifiedEmail).toBe('pending@example.com');
|
|
237
|
+
expect(result.data.verifiedPhoneNumber).toBe('+1234567890');
|
|
238
|
+
expect(result.data.unverifiedPhoneNumber).toBe('+0987654321');
|
|
37
239
|
}
|
|
38
240
|
});
|
|
39
|
-
test('should
|
|
241
|
+
test('should provide email alias for verifiedEmail', async () => {
|
|
40
242
|
const item = {
|
|
41
|
-
foo: 'bar',
|
|
42
243
|
id: generateUserId(),
|
|
43
|
-
|
|
44
|
-
|
|
244
|
+
verifiedEmail: 'verified@example.com',
|
|
245
|
+
status: UserStatus.ACTIVE,
|
|
246
|
+
createdAt: new Date(),
|
|
247
|
+
updatedAt: new Date(),
|
|
45
248
|
};
|
|
46
|
-
const result =
|
|
47
|
-
// Parse succeeds for valid data
|
|
249
|
+
const result = UserPayloadSchema.safeParse(item);
|
|
48
250
|
expect(result.success).toBe(true);
|
|
49
251
|
if (result.success) {
|
|
50
|
-
expect(result.data.
|
|
252
|
+
expect(result.data.email).toBe('verified@example.com');
|
|
253
|
+
expect(result.data.verifiedEmail).toBe('verified@example.com');
|
|
51
254
|
}
|
|
52
255
|
});
|
|
53
|
-
test('should
|
|
54
|
-
const
|
|
256
|
+
test('should provide phoneNumber alias for verifiedPhoneNumber', async () => {
|
|
257
|
+
const item = {
|
|
55
258
|
id: generateUserId(),
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
honorificPrefix: null,
|
|
61
|
-
honorificSuffix: null,
|
|
62
|
-
email: null,
|
|
63
|
-
verifiedEmail: null,
|
|
64
|
-
phoneNumber: null,
|
|
65
|
-
verifiedPhoneNumber: null,
|
|
66
|
-
createdAt: '2025-04-02T03:50:40.812Z',
|
|
67
|
-
updatedAt: '2025-04-02T03:50:40.812Z',
|
|
259
|
+
verifiedPhoneNumber: '+1234567890',
|
|
260
|
+
status: UserStatus.ACTIVE,
|
|
261
|
+
createdAt: new Date(),
|
|
262
|
+
updatedAt: new Date(),
|
|
68
263
|
};
|
|
69
|
-
const result = UserPayloadSchema.safeParse(
|
|
70
|
-
// Parse succeeds for valid data
|
|
264
|
+
const result = UserPayloadSchema.safeParse(item);
|
|
71
265
|
expect(result.success).toBe(true);
|
|
266
|
+
if (result.success) {
|
|
267
|
+
expect(result.data.phoneNumber).toBe('+1234567890');
|
|
268
|
+
expect(result.data.verifiedPhoneNumber).toBe('+1234567890');
|
|
269
|
+
}
|
|
72
270
|
});
|
|
73
|
-
test('should serialize nulls
|
|
271
|
+
test('should serialize nulls to undefined', async () => {
|
|
74
272
|
const payload = {
|
|
75
273
|
id: generateUserId(),
|
|
76
274
|
status: 'unverified',
|
|
@@ -79,16 +277,299 @@ describe('Customer - User', () => {
|
|
|
79
277
|
familyName: null,
|
|
80
278
|
honorificPrefix: null,
|
|
81
279
|
honorificSuffix: null,
|
|
82
|
-
email: null,
|
|
83
280
|
verifiedEmail: null,
|
|
84
|
-
|
|
281
|
+
unverifiedEmail: null,
|
|
85
282
|
verifiedPhoneNumber: null,
|
|
283
|
+
unverifiedPhoneNumber: null,
|
|
86
284
|
createdAt: '2025-04-02T03:50:40.812Z',
|
|
87
285
|
updatedAt: '2025-04-02T03:50:40.812Z',
|
|
88
286
|
};
|
|
89
287
|
const result = UserPayloadSchema.safeParse(payload);
|
|
90
|
-
// Parse succeeds for valid data
|
|
91
288
|
expect(result.success).toBe(true);
|
|
289
|
+
if (result.success) {
|
|
290
|
+
expect(result.data.verifiedEmail).toBeUndefined();
|
|
291
|
+
expect(result.data.unverifiedEmail).toBeUndefined();
|
|
292
|
+
expect(result.data.verifiedPhoneNumber).toBeUndefined();
|
|
293
|
+
expect(result.data.unverifiedPhoneNumber).toBeUndefined();
|
|
294
|
+
expect(result.data.email).toBeUndefined();
|
|
295
|
+
expect(result.data.phoneNumber).toBeUndefined();
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
describe('User Schema', () => {
|
|
300
|
+
test('should parse complete user object', async () => {
|
|
301
|
+
const user = {
|
|
302
|
+
id: generateUserId(),
|
|
303
|
+
givenName: 'John',
|
|
304
|
+
familyName: 'Doe',
|
|
305
|
+
verifiedEmail: 'john@example.com',
|
|
306
|
+
verifiedPhoneNumber: '+1234567890',
|
|
307
|
+
status: UserStatus.ACTIVE,
|
|
308
|
+
lastLogin: new Date(),
|
|
309
|
+
createdAt: new Date(),
|
|
310
|
+
updatedAt: new Date(),
|
|
311
|
+
};
|
|
312
|
+
const result = UserSchema.safeParse(user);
|
|
313
|
+
expect(result.success).toBe(true);
|
|
314
|
+
if (result.success) {
|
|
315
|
+
expect(result.data.givenName).toBe('John');
|
|
316
|
+
expect(result.data.verifiedEmail).toBe('john@example.com');
|
|
317
|
+
expect(result.data.verifiedPhoneNumber).toBe('+1234567890');
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
test('should provide email alias for verifiedEmail', async () => {
|
|
321
|
+
const user = {
|
|
322
|
+
id: generateUserId(),
|
|
323
|
+
verifiedEmail: 'john@example.com',
|
|
324
|
+
status: UserStatus.ACTIVE,
|
|
325
|
+
createdAt: new Date(),
|
|
326
|
+
updatedAt: new Date(),
|
|
327
|
+
};
|
|
328
|
+
const result = UserSchema.safeParse(user);
|
|
329
|
+
expect(result.success).toBe(true);
|
|
330
|
+
if (result.success) {
|
|
331
|
+
expect(result.data.email).toBe('john@example.com');
|
|
332
|
+
expect(result.data.verifiedEmail).toBe('john@example.com');
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
test('should provide phoneNumber alias for verifiedPhoneNumber', async () => {
|
|
336
|
+
const user = {
|
|
337
|
+
id: generateUserId(),
|
|
338
|
+
verifiedPhoneNumber: '+1234567890',
|
|
339
|
+
status: UserStatus.ACTIVE,
|
|
340
|
+
createdAt: new Date(),
|
|
341
|
+
updatedAt: new Date(),
|
|
342
|
+
};
|
|
343
|
+
const result = UserSchema.safeParse(user);
|
|
344
|
+
expect(result.success).toBe(true);
|
|
345
|
+
if (result.success) {
|
|
346
|
+
expect(result.data.phoneNumber).toBe('+1234567890');
|
|
347
|
+
expect(result.data.verifiedPhoneNumber).toBe('+1234567890');
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
test('should have undefined aliases when verified fields are undefined', async () => {
|
|
351
|
+
const user = {
|
|
352
|
+
id: generateUserId(),
|
|
353
|
+
status: UserStatus.ACTIVE,
|
|
354
|
+
createdAt: new Date(),
|
|
355
|
+
updatedAt: new Date(),
|
|
356
|
+
};
|
|
357
|
+
const result = UserSchema.safeParse(user);
|
|
358
|
+
expect(result.success).toBe(true);
|
|
359
|
+
if (result.success) {
|
|
360
|
+
expect(result.data.email).toBeUndefined();
|
|
361
|
+
expect(result.data.phoneNumber).toBeUndefined();
|
|
362
|
+
expect(result.data.verifiedEmail).toBeUndefined();
|
|
363
|
+
expect(result.data.verifiedPhoneNumber).toBeUndefined();
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
test('should parse user with deletedAt and deactivatedAt', async () => {
|
|
367
|
+
const user = {
|
|
368
|
+
id: generateUserId(),
|
|
369
|
+
status: UserStatus.SUSPENDED,
|
|
370
|
+
createdAt: new Date(),
|
|
371
|
+
updatedAt: new Date(),
|
|
372
|
+
deletedAt: new Date(),
|
|
373
|
+
deactivatedAt: new Date(),
|
|
374
|
+
};
|
|
375
|
+
const result = UserSchema.safeParse(user);
|
|
376
|
+
expect(result.success).toBe(true);
|
|
377
|
+
if (result.success) {
|
|
378
|
+
expect(result.data.deletedAt).toBeInstanceOf(Date);
|
|
379
|
+
expect(result.data.deactivatedAt).toBeInstanceOf(Date);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
test('should include unverified fields alongside aliases', async () => {
|
|
383
|
+
const user = {
|
|
384
|
+
id: generateUserId(),
|
|
385
|
+
verifiedEmail: 'verified@example.com',
|
|
386
|
+
unverifiedEmail: 'pending@example.com',
|
|
387
|
+
verifiedPhoneNumber: '+1111111111',
|
|
388
|
+
unverifiedPhoneNumber: '+2222222222',
|
|
389
|
+
status: UserStatus.ACTIVE,
|
|
390
|
+
createdAt: new Date(),
|
|
391
|
+
updatedAt: new Date(),
|
|
392
|
+
};
|
|
393
|
+
const result = UserSchema.safeParse(user);
|
|
394
|
+
expect(result.success).toBe(true);
|
|
395
|
+
if (result.success) {
|
|
396
|
+
expect(result.data.email).toBe('verified@example.com');
|
|
397
|
+
expect(result.data.verifiedEmail).toBe('verified@example.com');
|
|
398
|
+
expect(result.data.unverifiedEmail).toBe('pending@example.com');
|
|
399
|
+
expect(result.data.phoneNumber).toBe('+1111111111');
|
|
400
|
+
expect(result.data.verifiedPhoneNumber).toBe('+1111111111');
|
|
401
|
+
expect(result.data.unverifiedPhoneNumber).toBe('+2222222222');
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
describe('Insert User Payload', () => {
|
|
406
|
+
test('should parse attributes successfully', async () => {
|
|
407
|
+
const item = {
|
|
408
|
+
foo: 'bar',
|
|
409
|
+
id: generateUserId(),
|
|
410
|
+
familyName: 'Foo',
|
|
411
|
+
verifiedPhoneNumber: '123',
|
|
412
|
+
};
|
|
413
|
+
const result = InsertUserPayloadSchema.safeParse(item);
|
|
414
|
+
expect(result.success).toBe(true);
|
|
415
|
+
if (result.success) {
|
|
416
|
+
expect(result.data.metadata).toBeUndefined();
|
|
417
|
+
expect(result.data.familyName).toBe(item.familyName);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
test('should parse with all verified and unverified email/phone properties', async () => {
|
|
421
|
+
const item = {
|
|
422
|
+
id: generateUserId(),
|
|
423
|
+
verifiedEmail: 'verified@example.com',
|
|
424
|
+
unverifiedEmail: 'pending@example.com',
|
|
425
|
+
verifiedPhoneNumber: '+1234567890',
|
|
426
|
+
unverifiedPhoneNumber: '+0987654321',
|
|
427
|
+
};
|
|
428
|
+
const result = InsertUserPayloadSchema.safeParse(item);
|
|
429
|
+
expect(result.success).toBe(true);
|
|
430
|
+
if (result.success) {
|
|
431
|
+
expect(result.data.verifiedEmail).toBe('verified@example.com');
|
|
432
|
+
expect(result.data.unverifiedEmail).toBe('pending@example.com');
|
|
433
|
+
expect(result.data.verifiedPhoneNumber).toBe('+1234567890');
|
|
434
|
+
expect(result.data.unverifiedPhoneNumber).toBe('+0987654321');
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
test('should serialize empty Map to null', async () => {
|
|
438
|
+
const item = {
|
|
439
|
+
foo: 'bar',
|
|
440
|
+
id: generateUserId(),
|
|
441
|
+
verifiedPhoneNumber: '123',
|
|
442
|
+
metadata: new Map(),
|
|
443
|
+
};
|
|
444
|
+
const result = InsertUserPayloadSchema.safeParse(item);
|
|
445
|
+
expect(result.success).toBe(true);
|
|
446
|
+
if (result.success) {
|
|
447
|
+
expect(result.data.metadata).toBeNull();
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
test('should allow optional id and status', async () => {
|
|
451
|
+
const item = {
|
|
452
|
+
verifiedEmail: 'test@example.com',
|
|
453
|
+
};
|
|
454
|
+
const result = InsertUserPayloadSchema.safeParse(item);
|
|
455
|
+
expect(result.success).toBe(true);
|
|
456
|
+
if (result.success) {
|
|
457
|
+
expect(result.data.id).toBeUndefined();
|
|
458
|
+
expect(result.data.status).toBeUndefined();
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
test('should parse with roles association', async () => {
|
|
462
|
+
const item = {
|
|
463
|
+
id: generateUserId(),
|
|
464
|
+
verifiedEmail: 'test@example.com',
|
|
465
|
+
roles: [
|
|
466
|
+
'rol_2NfYOTzVqhCHgWFzUL0WPfRRuhH',
|
|
467
|
+
'rol_2NfYOTzVqhCHgWFzUL0WPfRRuhI',
|
|
468
|
+
],
|
|
469
|
+
};
|
|
470
|
+
const result = InsertUserPayloadSchema.safeParse(item);
|
|
471
|
+
expect(result.success).toBe(true);
|
|
472
|
+
if (result.success) {
|
|
473
|
+
expect(result.data.roles).toEqual([
|
|
474
|
+
'rol_2NfYOTzVqhCHgWFzUL0WPfRRuhH',
|
|
475
|
+
'rol_2NfYOTzVqhCHgWFzUL0WPfRRuhI',
|
|
476
|
+
]);
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
describe('Update User Payload', () => {
|
|
481
|
+
test('should parse suspended flag', async () => {
|
|
482
|
+
const result = UpdateUserPayloadSchema.safeParse({
|
|
483
|
+
suspended: true,
|
|
484
|
+
});
|
|
485
|
+
expect(result.success).toBe(true);
|
|
486
|
+
if (result.success) {
|
|
487
|
+
expect(result.data.suspended).toBe(true);
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
test('should parse name updates', async () => {
|
|
491
|
+
const result = UpdateUserPayloadSchema.safeParse({
|
|
492
|
+
givenName: 'Jane',
|
|
493
|
+
familyName: null,
|
|
494
|
+
});
|
|
495
|
+
expect(result.success).toBe(true);
|
|
496
|
+
if (result.success) {
|
|
497
|
+
expect(result.data.givenName).toBe('Jane');
|
|
498
|
+
expect(result.data.familyName).toBeNull();
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
test('should parse verified and unverified email/phone updates', async () => {
|
|
502
|
+
const result = UpdateUserPayloadSchema.safeParse({
|
|
503
|
+
verifiedEmail: 'newemail@example.com',
|
|
504
|
+
unverifiedEmail: 'pending@example.com',
|
|
505
|
+
verifiedPhoneNumber: '+9999999999',
|
|
506
|
+
unverifiedPhoneNumber: '+8888888888',
|
|
507
|
+
});
|
|
508
|
+
expect(result.success).toBe(true);
|
|
509
|
+
if (result.success) {
|
|
510
|
+
expect(result.data.verifiedEmail).toBe('newemail@example.com');
|
|
511
|
+
expect(result.data.unverifiedEmail).toBe('pending@example.com');
|
|
512
|
+
expect(result.data.verifiedPhoneNumber).toBe('+9999999999');
|
|
513
|
+
expect(result.data.unverifiedPhoneNumber).toBe('+8888888888');
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
test('should parse metadata updates', async () => {
|
|
517
|
+
const result = UpdateUserPayloadSchema.safeParse({
|
|
518
|
+
metadata: { key: 'value' },
|
|
519
|
+
});
|
|
520
|
+
expect(result.success).toBe(true);
|
|
521
|
+
if (result.success) {
|
|
522
|
+
expect(result.data.metadata).toEqual({ key: 'value' });
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
test('should allow empty object', async () => {
|
|
526
|
+
const result = UpdateUserPayloadSchema.safeParse({});
|
|
527
|
+
expect(result.success).toBe(true);
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
describe('UserAssociationReferenceSchema', () => {
|
|
531
|
+
test('should parse valid association reference', () => {
|
|
532
|
+
const result = UserAssociationReferenceSchema.safeParse({
|
|
533
|
+
id: generateUserId(),
|
|
534
|
+
givenName: 'John',
|
|
535
|
+
familyName: 'Doe',
|
|
536
|
+
email: 'john@example.com',
|
|
537
|
+
phoneNumber: '+1234567890',
|
|
538
|
+
model: 'User',
|
|
539
|
+
});
|
|
540
|
+
expect(result.success).toBe(true);
|
|
541
|
+
if (result.success) {
|
|
542
|
+
expect(result.data.model).toBe('User');
|
|
543
|
+
expect(result.data.status).toBe('unverified');
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
test('should default status to unverified', () => {
|
|
547
|
+
const result = UserAssociationReferenceSchema.safeParse({
|
|
548
|
+
id: generateUserId(),
|
|
549
|
+
model: 'User',
|
|
550
|
+
});
|
|
551
|
+
expect(result.success).toBe(true);
|
|
552
|
+
if (result.success) {
|
|
553
|
+
expect(result.data.status).toBe('unverified');
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
test('should allow custom status', () => {
|
|
557
|
+
const result = UserAssociationReferenceSchema.safeParse({
|
|
558
|
+
id: generateUserId(),
|
|
559
|
+
status: 'active',
|
|
560
|
+
model: 'User',
|
|
561
|
+
});
|
|
562
|
+
expect(result.success).toBe(true);
|
|
563
|
+
if (result.success) {
|
|
564
|
+
expect(result.data.status).toBe('active');
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
test('should reject invalid model literal', () => {
|
|
568
|
+
const result = UserAssociationReferenceSchema.safeParse({
|
|
569
|
+
id: generateUserId(),
|
|
570
|
+
model: 'Organization',
|
|
571
|
+
});
|
|
572
|
+
expect(result.success).toBe(false);
|
|
92
573
|
});
|
|
93
574
|
});
|
|
94
575
|
});
|