@workos-inc/authkit-nextjs 2.13.0 → 2.14.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.
@@ -6,41 +6,37 @@ import { useAuth } from './authkit-provider.js';
6
6
  import { useAccessToken } from './useAccessToken.js';
7
7
  import { tokenStore } from './tokenStore.js';
8
8
 
9
- jest.mock('../actions.js', () => ({
10
- getAccessTokenAction: jest.fn(),
11
- refreshAccessTokenAction: jest.fn(),
9
+ vi.mock('../actions.js', () => ({
10
+ getAccessTokenAction: vi.fn(),
11
+ refreshAccessTokenAction: vi.fn(),
12
12
  }));
13
13
 
14
- jest.mock('./authkit-provider.js', () => {
15
- const originalModule = jest.requireActual('./authkit-provider.js');
14
+ vi.mock('./authkit-provider.js', async () => {
15
+ const originalModule = await vi.importActual<typeof import('./authkit-provider.js')>('./authkit-provider.js');
16
16
  return {
17
17
  ...originalModule,
18
- useAuth: jest.fn(),
18
+ useAuth: vi.fn(),
19
19
  };
20
20
  });
21
21
 
22
22
  describe('useAccessToken', () => {
23
23
  beforeEach(() => {
24
24
  tokenStore.reset();
25
- jest.resetAllMocks();
26
- jest.useFakeTimers();
25
+ vi.resetAllMocks();
26
+ vi.useFakeTimers({ shouldAdvanceTime: true });
27
27
 
28
- // Reset mock implementations to avoid test interference
29
- (getAccessTokenAction as jest.Mock).mockReset();
30
- (refreshAccessTokenAction as jest.Mock).mockReset();
31
-
32
- (useAuth as jest.Mock).mockImplementation(() => ({
28
+ (useAuth as Mock).mockImplementation(() => ({
33
29
  user: { id: 'user_123' },
34
30
  sessionId: 'session_123',
35
- refreshAuth: jest.fn().mockResolvedValue({}),
31
+ refreshAuth: vi.fn().mockResolvedValue({}),
36
32
  }));
37
33
  });
38
34
 
39
35
  afterEach(() => {
40
- jest.clearAllTimers();
41
- jest.useRealTimers();
36
+ vi.clearAllTimers();
37
+ vi.useRealTimers();
42
38
  tokenStore.reset();
43
- jest.clearAllMocks();
39
+ vi.clearAllMocks();
44
40
  });
45
41
 
46
42
  const TestComponent = () => {
@@ -60,7 +56,7 @@ describe('useAccessToken', () => {
60
56
  it('should fetch an access token on mount and show loading state initially', async () => {
61
57
  const mockToken =
62
58
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
63
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(mockToken);
59
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(mockToken);
64
60
 
65
61
  const { getByTestId } = render(<TestComponent />);
66
62
 
@@ -92,8 +88,8 @@ describe('useAccessToken', () => {
92
88
  const refreshedToken =
93
89
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
94
90
 
95
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(expiringToken);
96
- (refreshAccessTokenAction as jest.Mock).mockResolvedValueOnce(refreshedToken);
91
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(expiringToken);
92
+ (refreshAccessTokenAction as Mock).mockResolvedValueOnce(refreshedToken);
97
93
 
98
94
  const { getByTestId } = render(<TestComponent />);
99
95
 
@@ -115,8 +111,8 @@ describe('useAccessToken', () => {
115
111
  const refreshedToken =
116
112
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJyZWZyZXNoZWQiLCJzaWQiOiJzZXNzaW9uXzEyMyIsImV4cCI6OTk5OTk5OTk5OX0.mock-signature-2';
117
113
 
118
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(initialToken);
119
- (refreshAccessTokenAction as jest.Mock).mockResolvedValueOnce(refreshedToken);
114
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(initialToken);
115
+ (refreshAccessTokenAction as Mock).mockResolvedValueOnce(refreshedToken);
120
116
 
121
117
  const { getByTestId } = render(<TestComponent />);
122
118
 
@@ -141,10 +137,10 @@ describe('useAccessToken', () => {
141
137
  });
142
138
 
143
139
  it('should handle the not loggged in state', async () => {
144
- (useAuth as jest.Mock).mockImplementation(() => ({
140
+ (useAuth as Mock).mockImplementation(() => ({
145
141
  user: undefined,
146
142
  sessionId: undefined,
147
- refreshAuth: jest.fn().mockResolvedValue({}),
143
+ refreshAuth: vi.fn().mockResolvedValue({}),
148
144
  }));
149
145
 
150
146
  const { getByTestId } = render(<TestComponent />);
@@ -157,7 +153,7 @@ describe('useAccessToken', () => {
157
153
 
158
154
  it('should handle errors during token fetch', async () => {
159
155
  const error = new Error('Failed to fetch token');
160
- (getAccessTokenAction as jest.Mock).mockRejectedValueOnce(error);
156
+ (getAccessTokenAction as Mock).mockRejectedValueOnce(error);
161
157
 
162
158
  const { getByTestId } = render(<TestComponent />);
163
159
 
@@ -176,8 +172,8 @@ describe('useAccessToken', () => {
176
172
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
177
173
  const error = new Error('Failed to refresh token');
178
174
 
179
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(initialToken);
180
- (refreshAccessTokenAction as jest.Mock).mockRejectedValueOnce(error);
175
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(initialToken);
176
+ (refreshAccessTokenAction as Mock).mockRejectedValueOnce(error);
181
177
 
182
178
  const { getByTestId } = render(<TestComponent />);
183
179
 
@@ -200,13 +196,13 @@ describe('useAccessToken', () => {
200
196
  it('should reset token state when user is undefined', async () => {
201
197
  const mockToken =
202
198
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
203
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(mockToken);
199
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(mockToken);
204
200
 
205
201
  // First render with user
206
- (useAuth as jest.Mock).mockImplementation(() => ({
202
+ (useAuth as Mock).mockImplementation(() => ({
207
203
  user: { id: 'user_123' },
208
204
  sessionId: 'session_123',
209
- refreshAuth: jest.fn().mockResolvedValue({}),
205
+ refreshAuth: vi.fn().mockResolvedValue({}),
210
206
  }));
211
207
 
212
208
  const { getByTestId, rerender } = render(<TestComponent />);
@@ -215,10 +211,10 @@ describe('useAccessToken', () => {
215
211
  expect(getByTestId('token')).toHaveTextContent(mockToken);
216
212
  });
217
213
 
218
- (useAuth as jest.Mock).mockImplementation(() => ({
214
+ (useAuth as Mock).mockImplementation(() => ({
219
215
  user: undefined,
220
216
  sessionId: undefined,
221
- refreshAuth: jest.fn().mockResolvedValue({}),
217
+ refreshAuth: vi.fn().mockResolvedValue({}),
222
218
  }));
223
219
 
224
220
  rerender(<TestComponent />);
@@ -230,7 +226,7 @@ describe('useAccessToken', () => {
230
226
 
231
227
  it('should handle invalid tokens gracefully', async () => {
232
228
  const invalidToken = 'invalid-token';
233
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(invalidToken);
229
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(invalidToken);
234
230
 
235
231
  const { getByTestId } = render(<TestComponent />);
236
232
 
@@ -246,7 +242,7 @@ describe('useAccessToken', () => {
246
242
  const mockToken =
247
243
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
248
244
 
249
- (getAccessTokenAction as jest.Mock).mockRejectedValueOnce(error).mockResolvedValueOnce(mockToken);
245
+ (getAccessTokenAction as Mock).mockRejectedValueOnce(error).mockResolvedValueOnce(mockToken);
250
246
 
251
247
  const { getByTestId } = render(<TestComponent />);
252
248
 
@@ -257,7 +253,7 @@ describe('useAccessToken', () => {
257
253
  });
258
254
 
259
255
  act(() => {
260
- jest.advanceTimersByTime(5 * 60 * 1000); // RETRY_DELAY
256
+ vi.advanceTimersByTime(5 * 60 * 1000); // RETRY_DELAY
261
257
  });
262
258
 
263
259
  // Loading should remain false during retry
@@ -283,8 +279,8 @@ describe('useAccessToken', () => {
283
279
  const expiringToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.${btoa(JSON.stringify(payload))}.mock-signature`;
284
280
  const error = new Error('Failed to refresh token');
285
281
 
286
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(expiringToken);
287
- (refreshAccessTokenAction as jest.Mock).mockRejectedValueOnce(error);
282
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(expiringToken);
283
+ (refreshAccessTokenAction as Mock).mockRejectedValueOnce(error);
288
284
 
289
285
  const { getByTestId } = render(<TestComponent />);
290
286
 
@@ -301,7 +297,7 @@ describe('useAccessToken', () => {
301
297
 
302
298
  it('should handle token with an invalid payload format', async () => {
303
299
  const badPayloadToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.invalidpayload.mock-signature';
304
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(badPayloadToken);
300
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(badPayloadToken);
305
301
 
306
302
  const { getByTestId } = render(<TestComponent />);
307
303
 
@@ -313,7 +309,7 @@ describe('useAccessToken', () => {
313
309
  });
314
310
 
315
311
  it('should immediately try to update token when token is undefined', async () => {
316
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(undefined).mockResolvedValueOnce(undefined);
312
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(undefined).mockResolvedValueOnce(undefined);
317
313
 
318
314
  const { getByTestId } = render(<TestComponent />);
319
315
 
@@ -327,17 +323,17 @@ describe('useAccessToken', () => {
327
323
 
328
324
  it('should react to sessionId changes', async () => {
329
325
  // Clear any previous mocks to ensure clean state
330
- jest.clearAllMocks();
326
+ vi.clearAllMocks();
331
327
 
332
328
  const token1 = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMSIsImV4cCI6OTk5OTk5OTk5OX0.mock-signature-1';
333
329
  const token2 = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMSIsImV4cCI6OTk5OTk5OTk5OX0.mock-signature-2';
334
330
 
335
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(token1).mockResolvedValueOnce(token2);
331
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(token1).mockResolvedValueOnce(token2);
336
332
 
337
- (useAuth as jest.Mock).mockImplementation(() => ({
333
+ (useAuth as Mock).mockImplementation(() => ({
338
334
  user: { id: 'user1' },
339
335
  sessionId: 'session1',
340
- refreshAuth: jest.fn().mockResolvedValue({}),
336
+ refreshAuth: vi.fn().mockResolvedValue({}),
341
337
  }));
342
338
 
343
339
  const { rerender } = render(<TestComponent />);
@@ -346,10 +342,10 @@ describe('useAccessToken', () => {
346
342
  expect(getAccessTokenAction).toHaveBeenCalledTimes(1);
347
343
  });
348
344
 
349
- (useAuth as jest.Mock).mockImplementation(() => ({
345
+ (useAuth as Mock).mockImplementation(() => ({
350
346
  user: { id: 'user1' }, // Same user ID
351
347
  sessionId: 'session2',
352
- refreshAuth: jest.fn().mockResolvedValue({}),
348
+ refreshAuth: vi.fn().mockResolvedValue({}),
353
349
  }));
354
350
 
355
351
  rerender(<TestComponent />);
@@ -360,8 +356,8 @@ describe('useAccessToken', () => {
360
356
  });
361
357
 
362
358
  it('should prevent concurrent token fetches via updateToken', async () => {
363
- jest.clearAllMocks();
364
- (getAccessTokenAction as jest.Mock).mockReset();
359
+ vi.clearAllMocks();
360
+ (getAccessTokenAction as Mock).mockReset();
365
361
 
366
362
  const mockToken =
367
363
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
@@ -374,7 +370,7 @@ describe('useAccessToken', () => {
374
370
  }, 0);
375
371
  });
376
372
 
377
- (getAccessTokenAction as jest.Mock).mockImplementation(() => {
373
+ (getAccessTokenAction as Mock).mockImplementation(() => {
378
374
  fetchCalls++;
379
375
  return tokenPromise;
380
376
  });
@@ -397,7 +393,7 @@ describe('useAccessToken', () => {
397
393
  });
398
394
 
399
395
  it('should prevent concurrent manual refresh operations', async () => {
400
- jest.clearAllMocks();
396
+ vi.clearAllMocks();
401
397
 
402
398
  let refreshCalls = 0;
403
399
 
@@ -412,12 +408,12 @@ describe('useAccessToken', () => {
412
408
  setTimeout(() => resolve(refreshedToken), 10);
413
409
  });
414
410
 
415
- (refreshAccessTokenAction as jest.Mock).mockImplementation(() => {
411
+ (refreshAccessTokenAction as Mock).mockImplementation(() => {
416
412
  refreshCalls++;
417
413
  return refreshPromise;
418
414
  });
419
415
 
420
- (getAccessTokenAction as jest.Mock).mockImplementation(() => {
416
+ (getAccessTokenAction as Mock).mockImplementation(() => {
421
417
  return Promise.resolve(mockToken);
422
418
  });
423
419
 
@@ -446,7 +442,7 @@ describe('useAccessToken', () => {
446
442
 
447
443
  it('should handle non-Error objects thrown during token fetch', async () => {
448
444
  // Simulate a string error being thrown
449
- (getAccessTokenAction as jest.Mock).mockImplementation(() => {
445
+ (getAccessTokenAction as Mock).mockImplementation(() => {
450
446
  throw 'String error message';
451
447
  });
452
448
 
@@ -461,13 +457,13 @@ describe('useAccessToken', () => {
461
457
 
462
458
  it('should show loading state immediately on first render when user exists but no token', () => {
463
459
  // Mock user with no token initially
464
- (useAuth as jest.Mock).mockImplementation(() => ({
460
+ (useAuth as Mock).mockImplementation(() => ({
465
461
  user: { id: 'user_123' },
466
462
  sessionId: 'session_123',
467
- refreshAuth: jest.fn().mockResolvedValue({}),
463
+ refreshAuth: vi.fn().mockResolvedValue({}),
468
464
  }));
469
465
 
470
- (getAccessTokenAction as jest.Mock).mockImplementation(
466
+ (getAccessTokenAction as Mock).mockImplementation(
471
467
  () => new Promise((resolve) => setTimeout(() => resolve('token'), 100)),
472
468
  );
473
469
 
@@ -482,12 +478,12 @@ describe('useAccessToken', () => {
482
478
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJleGlzdGluZyIsInNpZCI6InNlc3Npb24xMjMiLCJleHAiOjk5OTk5OTk5OTl9.existing';
483
479
 
484
480
  await act(async () => {
485
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(existingToken);
481
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(existingToken);
486
482
  await tokenStore.getAccessTokenSilently();
487
483
  });
488
484
 
489
485
  // Reset the mock to track new calls
490
- (getAccessTokenAction as jest.Mock).mockClear();
486
+ (getAccessTokenAction as Mock).mockClear();
491
487
 
492
488
  const { getByTestId } = render(<TestComponent />);
493
489
 
@@ -511,8 +507,8 @@ describe('useAccessToken', () => {
511
507
  resolveRefreshPromise = resolve;
512
508
  });
513
509
 
514
- (refreshAccessTokenAction as jest.Mock).mockReturnValue(refreshPromise);
515
- (getAccessTokenAction as jest.Mock).mockResolvedValue(initialToken);
510
+ (refreshAccessTokenAction as Mock).mockReturnValue(refreshPromise);
511
+ (getAccessTokenAction as Mock).mockResolvedValue(initialToken);
516
512
 
517
513
  const { getByTestId } = render(<TestComponent />);
518
514
 
@@ -541,7 +537,7 @@ describe('useAccessToken', () => {
541
537
  it('should clear refresh timeout on unmount', async () => {
542
538
  const mockToken =
543
539
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
544
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(mockToken);
540
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(mockToken);
545
541
 
546
542
  const { getByTestId, unmount } = render(<TestComponent />);
547
543
 
@@ -555,7 +551,7 @@ describe('useAccessToken', () => {
555
551
  it('should handle edge cases when token data is null', async () => {
556
552
  // Create a token that resembles a JWT but with a null payload
557
553
  const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.bnVsbA==.mock-signature'; // "null" in base64
558
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(token);
554
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(token);
559
555
 
560
556
  const { getByTestId } = render(<TestComponent />);
561
557
 
@@ -570,7 +566,7 @@ describe('useAccessToken', () => {
570
566
  it('should handle errors with string messages instead of Error objects', async () => {
571
567
  const error = 'String error message';
572
568
  const errorObj = new Error(error);
573
- (getAccessTokenAction as jest.Mock).mockRejectedValueOnce(errorObj);
569
+ (getAccessTokenAction as Mock).mockRejectedValueOnce(errorObj);
574
570
 
575
571
  const { getByTestId } = render(<TestComponent />);
576
572
 
@@ -585,9 +581,9 @@ describe('useAccessToken', () => {
585
581
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
586
582
  const stringError = 'String error directly'; // Not wrapped in Error object
587
583
 
588
- (getAccessTokenAction as jest.Mock).mockResolvedValueOnce(initialToken);
584
+ (getAccessTokenAction as Mock).mockResolvedValueOnce(initialToken);
589
585
  // Mock refreshAccessTokenAction to reject with a string, not an Error object
590
- (refreshAccessTokenAction as jest.Mock).mockImplementation(() => {
586
+ (refreshAccessTokenAction as Mock).mockImplementation(() => {
591
587
  return Promise.reject(stringError); // Directly reject with string
592
588
  });
593
589
 
@@ -613,12 +609,12 @@ describe('useAccessToken', () => {
613
609
  const token =
614
610
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
615
611
 
616
- (getAccessTokenAction as jest.Mock).mockResolvedValue(token);
612
+ (getAccessTokenAction as Mock).mockResolvedValue(token);
617
613
 
618
- (useAuth as jest.Mock).mockImplementation(() => ({
614
+ (useAuth as Mock).mockImplementation(() => ({
619
615
  user: { id: 'user_123' },
620
616
  sessionId: 'session_123',
621
- refreshAuth: jest.fn().mockResolvedValue({}),
617
+ refreshAuth: vi.fn().mockResolvedValue({}),
622
618
  }));
623
619
 
624
620
  const { getByTestId, rerender } = render(<TestComponent />);
@@ -628,10 +624,10 @@ describe('useAccessToken', () => {
628
624
  expect(getAccessTokenAction).toHaveBeenCalledTimes(1);
629
625
  });
630
626
 
631
- (useAuth as jest.Mock).mockImplementation(() => ({
627
+ (useAuth as Mock).mockImplementation(() => ({
632
628
  user: { id: 'user_456' }, // Different user
633
629
  sessionId: 'session_123', // Same session
634
- refreshAuth: jest.fn().mockResolvedValue({}),
630
+ refreshAuth: vi.fn().mockResolvedValue({}),
635
631
  }));
636
632
 
637
633
  rerender(<TestComponent />);
@@ -642,10 +638,10 @@ describe('useAccessToken', () => {
642
638
  });
643
639
 
644
640
  it('should handle getAccessToken when user is not authenticated', async () => {
645
- (useAuth as jest.Mock).mockImplementation(() => ({
641
+ (useAuth as Mock).mockImplementation(() => ({
646
642
  user: null,
647
643
  sessionId: undefined,
648
- refreshAuth: jest.fn().mockResolvedValue({}),
644
+ refreshAuth: vi.fn().mockResolvedValue({}),
649
645
  }));
650
646
 
651
647
  const TestComponentWithGetAccessToken = () => {
@@ -670,11 +666,11 @@ describe('useAccessToken', () => {
670
666
  const mockToken =
671
667
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2lkIjoic2Vzc2lvbl8xMjMiLCJleHAiOjk5OTk5OTk5OTl9.mock-signature';
672
668
 
673
- (getAccessTokenAction as jest.Mock).mockResolvedValue(mockToken);
674
- (useAuth as jest.Mock).mockImplementation(() => ({
669
+ (getAccessTokenAction as Mock).mockResolvedValue(mockToken);
670
+ (useAuth as Mock).mockImplementation(() => ({
675
671
  user: { id: 'user_123' },
676
672
  sessionId: 'session_123',
677
- refreshAuth: jest.fn().mockResolvedValue({}),
673
+ refreshAuth: vi.fn().mockResolvedValue({}),
678
674
  }));
679
675
 
680
676
  const TestComponentWithGetAccessToken = () => {
@@ -696,7 +692,7 @@ describe('useAccessToken', () => {
696
692
 
697
693
  // Advance timers to trigger getAccessToken call
698
694
  act(() => {
699
- jest.advanceTimersByTime(100);
695
+ vi.advanceTimersByTime(100);
700
696
  });
701
697
 
702
698
  await waitFor(() => {
@@ -705,10 +701,10 @@ describe('useAccessToken', () => {
705
701
  });
706
702
 
707
703
  it('should handle manual refresh when user is not authenticated', async () => {
708
- (useAuth as jest.Mock).mockImplementation(() => ({
704
+ (useAuth as Mock).mockImplementation(() => ({
709
705
  user: null,
710
706
  sessionId: undefined,
711
- refreshAuth: jest.fn().mockResolvedValue({}),
707
+ refreshAuth: vi.fn().mockResolvedValue({}),
712
708
  }));
713
709
 
714
710
  const TestComponentWithRefresh = () => {
@@ -3,25 +3,25 @@ import { render, waitFor } from '@testing-library/react';
3
3
  import React from 'react';
4
4
  import { useAuth } from './authkit-provider.js';
5
5
 
6
- jest.mock('../actions.js', () => ({
7
- getAccessTokenAction: jest.fn(),
8
- refreshAccessTokenAction: jest.fn(),
6
+ vi.mock('../actions.js', () => ({
7
+ getAccessTokenAction: vi.fn(),
8
+ refreshAccessTokenAction: vi.fn(),
9
9
  }));
10
10
 
11
- jest.mock('./authkit-provider.js', () => {
12
- const originalModule = jest.requireActual('./authkit-provider.js');
11
+ vi.mock('./authkit-provider.js', async () => {
12
+ const originalModule = await vi.importActual<typeof import('./authkit-provider.js')>('./authkit-provider.js');
13
13
  return {
14
14
  ...originalModule,
15
- useAuth: jest.fn(),
15
+ useAuth: vi.fn(),
16
16
  };
17
17
  });
18
18
 
19
- jest.mock('./useAccessToken.js', () => ({
20
- useAccessToken: jest.fn(() => ({ accessToken: undefined })),
19
+ vi.mock('./useAccessToken.js', () => ({
20
+ useAccessToken: vi.fn(() => ({ accessToken: undefined })),
21
21
  }));
22
22
 
23
- jest.mock('jose', () => ({
24
- decodeJwt: jest.fn((token: string) => {
23
+ vi.mock('jose', () => ({
24
+ decodeJwt: vi.fn((token: string) => {
25
25
  if (token === 'malformed-token' || token === 'throw-error-token') {
26
26
  throw new Error('Invalid JWT');
27
27
  }
@@ -42,21 +42,21 @@ import { useTokenClaims } from './useTokenClaims.js';
42
42
 
43
43
  describe('useTokenClaims', () => {
44
44
  beforeEach(() => {
45
- jest.clearAllMocks();
46
- jest.useFakeTimers();
45
+ vi.clearAllMocks();
46
+ vi.useFakeTimers({ shouldAdvanceTime: true });
47
47
 
48
- (useAuth as jest.Mock).mockImplementation(() => ({
48
+ (useAuth as Mock).mockImplementation(() => ({
49
49
  user: { id: 'user_123' },
50
50
  sessionId: 'session_123',
51
- refreshAuth: jest.fn().mockResolvedValue({}),
51
+ refreshAuth: vi.fn().mockResolvedValue({}),
52
52
  }));
53
53
 
54
54
  // Reset useAccessToken mock to default
55
- (useAccessToken as jest.Mock).mockReturnValue({ accessToken: undefined });
55
+ (useAccessToken as Mock).mockReturnValue({ accessToken: undefined });
56
56
  });
57
57
 
58
58
  afterEach(() => {
59
- jest.useRealTimers();
59
+ vi.useRealTimers();
60
60
  });
61
61
 
62
62
  const TokenClaimsTestComponent = () => {
@@ -69,7 +69,7 @@ describe('useTokenClaims', () => {
69
69
  };
70
70
 
71
71
  it('should return empty object when no access token is available', async () => {
72
- (useAccessToken as jest.Mock).mockReturnValue({ accessToken: undefined });
72
+ (useAccessToken as Mock).mockReturnValue({ accessToken: undefined });
73
73
 
74
74
  const { getByTestId } = render(<TokenClaimsTestComponent />);
75
75
 
@@ -101,7 +101,7 @@ describe('useTokenClaims', () => {
101
101
  };
102
102
  const token = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.${btoa(JSON.stringify(payload))}.mock-signature`;
103
103
 
104
- (useAccessToken as jest.Mock).mockReturnValue({ accessToken: token });
104
+ (useAccessToken as Mock).mockReturnValue({ accessToken: token });
105
105
 
106
106
  const { getByTestId } = render(<TokenClaimsTestComponent />);
107
107
 
@@ -129,7 +129,7 @@ describe('useTokenClaims', () => {
129
129
  };
130
130
  const token = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.${btoa(JSON.stringify(payload))}.mock-signature`;
131
131
 
132
- (useAccessToken as jest.Mock).mockReturnValue({ accessToken: token });
132
+ (useAccessToken as Mock).mockReturnValue({ accessToken: token });
133
133
 
134
134
  const { getByTestId } = render(<TokenClaimsTestComponent />);
135
135
 
@@ -147,7 +147,7 @@ describe('useTokenClaims', () => {
147
147
  };
148
148
  const token = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.${btoa(JSON.stringify(payload))}.mock-signature`;
149
149
 
150
- (useAccessToken as jest.Mock).mockReturnValue({ accessToken: token });
150
+ (useAccessToken as Mock).mockReturnValue({ accessToken: token });
151
151
 
152
152
  const { getByTestId } = render(<TokenClaimsTestComponent />);
153
153
 
@@ -175,7 +175,7 @@ describe('useTokenClaims', () => {
175
175
  };
176
176
  const token = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.${btoa(JSON.stringify(payload))}.mock-signature`;
177
177
 
178
- (useAccessToken as jest.Mock).mockReturnValue({ accessToken: token });
178
+ (useAccessToken as Mock).mockReturnValue({ accessToken: token });
179
179
 
180
180
  const { getByTestId } = render(<TokenClaimsTestComponent />);
181
181
 
@@ -185,7 +185,7 @@ describe('useTokenClaims', () => {
185
185
  });
186
186
 
187
187
  it('should return empty object when decodeJwt throws an error', async () => {
188
- (useAccessToken as jest.Mock).mockReturnValue({ accessToken: 'malformed-token' });
188
+ (useAccessToken as Mock).mockReturnValue({ accessToken: 'malformed-token' });
189
189
 
190
190
  const { getByTestId } = render(<TokenClaimsTestComponent />);
191
191
 
@@ -1,14 +1,13 @@
1
- import { describe, it, expect } from '@jest/globals';
2
-
3
- // Mock at the top of the file
4
- jest.mock('./env-variables');
5
-
6
1
  describe('cookie.ts', () => {
7
2
  beforeEach(() => {
8
3
  // Clear all mocks before each test
9
- jest.clearAllMocks();
10
- // Reset modules
11
- jest.resetModules();
4
+ vi.clearAllMocks();
5
+ // Reset modules to ensure fresh imports
6
+ vi.resetModules();
7
+ // Re-mock env-variables with a fresh copy each time
8
+ vi.doMock('./env-variables', async (importOriginal) => {
9
+ return { ...(await importOriginal<typeof import('./env-variables')>()) };
10
+ });
12
11
  });
13
12
 
14
13
  describe('getCookieOptions', () => {
@@ -1,25 +1,24 @@
1
- import { describe, it, expect, beforeEach, jest } from '@jest/globals';
2
1
  import { getAuthorizationUrl } from './get-authorization-url.js';
3
2
  import { headers } from 'next/headers';
4
3
  import { getWorkOS } from './workos.js';
5
4
 
6
- jest.mock('next/headers');
7
-
8
5
  // Mock dependencies
9
- const fakeWorkosInstance = {
10
- userManagement: {
11
- getAuthorizationUrl: jest.fn(),
6
+ const { fakeWorkosInstance } = vi.hoisted(() => ({
7
+ fakeWorkosInstance: {
8
+ userManagement: {
9
+ getAuthorizationUrl: vi.fn(),
10
+ },
12
11
  },
13
- };
12
+ }));
14
13
 
15
- jest.mock('./workos', () => ({
16
- getWorkOS: jest.fn(() => fakeWorkosInstance),
14
+ vi.mock('./workos', () => ({
15
+ getWorkOS: vi.fn(() => fakeWorkosInstance),
17
16
  }));
18
17
 
19
18
  describe('getAuthorizationUrl', () => {
20
19
  const workos = getWorkOS();
21
20
  beforeEach(() => {
22
- jest.clearAllMocks();
21
+ vi.clearAllMocks();
23
22
  });
24
23
 
25
24
  it('uses x-redirect-uri header when redirectUri option is not provided', async () => {
@@ -27,7 +26,7 @@ describe('getAuthorizationUrl', () => {
27
26
  nextHeaders.set('x-redirect-uri', 'http://test-redirect.com');
28
27
 
29
28
  // Mock workos.userManagement.getAuthorizationUrl
30
- jest.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
29
+ vi.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
31
30
 
32
31
  await getAuthorizationUrl({});
33
32
 
@@ -39,7 +38,7 @@ describe('getAuthorizationUrl', () => {
39
38
  });
40
39
 
41
40
  it('works when called with no arguments', async () => {
42
- jest.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
41
+ vi.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
43
42
 
44
43
  await getAuthorizationUrl(); // Call with no arguments
45
44
 
@@ -47,7 +46,7 @@ describe('getAuthorizationUrl', () => {
47
46
  });
48
47
 
49
48
  it('works when prompt is provided', async () => {
50
- jest.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
49
+ vi.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
51
50
 
52
51
  await getAuthorizationUrl({ prompt: 'consent' });
53
52