@lobehub/chat 1.122.4 → 1.122.5

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.
@@ -1,556 +0,0 @@
1
- import type {
2
- AdapterAccount,
3
- AdapterAuthenticator,
4
- AdapterSession,
5
- AdapterUser,
6
- VerificationToken,
7
- } from '@auth/core/adapters';
8
- import { eq } from 'drizzle-orm';
9
- import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
10
-
11
- import { LobeNextAuthDbAdapter } from '@/libs/next-auth/adapter';
12
-
13
- import { getTestDBInstance } from '../../../core/dbForTest';
14
- import {
15
- nextauthAccounts,
16
- nextauthAuthenticators,
17
- nextauthSessions,
18
- nextauthVerificationTokens,
19
- users,
20
- } from '../../../schemas';
21
-
22
- let serverDB = await getTestDBInstance();
23
-
24
- let nextAuthAdapter = LobeNextAuthDbAdapter(serverDB);
25
-
26
- const userId = 'user-db';
27
- const user: AdapterUser = {
28
- id: userId,
29
- name: 'John Doe',
30
- email: 'john.doe@example.com',
31
- emailVerified: new Date(),
32
- image: 'https://example.com/avatar.jpg',
33
- };
34
-
35
- const sessionToken = 'session-token';
36
-
37
- beforeAll(async () => {
38
- await serverDB.delete(users);
39
- await serverDB.delete(nextauthAccounts);
40
- await serverDB.delete(nextauthAuthenticators);
41
- await serverDB.delete(nextauthSessions);
42
- await serverDB.delete(nextauthVerificationTokens);
43
- });
44
-
45
- beforeEach(async () => {
46
- process.env.KEY_VAULTS_SECRET = 'ofQiJCXLF8mYemwfMWLOHoHimlPu91YmLfU7YZ4lreQ=';
47
- // insert a user
48
- // @ts-expect-error: createUser is defined
49
- await nextAuthAdapter.createUser(user);
50
- });
51
-
52
- afterEach(async () => {
53
- await serverDB.delete(users);
54
- });
55
-
56
- afterAll(async () => {
57
- await serverDB.delete(users);
58
- await serverDB.delete(nextauthAccounts);
59
- await serverDB.delete(nextauthAuthenticators);
60
- await serverDB.delete(nextauthSessions);
61
- await serverDB.delete(nextauthVerificationTokens);
62
- process.env.KEY_VAULTS_SECRET = undefined;
63
- });
64
-
65
- /**
66
- * The tests below only test the database operation functionality,
67
- * the mock values might not represent the actual value
68
- */
69
- describe('LobeNextAuthDbAdapter', () => {
70
- describe('users', () => {
71
- describe('createUser', () => {
72
- it('should create a new user', async () => {
73
- expect(nextAuthAdapter).toBeDefined();
74
- expect(nextAuthAdapter.createUser).toBeDefined();
75
- const anotherUserId = 'user-db-2';
76
- const anotherUserName = 'John Doe 2';
77
- const anotherEmail = 'john.doe.2@example.com';
78
- // @ts-expect-error: createUser is defined
79
- const createdUser = await nextAuthAdapter.createUser({
80
- ...user,
81
- id: anotherUserId,
82
- name: anotherUserName,
83
- email: anotherEmail,
84
- });
85
- expect(createdUser).toBeDefined();
86
- expect(createdUser.id).toBe(anotherUserId);
87
- expect(createdUser.name).toBe(anotherUserName);
88
- expect(createdUser.email).toBe(anotherEmail);
89
- expect(createdUser.emailVerified).toBe(user.emailVerified);
90
- expect(createdUser.image).toBe(user.image);
91
- });
92
-
93
- it('should not create a user if it already exists', async () => {
94
- expect(nextAuthAdapter).toBeDefined();
95
- expect(nextAuthAdapter.createUser).toBeDefined();
96
- // @ts-expect-error: createUser is defined
97
- await nextAuthAdapter.createUser(user);
98
- // Should not create a new user if it already exists
99
- expect(
100
- await serverDB.query.users.findMany({ where: eq(users.email, user.email) }),
101
- ).toHaveLength(1);
102
- });
103
-
104
- it('should not create a user if email exist', async () => {
105
- expect(nextAuthAdapter).toBeDefined();
106
- expect(nextAuthAdapter.createUser).toBeDefined();
107
- const anotherUserId = 'user-db-2';
108
- const anotherUserName = 'John Doe 2';
109
- // @ts-expect-error: createUser is defined
110
- await nextAuthAdapter.createUser({
111
- ...user,
112
- id: anotherUserId,
113
- name: anotherUserName,
114
- });
115
- // Should not create a new user if email already exists
116
- expect(
117
- await serverDB.query.users.findMany({ where: eq(users.email, user.email) }),
118
- ).toHaveLength(1);
119
- });
120
-
121
- it('should create a user if id not exist and email is null', async () => {
122
- // In previous version, it will link the account to the existing user if the email is null
123
- // issue: https://github.com/lobehub/lobe-chat/issues/4918
124
- expect(nextAuthAdapter).toBeDefined();
125
- expect(nextAuthAdapter.createUser).toBeDefined();
126
-
127
- const existUserId = 'user-db-1';
128
- const existUserName = 'John Doe 1';
129
- // @ts-expect-error: createUser is defined
130
- await nextAuthAdapter.createUser({
131
- ...user,
132
- id: existUserId,
133
- name: existUserName,
134
- email: '',
135
- });
136
-
137
- const anotherUserId = 'user-db-2';
138
- const anotherUserName = 'John Doe 2';
139
- // @ts-expect-error: createUser is defined
140
- await nextAuthAdapter.createUser({
141
- ...user,
142
- id: anotherUserId,
143
- name: anotherUserName,
144
- email: '',
145
- });
146
- // Should create a new user if id not exists and email is null
147
- expect(
148
- await serverDB.query.users.findMany({ where: eq(users.id, anotherUserId) }),
149
- ).toHaveLength(1);
150
- });
151
-
152
- it('should create a user if id not exist even email is invalid type', async () => {
153
- // In previous version, it will link the account to the existing user if the email is null
154
- // issue: https://github.com/lobehub/lobe-chat/issues/4918
155
- expect(nextAuthAdapter).toBeDefined();
156
- expect(nextAuthAdapter.createUser).toBeDefined();
157
-
158
- const existUserId = 'user-db-1';
159
- const existUserName = 'John Doe 1';
160
- // @ts-expect-error: createUser is defined
161
- await nextAuthAdapter.createUser({
162
- ...user,
163
- id: existUserId,
164
- name: existUserName,
165
- email: Object({}), // assign a non-string value
166
- });
167
-
168
- const anotherUserId = 'user-db-2';
169
- const anotherUserName = 'John Doe 2';
170
- // @ts-expect-error: createUser is defined
171
- await nextAuthAdapter.createUser({
172
- ...user,
173
- id: anotherUserId,
174
- name: anotherUserName,
175
- // @ts-expect-error: try to assign undefined value
176
- email: undefined,
177
- });
178
-
179
- // Should create a new user if id not exists and email is null
180
- expect(
181
- await serverDB.query.users.findMany({ where: eq(users.id, anotherUserId) }),
182
- ).toHaveLength(1);
183
- });
184
- });
185
-
186
- describe('deleteUser', () => {
187
- it('should delete a user', async () => {
188
- expect(nextAuthAdapter).toBeDefined();
189
- expect(nextAuthAdapter.deleteUser).toBeDefined();
190
- // @ts-expect-error: deleteUser is defined
191
- await nextAuthAdapter.deleteUser(userId);
192
- const deletedUser = await serverDB.query.users.findFirst({ where: eq(users.id, userId) });
193
- expect(deletedUser).toBeUndefined();
194
- });
195
- });
196
-
197
- describe('getUser', () => {
198
- it('should get a user', async () => {
199
- expect(nextAuthAdapter).toBeDefined();
200
- expect(nextAuthAdapter.getUser).toBeDefined();
201
- // @ts-expect-error: getUser is defined
202
- const fetchedUser = await nextAuthAdapter.getUser(userId);
203
- expect(fetchedUser).toBeDefined();
204
- expect(fetchedUser?.id).toBe(user.id);
205
- expect(fetchedUser?.name).toBe(user.name);
206
- expect(fetchedUser?.email).toBe(user.email);
207
- expect(fetchedUser?.emailVerified).toEqual(user.emailVerified);
208
- expect(fetchedUser?.image).toBe(user.image);
209
- });
210
- });
211
-
212
- describe('getUserByEmail', () => {
213
- it('should get a user by email', async () => {
214
- expect(nextAuthAdapter).toBeDefined();
215
- expect(nextAuthAdapter.getUserByEmail).toBeDefined();
216
- // @ts-expect-error: getUserByEmail is defined
217
- const fetchedUser = await nextAuthAdapter.getUserByEmail(user.email);
218
- expect(fetchedUser).toBeDefined();
219
- expect(fetchedUser?.id).toBe(user.id);
220
- expect(fetchedUser?.name).toBe(user.name);
221
- expect(fetchedUser?.email).toBe(user.email);
222
- expect(fetchedUser?.emailVerified).toEqual(user.emailVerified);
223
- expect(fetchedUser?.image).toBe(user.image);
224
- });
225
- });
226
-
227
- describe('getUserByAccount', () => {
228
- it('should get a user by account', async () => {
229
- const account: AdapterAccount = {
230
- providerAccountId: 'provider-account-id',
231
- userId: userId,
232
- provider: 'auth0',
233
- type: 'email',
234
- };
235
- // @ts-expect-error: linkAccount is defined
236
- await nextAuthAdapter.linkAccount(account);
237
- expect(nextAuthAdapter).toBeDefined();
238
- expect(nextAuthAdapter.getUserByAccount).toBeDefined();
239
- // @ts-expect-error: getUserByAccount is defined
240
- const fetchedUser = await nextAuthAdapter.getUserByAccount(account);
241
- expect(fetchedUser).toBeDefined();
242
- expect(fetchedUser?.id).toBe(user.id);
243
- expect(fetchedUser?.name).toBe(user.name);
244
- expect(fetchedUser?.email).toBe(user.email);
245
- expect(fetchedUser?.emailVerified).toEqual(user.emailVerified);
246
- expect(fetchedUser?.image).toBe(user.image);
247
- });
248
- });
249
-
250
- describe('updateUser', () => {
251
- it('should update a user', async () => {
252
- expect(nextAuthAdapter).toBeDefined();
253
- expect(nextAuthAdapter.updateUser).toBeDefined();
254
- const updatedName = 'updated' + user.name;
255
- const updatedEmail = 'updated' + user.email;
256
- // @ts-expect-error: updateUser is defined
257
- const updatedUser = await nextAuthAdapter.updateUser({
258
- id: userId,
259
- name: updatedName,
260
- email: updatedEmail,
261
- });
262
- expect(updatedUser).toBeDefined();
263
- expect(updatedUser.id).toBe(userId);
264
- expect(updatedUser.name).toBe(updatedName);
265
- expect(updatedUser.email).toBe(updatedEmail);
266
- });
267
- });
268
- });
269
-
270
- describe('authenticators', () => {
271
- describe('createAuthenticator', () => {
272
- it('should create a new authenticator', async () => {
273
- // Create an authenticator and link to the exists user
274
- const params: AdapterAuthenticator = {
275
- credentialBackedUp: false,
276
- credentialDeviceType: 'type',
277
- credentialID: 'some-id',
278
- credentialPublicKey: 'some-key',
279
- userId: userId,
280
- providerAccountId: 'provider-account-id',
281
- counter: 1,
282
- };
283
- expect(nextAuthAdapter).toBeDefined();
284
- expect(nextAuthAdapter.createAuthenticator).toBeDefined();
285
- // @ts-expect-error: createAuthenticator is defined
286
- const authenticator = await nextAuthAdapter.createAuthenticator(params);
287
-
288
- expect(authenticator).toBeDefined();
289
- expect(authenticator.userId).toBe(params.userId);
290
- expect(authenticator.providerAccountId).toBe(params.providerAccountId);
291
- });
292
- });
293
-
294
- describe('getAuthenticator', () => {
295
- it('should get an authenticator', async () => {
296
- // Create an authenticator and link to the exists user
297
- const params: AdapterAuthenticator = {
298
- credentialBackedUp: false,
299
- credentialDeviceType: 'type',
300
- credentialID: 'some-id',
301
- credentialPublicKey: 'some-key',
302
- userId: userId,
303
- providerAccountId: 'provider-account-id',
304
- counter: 1,
305
- };
306
- // @ts-expect-error: createAuthenticator is defined
307
- await nextAuthAdapter.createAuthenticator(params);
308
- expect(nextAuthAdapter).toBeDefined();
309
- expect(nextAuthAdapter.getAuthenticator).toBeDefined();
310
- // @ts-expect-error: getAuthenticator is defined
311
- const fetchedAuthenticator = await nextAuthAdapter.getAuthenticator(params.credentialID);
312
- expect(fetchedAuthenticator).toBeDefined();
313
- expect(fetchedAuthenticator?.userId).toBe(params.userId);
314
- expect(fetchedAuthenticator?.providerAccountId).toBe(params.providerAccountId);
315
- });
316
- });
317
-
318
- describe('updateAuthenticatorCounter', () => {
319
- it('should update an authenticator counter', async () => {
320
- // Create an authenticator and link to the exists user
321
- const params: AdapterAuthenticator = {
322
- credentialBackedUp: false,
323
- credentialDeviceType: 'type',
324
- credentialID: 'some-id',
325
- credentialPublicKey: 'some-key',
326
- userId: userId,
327
- providerAccountId: 'provider-account-id',
328
- counter: 1,
329
- };
330
- // @ts-expect-error: createAuthenticator is defined
331
- await nextAuthAdapter.createAuthenticator(params);
332
- expect(nextAuthAdapter).toBeDefined();
333
- expect(nextAuthAdapter.updateAuthenticatorCounter).toBeDefined();
334
- // @ts-expect-error: updateAuthenticatorCounter is defined
335
- const updatedAuthenticator = await nextAuthAdapter.updateAuthenticatorCounter(
336
- params.credentialID,
337
- 2,
338
- );
339
- expect(updatedAuthenticator).toBeDefined();
340
- expect(updatedAuthenticator.counter).toBe(2);
341
- });
342
- });
343
-
344
- describe('listAuthenticatorsByUserId', () => {
345
- it('should list authenticators by user id', async () => {
346
- // Create an authenticator and link to the exists user
347
- const params: AdapterAuthenticator = {
348
- credentialBackedUp: false,
349
- credentialDeviceType: 'type',
350
- credentialID: 'some-id',
351
- credentialPublicKey: 'some-key',
352
- userId: userId,
353
- providerAccountId: 'provider-account-id',
354
- counter: 1,
355
- };
356
- // @ts-expect-error: createAuthenticator is defined
357
- await nextAuthAdapter.createAuthenticator(params);
358
- expect(nextAuthAdapter).toBeDefined();
359
- expect(nextAuthAdapter.listAuthenticatorsByUserId).toBeDefined();
360
- // @ts-expect-error: listAuthenticatorsByUserId is defined
361
- const authenticators = await nextAuthAdapter.listAuthenticatorsByUserId(userId);
362
- expect(authenticators).toBeDefined();
363
- expect(authenticators.length).toBeGreaterThan(0);
364
- expect(authenticators[0].userId).toBe(params.userId);
365
- expect(authenticators[0].providerAccountId).toBe(params.providerAccountId);
366
- });
367
- });
368
- });
369
-
370
- describe('session', () => {
371
- describe('createSession', () => {
372
- it('should create a new session', async () => {
373
- const data: AdapterSession = {
374
- sessionToken,
375
- userId: userId,
376
- expires: new Date(),
377
- };
378
- expect(nextAuthAdapter).toBeDefined();
379
- expect(nextAuthAdapter.createSession).toBeDefined();
380
-
381
- // @ts-expect-error: createSession is defined
382
- const session = await nextAuthAdapter.createSession(data);
383
-
384
- expect(session).toBeDefined();
385
- expect(session.sessionToken).toBe(data.sessionToken);
386
- expect(session.userId).toBe(data.userId);
387
- expect(session.expires).toEqual(data.expires);
388
- });
389
- });
390
-
391
- describe('updateSession', () => {
392
- it('should update a session', async () => {
393
- const data: AdapterSession = {
394
- sessionToken,
395
- userId: userId,
396
- expires: new Date(),
397
- };
398
- // @ts-expect-error: createSession is defined
399
- await nextAuthAdapter.createSession(data);
400
- const updatedExpires = new Date();
401
- expect(nextAuthAdapter).toBeDefined();
402
- expect(nextAuthAdapter.updateSession).toBeDefined();
403
- // @ts-expect-error: updateSession is defined
404
- const updatedSession = await nextAuthAdapter.updateSession({
405
- sessionToken,
406
- expires: updatedExpires,
407
- });
408
- expect(updatedSession).toBeDefined();
409
- expect(updatedSession?.sessionToken).toBe(data.sessionToken);
410
- expect(updatedSession?.expires).toEqual(updatedExpires);
411
- });
412
- });
413
-
414
- describe('getSessionAndUser', () => {
415
- it('should get a session and user', async () => {
416
- // create session
417
- const data = {
418
- sessionToken,
419
- userId: userId,
420
- expires: new Date(),
421
- };
422
- // @ts-expect-error: createSession is defined
423
- await nextAuthAdapter.createSession(data);
424
-
425
- // @ts-expect-error: getSessionAndUser is defined
426
- const sessionAndUser = await nextAuthAdapter.getSessionAndUser(sessionToken);
427
- expect(sessionAndUser?.session.sessionToken).toBe(sessionToken);
428
- expect(sessionAndUser?.user.id).toBe(user.id);
429
- });
430
- });
431
-
432
- describe('deleteSession', () => {
433
- it('should delete a session', async () => {
434
- const data = {
435
- sessionToken,
436
- userId: userId,
437
- expires: new Date(),
438
- };
439
- // @ts-expect-error: createSession is defined
440
- await nextAuthAdapter.createSession(data);
441
-
442
- // @ts-expect-error: deleteSession is defined
443
- await nextAuthAdapter.deleteSession(sessionToken);
444
- const session = await serverDB.query.nextauthSessions.findFirst({
445
- where: eq(nextauthSessions.sessionToken, sessionToken),
446
- });
447
- expect(session).toBeUndefined();
448
- });
449
- });
450
- });
451
-
452
- describe('verificationToken', () => {
453
- describe('createVerificationToken', () => {
454
- it('should create a new verification token', async () => {
455
- const token: VerificationToken = {
456
- identifier: 'identifier',
457
- expires: new Date(),
458
- token: 'token',
459
- };
460
- // @ts-expect-error: createVerificationToken is defined
461
- const createdToken = await nextAuthAdapter.createVerificationToken(token);
462
- expect(createdToken).toBeDefined();
463
- expect(createdToken?.identifier).toBe(token.identifier);
464
- expect(createdToken?.expires).toEqual(token.expires);
465
- expect(createdToken?.token).toBe(token.token);
466
- });
467
- });
468
-
469
- describe('useVerificationToken', () => {
470
- it('should use a verification token if exist', async () => {
471
- const token: VerificationToken = {
472
- identifier: 'identifier',
473
- expires: new Date(),
474
- token: 'token2',
475
- };
476
- // @ts-expect-error: createVerificationToken is defined
477
- await nextAuthAdapter.createVerificationToken(token);
478
- // @ts-expect-error: useVerificationToken is defined
479
- await nextAuthAdapter.useVerificationToken(token.token);
480
- });
481
-
482
- it('should return null if the token does not exist', async () => {
483
- const token: VerificationToken = {
484
- identifier: 'identifier',
485
- expires: new Date(),
486
- token: 'token-not-exist',
487
- };
488
- // @ts-expect-error: useVerificationToken is defined
489
- const result = await nextAuthAdapter.useVerificationToken(token.token);
490
- expect(result).toBeNull();
491
- });
492
- });
493
- });
494
-
495
- describe('accounts', () => {
496
- describe('linkAccount', () => {
497
- it('should link an account', async () => {
498
- const account: AdapterAccount = {
499
- providerAccountId: 'provider-account-id',
500
- userId: userId,
501
- provider: 'auth0',
502
- type: 'email',
503
- };
504
- // @ts-expect-error: linkAccount is defined
505
- const insertedAccount = await nextAuthAdapter.linkAccount(account);
506
- expect(insertedAccount).toBeDefined();
507
- expect(insertedAccount?.providerAccountId).toBe(account.providerAccountId);
508
- expect(insertedAccount?.userId).toBe(userId);
509
- expect(insertedAccount?.provider).toBe(account.provider);
510
- expect(insertedAccount?.type).toBe(account.type);
511
- });
512
- });
513
-
514
- describe('getAccount', () => {
515
- it('should get an account', async () => {
516
- const account: AdapterAccount = {
517
- providerAccountId: 'provider-account-id',
518
- userId: userId,
519
- provider: 'auth0',
520
- type: 'email',
521
- };
522
- // @ts-expect-error: linkAccount is defined
523
- await nextAuthAdapter.linkAccount(account);
524
- // @ts-expect-error: getAccount is defined
525
- const fetchedAccount = await nextAuthAdapter.getAccount(
526
- account.providerAccountId,
527
- account.provider,
528
- );
529
- expect(fetchedAccount).toBeDefined();
530
- expect(fetchedAccount?.providerAccountId).toBe(account.providerAccountId);
531
- expect(fetchedAccount?.userId).toBe(userId);
532
- expect(fetchedAccount?.provider).toBe(account.provider);
533
- expect(fetchedAccount?.type).toBe(account.type);
534
- });
535
- });
536
-
537
- describe('unlinkAccount', () => {
538
- it('should unlink an account', async () => {
539
- const account: AdapterAccount = {
540
- providerAccountId: 'provider-account-id',
541
- userId: userId,
542
- provider: 'auth0',
543
- type: 'email',
544
- };
545
- // @ts-expect-error: linkAccount is defined
546
- await nextAuthAdapter.linkAccount(account);
547
- // @ts-expect-error: unlinkAccount is defined
548
- await nextAuthAdapter.unlinkAccount(account);
549
- const fetchedAccount = await serverDB.query.nextauthAccounts.findFirst({
550
- where: eq(nextauthAccounts.providerAccountId, account.providerAccountId),
551
- });
552
- expect(fetchedAccount).toBeUndefined();
553
- });
554
- });
555
- });
556
- });
@@ -1,26 +0,0 @@
1
- import NextAuth from 'next-auth';
2
-
3
- import authConfig from './auth.config';
4
-
5
- /**
6
- * NextAuth initialization without Database adapter
7
- *
8
- * @example
9
- * ```ts
10
- * import NextAuthEdge from '@/libs/next-auth/edge';
11
- * const { auth } = NextAuthEdge;
12
- * ```
13
- *
14
- * @note
15
- * We currently use `jwt` strategy for session management.
16
- * So you don't need to import `signIn` or `signOut` from
17
- * this module, just import from `next-auth` directly.
18
- *
19
- * Inside react component
20
- * @example
21
- * ```ts
22
- * import { signOut } from 'next-auth/react';
23
- * signOut();
24
- * ```
25
- */
26
- export default NextAuth(authConfig);
@@ -1,108 +0,0 @@
1
- // @vitest-environment node
2
- import { NextResponse } from 'next/server';
3
- import { beforeEach, describe, expect, it, vi } from 'vitest';
4
-
5
- import { UserModel } from '@/database/models/user';
6
- import { UserItem } from '@/database/schemas';
7
- import { serverDB } from '@/database/server';
8
- import { pino } from '@/libs/logger';
9
-
10
- import { NextAuthUserService } from './index';
11
-
12
- vi.mock('@/libs/logger', () => ({
13
- pino: {
14
- info: vi.fn(),
15
- warn: vi.fn(),
16
- },
17
- }));
18
-
19
- vi.mock('@/database/models/user');
20
- vi.mock('@/database/server');
21
-
22
- describe('NextAuthUserService', () => {
23
- let service: NextAuthUserService;
24
-
25
- beforeEach(async () => {
26
- vi.clearAllMocks();
27
- service = new NextAuthUserService(serverDB);
28
- });
29
-
30
- describe('safeUpdateUser', () => {
31
- const mockUser = {
32
- id: 'user-123',
33
- email: 'test@example.com',
34
- };
35
-
36
- const mockAccount = {
37
- provider: 'github',
38
- providerAccountId: '12345',
39
- };
40
-
41
- const mockUpdateData: Partial<UserItem> = {
42
- avatar: 'https://example.com/avatar.jpg',
43
- email: 'new@example.com',
44
- fullName: 'Test User',
45
- };
46
-
47
- it('should update user when user is found', async () => {
48
- const mockUserModel = {
49
- updateUser: vi.fn().mockResolvedValue({}),
50
- };
51
-
52
- vi.mocked(UserModel).mockImplementation(() => mockUserModel as any);
53
-
54
- // Mock the adapter directly on the service instance
55
- service.adapter = {
56
- getUserByAccount: vi.fn().mockResolvedValue(mockUser),
57
- };
58
-
59
- const response = await service.safeUpdateUser(mockAccount, mockUpdateData);
60
-
61
- expect(pino.info).toHaveBeenCalledWith(
62
- `updating user "${JSON.stringify(mockAccount)}" due to webhook`,
63
- );
64
-
65
- expect(service.adapter.getUserByAccount).toHaveBeenCalledWith(mockAccount);
66
- expect(UserModel).toHaveBeenCalledWith(serverDB, mockUser.id);
67
- expect(mockUserModel.updateUser).toHaveBeenCalledWith(mockUpdateData);
68
-
69
- expect(response).toBeInstanceOf(NextResponse);
70
- expect(response.status).toBe(200);
71
- const data = await response.json();
72
- expect(data).toEqual({ message: 'user updated', success: true });
73
- });
74
-
75
- it('should handle case when user is not found', async () => {
76
- // Mock the adapter directly on the service instance
77
- service.adapter = {
78
- getUserByAccount: vi.fn().mockResolvedValue(null),
79
- };
80
-
81
- const response = await service.safeUpdateUser(mockAccount, mockUpdateData);
82
-
83
- expect(pino.warn).toHaveBeenCalledWith(
84
- `[${mockAccount.provider}]: Webhooks handler user "${JSON.stringify(mockAccount)}" update for "${JSON.stringify(mockUpdateData)}", but no user was found by the providerAccountId.`,
85
- );
86
-
87
- expect(UserModel).not.toHaveBeenCalled();
88
-
89
- expect(response).toBeInstanceOf(NextResponse);
90
- expect(response.status).toBe(200);
91
- const data = await response.json();
92
- expect(data).toEqual({ message: 'user updated', success: true });
93
- });
94
-
95
- it('should handle errors during user update', async () => {
96
- const mockError = new Error('Database error');
97
-
98
- // Mock the adapter directly on the service instance
99
- service.adapter = {
100
- getUserByAccount: vi.fn().mockRejectedValue(mockError),
101
- };
102
-
103
- await expect(service.safeUpdateUser(mockAccount, mockUpdateData)).rejects.toThrow(mockError);
104
-
105
- expect(UserModel).not.toHaveBeenCalled();
106
- });
107
- });
108
- });