@better-auth/stripe 1.4.8 → 1.4.9

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,11 +1,7 @@
1
- import type { GenericEndpointContext } from "@better-auth/core";
2
1
  import { runWithEndpointContext } from "@better-auth/core/context";
3
2
  import type { Auth, User } from "better-auth";
4
- import { betterAuth } from "better-auth";
5
3
  import { memoryAdapter } from "better-auth/adapters/memory";
6
- import { createAuthClient } from "better-auth/client";
7
- import { setCookieToHeader } from "better-auth/cookies";
8
- import { bearer } from "better-auth/plugins";
4
+ import { getTestInstance } from "better-auth/test";
9
5
  import type Stripe from "stripe";
10
6
  import { beforeEach, describe, expect, expectTypeOf, it, vi } from "vitest";
11
7
  import type { StripePlugin } from ".";
@@ -50,10 +46,12 @@ describe("stripe type", () => {
50
46
  expectTypeOf<MyAuth["api"]["cancelSubscriptionCallback"]>().toBeFunction();
51
47
  expectTypeOf<MyAuth["api"]["cancelSubscription"]>().toBeFunction();
52
48
  expectTypeOf<MyAuth["api"]["restoreSubscription"]>().toBeFunction();
49
+ expectTypeOf<MyAuth["api"]["upgradeSubscription"]>().toBeFunction();
50
+ expectTypeOf<MyAuth["api"]["createBillingPortal"]>().toBeFunction();
53
51
  });
54
52
  });
55
53
 
56
- describe("stripe", async () => {
54
+ describe("stripe", () => {
57
55
  const mockStripe = {
58
56
  prices: {
59
57
  list: vi.fn().mockResolvedValue({ data: [{ id: "price_lookup_123" }] }),
@@ -95,17 +93,7 @@ describe("stripe", async () => {
95
93
  constructEventAsync: vi.fn(),
96
94
  },
97
95
  };
98
-
99
96
  const _stripe = mockStripe as unknown as Stripe;
100
- const data = {
101
- user: [],
102
- session: [],
103
- verification: [],
104
- account: [],
105
- customer: [],
106
- subscription: [],
107
- };
108
- const memory = memoryAdapter(data);
109
97
  const stripeOptions = {
110
98
  stripeClient: _stripe,
111
99
  stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
@@ -126,36 +114,20 @@ describe("stripe", async () => {
126
114
  ],
127
115
  },
128
116
  } satisfies StripeOptions;
129
- const auth = betterAuth({
130
- database: memory,
131
- baseURL: "http://localhost:3000",
132
- // database: new Database(":memory:"),
133
- emailAndPassword: {
134
- enabled: true,
135
- },
136
- plugins: [stripe(stripeOptions)],
137
- });
138
- const ctx = await auth.$context;
139
- const authClient = createAuthClient({
140
- baseURL: "http://localhost:3000",
141
- plugins: [
142
- bearer(),
143
- stripeClient({
144
- subscription: true,
145
- }),
146
- ],
147
- fetchOptions: {
148
- customFetchImpl: async (url, init) => {
149
- return auth.handler(new Request(url, init));
150
- },
151
- },
152
- });
153
117
 
154
118
  const testUser = {
155
119
  email: "test@email.com",
156
120
  password: "password",
157
121
  name: "Test User",
158
122
  };
123
+ const data = {
124
+ user: [],
125
+ session: [],
126
+ verification: [],
127
+ account: [],
128
+ customer: [],
129
+ subscription: [],
130
+ };
159
131
 
160
132
  beforeEach(() => {
161
133
  data.user = [];
@@ -168,8 +140,24 @@ describe("stripe", async () => {
168
140
  vi.clearAllMocks();
169
141
  });
170
142
 
143
+ const memory = memoryAdapter(data);
144
+
171
145
  it("should create a customer on sign up", async () => {
172
- const userRes = await authClient.signUp.email(testUser, {
146
+ const { client, auth } = await getTestInstance(
147
+ {
148
+ database: memory,
149
+ plugins: [stripe(stripeOptions)],
150
+ },
151
+ {
152
+ disableTestUser: true,
153
+ clientOptions: {
154
+ plugins: [stripeClient({ subscription: true })],
155
+ },
156
+ },
157
+ );
158
+ const ctx = await auth.$context;
159
+
160
+ const userRes = await client.signUp.email(testUser, {
173
161
  throw: true,
174
162
  });
175
163
  const res = await ctx.adapter.findOne<User>({
@@ -188,17 +176,31 @@ describe("stripe", async () => {
188
176
  });
189
177
 
190
178
  it("should create a subscription", async () => {
191
- const userRes = await authClient.signUp.email(testUser, {
179
+ const { client, auth, sessionSetter } = await getTestInstance(
180
+ {
181
+ database: memory,
182
+ plugins: [stripe(stripeOptions)],
183
+ },
184
+ {
185
+ disableTestUser: true,
186
+ clientOptions: {
187
+ plugins: [stripeClient({ subscription: true })],
188
+ },
189
+ },
190
+ );
191
+ const ctx = await auth.$context;
192
+
193
+ const userRes = await client.signUp.email(testUser, {
192
194
  throw: true,
193
195
  });
194
196
 
195
197
  const headers = new Headers();
196
- await authClient.signIn.email(testUser, {
198
+ await client.signIn.email(testUser, {
197
199
  throw: true,
198
- onSuccess: setCookieToHeader(headers),
200
+ onSuccess: sessionSetter(headers),
199
201
  });
200
202
 
201
- const res = await authClient.subscription.upgrade({
203
+ const res = await client.subscription.upgrade({
202
204
  plan: "starter",
203
205
  fetchOptions: {
204
206
  headers,
@@ -228,19 +230,33 @@ describe("stripe", async () => {
228
230
  });
229
231
 
230
232
  it("should not allow cross-user subscriptionId operations (upgrade/cancel/restore)", async () => {
233
+ const { client, auth, sessionSetter } = await getTestInstance(
234
+ {
235
+ database: memory,
236
+ plugins: [stripe(stripeOptions)],
237
+ },
238
+ {
239
+ disableTestUser: true,
240
+ clientOptions: {
241
+ plugins: [stripeClient({ subscription: true })],
242
+ },
243
+ },
244
+ );
245
+ const ctx = await auth.$context;
246
+
231
247
  const userA = {
232
248
  email: "user-a@email.com",
233
249
  password: "password",
234
250
  name: "User A",
235
251
  };
236
- const userARes = await authClient.signUp.email(userA, { throw: true });
252
+ const userARes = await client.signUp.email(userA, { throw: true });
237
253
 
238
254
  const userAHeaders = new Headers();
239
- await authClient.signIn.email(userA, {
255
+ await client.signIn.email(userA, {
240
256
  throw: true,
241
- onSuccess: setCookieToHeader(userAHeaders),
257
+ onSuccess: sessionSetter(userAHeaders),
242
258
  });
243
- await authClient.subscription.upgrade({
259
+ await client.subscription.upgrade({
244
260
  plan: "starter",
245
261
  fetchOptions: { headers: userAHeaders },
246
262
  });
@@ -256,11 +272,11 @@ describe("stripe", async () => {
256
272
  password: "password",
257
273
  name: "User B",
258
274
  };
259
- await authClient.signUp.email(userB, { throw: true });
275
+ await client.signUp.email(userB, { throw: true });
260
276
  const userBHeaders = new Headers();
261
- await authClient.signIn.email(userB, {
277
+ await client.signIn.email(userB, {
262
278
  throw: true,
263
- onSuccess: setCookieToHeader(userBHeaders),
279
+ onSuccess: sessionSetter(userBHeaders),
264
280
  });
265
281
 
266
282
  mockStripe.checkout.sessions.create.mockClear();
@@ -268,7 +284,7 @@ describe("stripe", async () => {
268
284
  mockStripe.subscriptions.list.mockClear();
269
285
  mockStripe.subscriptions.update.mockClear();
270
286
 
271
- const upgradeRes = await authClient.subscription.upgrade({
287
+ const upgradeRes = await client.subscription.upgrade({
272
288
  plan: "premium",
273
289
  subscriptionId: userASub!.id,
274
290
  fetchOptions: { headers: userBHeaders },
@@ -314,7 +330,21 @@ describe("stripe", async () => {
314
330
  });
315
331
 
316
332
  it("should list active subscriptions", async () => {
317
- const userRes = await authClient.signUp.email(
333
+ const { client, auth, sessionSetter } = await getTestInstance(
334
+ {
335
+ database: memory,
336
+ plugins: [stripe(stripeOptions)],
337
+ },
338
+ {
339
+ disableTestUser: true,
340
+ clientOptions: {
341
+ plugins: [stripeClient({ subscription: true })],
342
+ },
343
+ },
344
+ );
345
+ const ctx = await auth.$context;
346
+
347
+ const userRes = await client.signUp.email(
318
348
  {
319
349
  ...testUser,
320
350
  email: "list-test@email.com",
@@ -326,18 +356,18 @@ describe("stripe", async () => {
326
356
  const userId = userRes.user.id;
327
357
 
328
358
  const headers = new Headers();
329
- await authClient.signIn.email(
359
+ await client.signIn.email(
330
360
  {
331
361
  ...testUser,
332
362
  email: "list-test@email.com",
333
363
  },
334
364
  {
335
365
  throw: true,
336
- onSuccess: setCookieToHeader(headers),
366
+ onSuccess: sessionSetter(headers),
337
367
  },
338
368
  );
339
369
 
340
- const listRes = await authClient.subscription.list({
370
+ const listRes = await client.subscription.list({
341
371
  fetchOptions: {
342
372
  headers,
343
373
  },
@@ -345,13 +375,13 @@ describe("stripe", async () => {
345
375
 
346
376
  expect(Array.isArray(listRes.data)).toBe(true);
347
377
 
348
- await authClient.subscription.upgrade({
378
+ await client.subscription.upgrade({
349
379
  plan: "starter",
350
380
  fetchOptions: {
351
381
  headers,
352
382
  },
353
383
  });
354
- const listBeforeActive = await authClient.subscription.list({
384
+ const listBeforeActive = await client.subscription.list({
355
385
  fetchOptions: {
356
386
  headers,
357
387
  },
@@ -370,7 +400,7 @@ describe("stripe", async () => {
370
400
  },
371
401
  ],
372
402
  });
373
- const listAfterRes = await authClient.subscription.list({
403
+ const listAfterRes = await client.subscription.list({
374
404
  fetchOptions: {
375
405
  headers,
376
406
  },
@@ -379,13 +409,24 @@ describe("stripe", async () => {
379
409
  });
380
410
 
381
411
  it("should handle subscription webhook events", async () => {
382
- const { id: testReferenceId } = await ctx.adapter.create({
412
+ const { auth: testAuth } = await getTestInstance(
413
+ {
414
+ database: memory,
415
+ plugins: [stripe(stripeOptions)],
416
+ },
417
+ {
418
+ disableTestUser: true,
419
+ },
420
+ );
421
+ const testCtx = await testAuth.$context;
422
+
423
+ const { id: testReferenceId } = await testCtx.adapter.create({
383
424
  model: "user",
384
425
  data: {
385
426
  email: "test@email.com",
386
427
  },
387
428
  });
388
- const { id: testSubscriptionId } = await ctx.adapter.create({
429
+ const { id: testSubscriptionId } = await testCtx.adapter.create({
389
430
  model: "subscription",
390
431
  data: {
391
432
  referenceId: testReferenceId,
@@ -442,16 +483,17 @@ describe("stripe", async () => {
442
483
  stripeWebhookSecret: "test_secret",
443
484
  };
444
485
 
445
- const testAuth = betterAuth({
446
- baseURL: "http://localhost:3000",
447
- database: memory,
448
- emailAndPassword: {
449
- enabled: true,
486
+ const { auth: webhookTestAuth } = await getTestInstance(
487
+ {
488
+ database: memory,
489
+ plugins: [stripe(testOptions)],
450
490
  },
451
- plugins: [stripe(testOptions)],
452
- });
491
+ {
492
+ disableTestUser: true,
493
+ },
494
+ );
453
495
 
454
- const testCtx = await testAuth.$context;
496
+ const webhookTestCtx = await webhookTestAuth.$context;
455
497
 
456
498
  const mockRequest = new Request(
457
499
  "http://localhost:3000/api/auth/stripe/webhook",
@@ -463,18 +505,19 @@ describe("stripe", async () => {
463
505
  body: JSON.stringify(mockCheckoutSessionEvent),
464
506
  },
465
507
  );
466
- const response = await testAuth.handler(mockRequest);
508
+ const response = await webhookTestAuth.handler(mockRequest);
467
509
  expect(response.status).toBe(200);
468
510
 
469
- const updatedSubscription = await testCtx.adapter.findOne<Subscription>({
470
- model: "subscription",
471
- where: [
472
- {
473
- field: "id",
474
- value: testSubscriptionId,
475
- },
476
- ],
477
- });
511
+ const updatedSubscription =
512
+ await webhookTestCtx.adapter.findOne<Subscription>({
513
+ model: "subscription",
514
+ where: [
515
+ {
516
+ field: "id",
517
+ value: testSubscriptionId,
518
+ },
519
+ ],
520
+ });
478
521
 
479
522
  expect(updatedSubscription).toMatchObject({
480
523
  id: testSubscriptionId,
@@ -486,13 +529,24 @@ describe("stripe", async () => {
486
529
  });
487
530
 
488
531
  it("should handle subscription webhook events with trial", async () => {
489
- const { id: testReferenceId } = await ctx.adapter.create({
532
+ const { auth: testAuth } = await getTestInstance(
533
+ {
534
+ database: memory,
535
+ plugins: [stripe(stripeOptions)],
536
+ },
537
+ {
538
+ disableTestUser: true,
539
+ },
540
+ );
541
+ const testCtx = await testAuth.$context;
542
+
543
+ const { id: testReferenceId } = await testCtx.adapter.create({
490
544
  model: "user",
491
545
  data: {
492
546
  email: "test@email.com",
493
547
  },
494
548
  });
495
- const { id: testSubscriptionId } = await ctx.adapter.create({
549
+ const { id: testSubscriptionId } = await testCtx.adapter.create({
496
550
  model: "subscription",
497
551
  data: {
498
552
  referenceId: testReferenceId,
@@ -551,16 +605,17 @@ describe("stripe", async () => {
551
605
  stripeWebhookSecret: "test_secret",
552
606
  };
553
607
 
554
- const testAuth = betterAuth({
555
- baseURL: "http://localhost:3000",
556
- database: memory,
557
- emailAndPassword: {
558
- enabled: true,
608
+ const { auth: webhookTestAuth } = await getTestInstance(
609
+ {
610
+ database: memory,
611
+ plugins: [stripe(testOptions)],
559
612
  },
560
- plugins: [stripe(testOptions)],
561
- });
613
+ {
614
+ disableTestUser: true,
615
+ },
616
+ );
562
617
 
563
- const testCtx = await testAuth.$context;
618
+ const webhookTestCtx = await webhookTestAuth.$context;
564
619
 
565
620
  const mockRequest = new Request(
566
621
  "http://localhost:3000/api/auth/stripe/webhook",
@@ -572,18 +627,19 @@ describe("stripe", async () => {
572
627
  body: JSON.stringify(mockCheckoutSessionEvent),
573
628
  },
574
629
  );
575
- const response = await testAuth.handler(mockRequest);
630
+ const response = await webhookTestAuth.handler(mockRequest);
576
631
  expect(response.status).toBe(200);
577
632
 
578
- const updatedSubscription = await testCtx.adapter.findOne<Subscription>({
579
- model: "subscription",
580
- where: [
581
- {
582
- field: "id",
583
- value: testSubscriptionId,
584
- },
585
- ],
586
- });
633
+ const updatedSubscription =
634
+ await webhookTestCtx.adapter.findOne<Subscription>({
635
+ model: "subscription",
636
+ where: [
637
+ {
638
+ field: "id",
639
+ value: testSubscriptionId,
640
+ },
641
+ ],
642
+ });
587
643
 
588
644
  expect(updatedSubscription).toMatchObject({
589
645
  id: testSubscriptionId,
@@ -596,17 +652,28 @@ describe("stripe", async () => {
596
652
  });
597
653
  });
598
654
 
599
- const { id: userId } = await ctx.adapter.create({
600
- model: "user",
601
- data: {
602
- email: "delete-test@email.com",
603
- },
604
- });
605
-
606
655
  it("should handle subscription deletion webhook", async () => {
656
+ const { auth: testAuth } = await getTestInstance(
657
+ {
658
+ database: memory,
659
+ plugins: [stripe(stripeOptions)],
660
+ },
661
+ {
662
+ disableTestUser: true,
663
+ },
664
+ );
665
+ const testCtx = await testAuth.$context;
666
+
667
+ const { id: userId } = await testCtx.adapter.create({
668
+ model: "user",
669
+ data: {
670
+ email: "delete-test@email.com",
671
+ },
672
+ });
673
+
607
674
  const subId = "test_sub_delete";
608
675
 
609
- await ctx.adapter.create({
676
+ await testCtx.adapter.create({
610
677
  model: "subscription",
611
678
  data: {
612
679
  referenceId: userId,
@@ -617,7 +684,7 @@ describe("stripe", async () => {
617
684
  },
618
685
  });
619
686
 
620
- const subscription = await ctx.adapter.findOne<Subscription>({
687
+ const subscription = await testCtx.adapter.findOne<Subscription>({
621
688
  model: "subscription",
622
689
  where: [
623
690
  {
@@ -661,14 +728,17 @@ describe("stripe", async () => {
661
728
  stripeWebhookSecret: "test_secret",
662
729
  };
663
730
 
664
- const testAuth = betterAuth({
665
- baseURL: "http://localhost:3000",
666
- emailAndPassword: {
667
- enabled: true,
731
+ const { auth: webhookTestAuth } = await getTestInstance(
732
+ {
733
+ database: memory,
734
+ plugins: [stripe(testOptions)],
668
735
  },
669
- database: memory,
670
- plugins: [stripe(testOptions)],
671
- });
736
+ {
737
+ disableTestUser: true,
738
+ },
739
+ );
740
+
741
+ const webhookTestCtx = await webhookTestAuth.$context;
672
742
 
673
743
  const mockRequest = new Request(
674
744
  "http://localhost:3000/api/auth/stripe/webhook",
@@ -681,24 +751,43 @@ describe("stripe", async () => {
681
751
  },
682
752
  );
683
753
 
684
- const response = await testAuth.handler(mockRequest);
754
+ const response = await webhookTestAuth.handler(mockRequest);
685
755
  expect(response.status).toBe(200);
686
756
 
687
757
  if (subscription) {
688
- const updatedSubscription = await ctx.adapter.findOne<Subscription>({
689
- model: "subscription",
690
- where: [
691
- {
692
- field: "id",
693
- value: subscription.id,
694
- },
695
- ],
696
- });
758
+ const updatedSubscription =
759
+ await webhookTestCtx.adapter.findOne<Subscription>({
760
+ model: "subscription",
761
+ where: [
762
+ {
763
+ field: "id",
764
+ value: subscription.id,
765
+ },
766
+ ],
767
+ });
697
768
  expect(updatedSubscription?.status).toBe("canceled");
698
769
  }
699
770
  });
700
771
 
701
772
  it("should execute subscription event handlers", async () => {
773
+ const { auth: testAuth } = await getTestInstance(
774
+ {
775
+ database: memory,
776
+ plugins: [stripe(stripeOptions)],
777
+ },
778
+ {
779
+ disableTestUser: true,
780
+ },
781
+ );
782
+ const testCtx = await testAuth.$context;
783
+
784
+ const { id: userId } = await testCtx.adapter.create({
785
+ model: "user",
786
+ data: {
787
+ email: "event-handler-test@email.com",
788
+ },
789
+ });
790
+
702
791
  const onSubscriptionComplete = vi.fn();
703
792
  const onSubscriptionUpdate = vi.fn();
704
793
  const onSubscriptionCancel = vi.fn();
@@ -755,14 +844,19 @@ describe("stripe", async () => {
755
844
  stripeClient: mockStripeForEvents as unknown as Stripe,
756
845
  };
757
846
 
758
- const eventTestAuth = betterAuth({
759
- baseURL: "http://localhost:3000",
760
- database: memory,
761
- emailAndPassword: { enabled: true },
762
- plugins: [stripe(eventTestOptions)],
763
- });
847
+ const { auth: eventTestAuth } = await getTestInstance(
848
+ {
849
+ database: memory,
850
+ plugins: [stripe(eventTestOptions)],
851
+ },
852
+ {
853
+ disableTestUser: true,
854
+ },
855
+ );
764
856
 
765
- const { id: testSubscriptionId } = await ctx.adapter.create({
857
+ const eventTestCtx = await eventTestAuth.$context;
858
+
859
+ const { id: testSubscriptionId } = await eventTestCtx.adapter.create({
766
860
  model: "subscription",
767
861
  data: {
768
862
  referenceId: userId,
@@ -945,25 +1039,6 @@ describe("stripe", async () => {
945
1039
  it("should return updated subscription in onSubscriptionUpdate callback", async () => {
946
1040
  const onSubscriptionUpdate = vi.fn();
947
1041
 
948
- const { id: testReferenceId } = await ctx.adapter.create({
949
- model: "user",
950
- data: {
951
- email: "update-callback@email.com",
952
- },
953
- });
954
-
955
- const { id: testSubscriptionId } = await ctx.adapter.create({
956
- model: "subscription",
957
- data: {
958
- referenceId: testReferenceId,
959
- stripeCustomerId: "cus_update_test",
960
- stripeSubscriptionId: "sub_update_test",
961
- status: "active",
962
- plan: "starter",
963
- seats: 1,
964
- },
965
- });
966
-
967
1042
  // Simulate subscription update event (e.g., seat change from 1 to 5)
968
1043
  const updateEvent = {
969
1044
  type: "customer.subscription.updated",
@@ -1006,13 +1081,35 @@ describe("stripe", async () => {
1006
1081
  },
1007
1082
  } as unknown as StripeOptions;
1008
1083
 
1009
- const testAuth = betterAuth({
1010
- baseURL: "http://localhost:3000",
1011
- database: memory,
1012
- emailAndPassword: {
1013
- enabled: true,
1084
+ const { auth: testAuth } = await getTestInstance(
1085
+ {
1086
+ database: memory,
1087
+ plugins: [stripe(testOptions)],
1088
+ },
1089
+ {
1090
+ disableTestUser: true,
1091
+ },
1092
+ );
1093
+
1094
+ const ctx = await testAuth.$context;
1095
+
1096
+ const { id: testReferenceId } = await ctx.adapter.create({
1097
+ model: "user",
1098
+ data: {
1099
+ email: "update-callback@email.com",
1100
+ },
1101
+ });
1102
+
1103
+ const { id: testSubscriptionId } = await ctx.adapter.create({
1104
+ model: "subscription",
1105
+ data: {
1106
+ referenceId: testReferenceId,
1107
+ stripeCustomerId: "cus_update_test",
1108
+ stripeSubscriptionId: "sub_update_test",
1109
+ status: "active",
1110
+ plan: "starter",
1111
+ seats: 1,
1014
1112
  },
1015
- plugins: [stripe(testOptions)],
1016
1113
  });
1017
1114
 
1018
1115
  const mockRequest = new Request(
@@ -1050,7 +1147,21 @@ describe("stripe", async () => {
1050
1147
  });
1051
1148
 
1052
1149
  it("should allow seat upgrades for the same plan", async () => {
1053
- const userRes = await authClient.signUp.email(
1150
+ const { client, auth, sessionSetter } = await getTestInstance(
1151
+ {
1152
+ database: memory,
1153
+ plugins: [stripe(stripeOptions)],
1154
+ },
1155
+ {
1156
+ disableTestUser: true,
1157
+ clientOptions: {
1158
+ plugins: [stripeClient({ subscription: true })],
1159
+ },
1160
+ },
1161
+ );
1162
+ const ctx = await auth.$context;
1163
+
1164
+ const userRes = await client.signUp.email(
1054
1165
  {
1055
1166
  ...testUser,
1056
1167
  email: "seat-upgrade@email.com",
@@ -1061,18 +1172,18 @@ describe("stripe", async () => {
1061
1172
  );
1062
1173
 
1063
1174
  const headers = new Headers();
1064
- await authClient.signIn.email(
1175
+ await client.signIn.email(
1065
1176
  {
1066
1177
  ...testUser,
1067
1178
  email: "seat-upgrade@email.com",
1068
1179
  },
1069
1180
  {
1070
1181
  throw: true,
1071
- onSuccess: setCookieToHeader(headers),
1182
+ onSuccess: sessionSetter(headers),
1072
1183
  },
1073
1184
  );
1074
1185
 
1075
- await authClient.subscription.upgrade({
1186
+ await client.subscription.upgrade({
1076
1187
  plan: "starter",
1077
1188
  seats: 1,
1078
1189
  fetchOptions: {
@@ -1093,7 +1204,7 @@ describe("stripe", async () => {
1093
1204
  ],
1094
1205
  });
1095
1206
 
1096
- const upgradeRes = await authClient.subscription.upgrade({
1207
+ const upgradeRes = await client.subscription.upgrade({
1097
1208
  plan: "starter",
1098
1209
  seats: 5,
1099
1210
  fetchOptions: {
@@ -1105,7 +1216,21 @@ describe("stripe", async () => {
1105
1216
  });
1106
1217
 
1107
1218
  it("should prevent duplicate subscriptions with same plan and same seats", async () => {
1108
- const userRes = await authClient.signUp.email(
1219
+ const { client, auth, sessionSetter } = await getTestInstance(
1220
+ {
1221
+ database: memory,
1222
+ plugins: [stripe(stripeOptions)],
1223
+ },
1224
+ {
1225
+ disableTestUser: true,
1226
+ clientOptions: {
1227
+ plugins: [stripeClient({ subscription: true })],
1228
+ },
1229
+ },
1230
+ );
1231
+ const ctx = await auth.$context;
1232
+
1233
+ const userRes = await client.signUp.email(
1109
1234
  {
1110
1235
  ...testUser,
1111
1236
  email: "duplicate-prevention@email.com",
@@ -1116,18 +1241,18 @@ describe("stripe", async () => {
1116
1241
  );
1117
1242
 
1118
1243
  const headers = new Headers();
1119
- await authClient.signIn.email(
1244
+ await client.signIn.email(
1120
1245
  {
1121
1246
  ...testUser,
1122
1247
  email: "duplicate-prevention@email.com",
1123
1248
  },
1124
1249
  {
1125
1250
  throw: true,
1126
- onSuccess: setCookieToHeader(headers),
1251
+ onSuccess: sessionSetter(headers),
1127
1252
  },
1128
1253
  );
1129
1254
 
1130
- await authClient.subscription.upgrade({
1255
+ await client.subscription.upgrade({
1131
1256
  plan: "starter",
1132
1257
  seats: 3,
1133
1258
  fetchOptions: {
@@ -1149,7 +1274,7 @@ describe("stripe", async () => {
1149
1274
  ],
1150
1275
  });
1151
1276
 
1152
- const upgradeRes = await authClient.subscription.upgrade({
1277
+ const upgradeRes = await client.subscription.upgrade({
1153
1278
  plan: "starter",
1154
1279
  seats: 3,
1155
1280
  fetchOptions: {
@@ -1162,21 +1287,34 @@ describe("stripe", async () => {
1162
1287
  });
1163
1288
 
1164
1289
  it("should only call Stripe customers.create once for signup and upgrade", async () => {
1165
- await authClient.signUp.email(
1290
+ const { client, sessionSetter } = await getTestInstance(
1291
+ {
1292
+ database: memory,
1293
+ plugins: [stripe(stripeOptions)],
1294
+ },
1295
+ {
1296
+ disableTestUser: true,
1297
+ clientOptions: {
1298
+ plugins: [stripeClient({ subscription: true })],
1299
+ },
1300
+ },
1301
+ );
1302
+
1303
+ await client.signUp.email(
1166
1304
  { ...testUser, email: "single-create@email.com" },
1167
1305
  { throw: true },
1168
1306
  );
1169
1307
 
1170
1308
  const headers = new Headers();
1171
- await authClient.signIn.email(
1309
+ await client.signIn.email(
1172
1310
  { ...testUser, email: "single-create@email.com" },
1173
1311
  {
1174
1312
  throw: true,
1175
- onSuccess: setCookieToHeader(headers),
1313
+ onSuccess: sessionSetter(headers),
1176
1314
  },
1177
1315
  );
1178
1316
 
1179
- await authClient.subscription.upgrade({
1317
+ await client.subscription.upgrade({
1180
1318
  plan: "starter",
1181
1319
  fetchOptions: { headers },
1182
1320
  });
@@ -1185,7 +1323,20 @@ describe("stripe", async () => {
1185
1323
  });
1186
1324
 
1187
1325
  it("should create billing portal session", async () => {
1188
- await authClient.signUp.email(
1326
+ const { client, sessionSetter } = await getTestInstance(
1327
+ {
1328
+ database: memory,
1329
+ plugins: [stripe(stripeOptions)],
1330
+ },
1331
+ {
1332
+ disableTestUser: true,
1333
+ clientOptions: {
1334
+ plugins: [stripeClient({ subscription: true })],
1335
+ },
1336
+ },
1337
+ );
1338
+
1339
+ await client.signUp.email(
1189
1340
  {
1190
1341
  ...testUser,
1191
1342
  email: "billing-portal@email.com",
@@ -1196,17 +1347,17 @@ describe("stripe", async () => {
1196
1347
  );
1197
1348
 
1198
1349
  const headers = new Headers();
1199
- await authClient.signIn.email(
1350
+ await client.signIn.email(
1200
1351
  {
1201
1352
  ...testUser,
1202
1353
  email: "billing-portal@email.com",
1203
1354
  },
1204
1355
  {
1205
1356
  throw: true,
1206
- onSuccess: setCookieToHeader(headers),
1357
+ onSuccess: sessionSetter(headers),
1207
1358
  },
1208
1359
  );
1209
- const billingPortalRes = await authClient.subscription.billingPortal({
1360
+ const billingPortalRes = await client.subscription.billingPortal({
1210
1361
  returnUrl: "/dashboard",
1211
1362
  fetchOptions: {
1212
1363
  headers,
@@ -1233,36 +1384,37 @@ describe("stripe", async () => {
1233
1384
  },
1234
1385
  } as unknown as StripeOptions;
1235
1386
 
1236
- const testAuth = betterAuth({
1237
- baseURL: "http://localhost:3000",
1238
- database: memory,
1239
- emailAndPassword: { enabled: true },
1240
- plugins: [stripe(testOptions)],
1241
- });
1242
- const testCtx = await testAuth.$context;
1243
-
1244
- const testAuthClient = createAuthClient({
1245
- baseURL: "http://localhost:3000",
1246
- plugins: [bearer(), stripeClient({ subscription: true })],
1247
- fetchOptions: {
1248
- customFetchImpl: async (url, init) =>
1249
- testAuth.handler(new Request(url, init)),
1387
+ const {
1388
+ auth: testAuth,
1389
+ client: testClient,
1390
+ sessionSetter: testSessionSetter,
1391
+ } = await getTestInstance(
1392
+ {
1393
+ database: memory,
1394
+ plugins: [stripe(testOptions)],
1250
1395
  },
1251
- });
1396
+ {
1397
+ disableTestUser: true,
1398
+ clientOptions: {
1399
+ plugins: [stripeClient({ subscription: true })],
1400
+ },
1401
+ },
1402
+ );
1403
+ const testCtx = await testAuth.$context;
1252
1404
 
1253
1405
  // Sign up and sign in the user
1254
- const userRes = await testAuthClient.signUp.email(
1406
+ const userRes = await testClient.signUp.email(
1255
1407
  { ...testUser, email: "org-ref@email.com" },
1256
1408
  { throw: true },
1257
1409
  );
1258
1410
  const headers = new Headers();
1259
- await testAuthClient.signIn.email(
1411
+ await testClient.signIn.email(
1260
1412
  { ...testUser, email: "org-ref@email.com" },
1261
- { throw: true, onSuccess: setCookieToHeader(headers) },
1413
+ { throw: true, onSuccess: testSessionSetter(headers) },
1262
1414
  );
1263
1415
 
1264
1416
  // Create a personal subscription (referenceId = user id)
1265
- await testAuthClient.subscription.upgrade({
1417
+ await testClient.subscription.upgrade({
1266
1418
  plan: "starter",
1267
1419
  fetchOptions: { headers },
1268
1420
  });
@@ -1301,14 +1453,12 @@ describe("stripe", async () => {
1301
1453
  });
1302
1454
 
1303
1455
  // Attempt to upgrade using an org referenceId
1304
- const upgradeRes = await testAuthClient.subscription.upgrade({
1456
+ const upgradeRes = await testClient.subscription.upgrade({
1305
1457
  plan: "starter",
1306
1458
  referenceId: orgId,
1307
1459
  fetchOptions: { headers },
1308
1460
  });
1309
- console.log(upgradeRes);
1310
-
1311
- // // It should NOT go through billing portal (which would update the personal sub)
1461
+ // It should NOT go through billing portal (which would update the personal sub)
1312
1462
  expect(mockStripe.billingPortal.sessions.create).not.toHaveBeenCalled();
1313
1463
  expect(upgradeRes.data?.url).toBeDefined();
1314
1464
 
@@ -1330,23 +1480,37 @@ describe("stripe", async () => {
1330
1480
  });
1331
1481
 
1332
1482
  it("should prevent multiple free trials for the same user", async () => {
1483
+ const { client, auth, sessionSetter } = await getTestInstance(
1484
+ {
1485
+ database: memory,
1486
+ plugins: [stripe(stripeOptions)],
1487
+ },
1488
+ {
1489
+ disableTestUser: true,
1490
+ clientOptions: {
1491
+ plugins: [stripeClient({ subscription: true })],
1492
+ },
1493
+ },
1494
+ );
1495
+ const ctx = await auth.$context;
1496
+
1333
1497
  // Create a user
1334
- const userRes = await authClient.signUp.email(
1498
+ const userRes = await client.signUp.email(
1335
1499
  { ...testUser, email: "trial-prevention@email.com" },
1336
1500
  { throw: true },
1337
1501
  );
1338
1502
 
1339
1503
  const headers = new Headers();
1340
- await authClient.signIn.email(
1504
+ await client.signIn.email(
1341
1505
  { ...testUser, email: "trial-prevention@email.com" },
1342
1506
  {
1343
1507
  throw: true,
1344
- onSuccess: setCookieToHeader(headers),
1508
+ onSuccess: sessionSetter(headers),
1345
1509
  },
1346
1510
  );
1347
1511
 
1348
1512
  // First subscription with trial
1349
- const firstUpgradeRes = await authClient.subscription.upgrade({
1513
+ const firstUpgradeRes = await client.subscription.upgrade({
1350
1514
  plan: "starter",
1351
1515
  fetchOptions: { headers },
1352
1516
  });
@@ -1384,7 +1548,7 @@ describe("stripe", async () => {
1384
1548
  });
1385
1549
 
1386
1550
  // Try to subscribe again - should NOT get a trial
1387
- const secondUpgradeRes = await authClient.subscription.upgrade({
1551
+ const secondUpgradeRes = await client.subscription.upgrade({
1388
1552
  plan: "starter",
1389
1553
  fetchOptions: { headers },
1390
1554
  });
@@ -1418,18 +1582,32 @@ describe("stripe", async () => {
1418
1582
  // Reset mocks for this test
1419
1583
  vi.clearAllMocks();
1420
1584
 
1585
+ const { client, auth, sessionSetter } = await getTestInstance(
1586
+ {
1587
+ database: memory,
1588
+ plugins: [stripe(stripeOptions)],
1589
+ },
1590
+ {
1591
+ disableTestUser: true,
1592
+ clientOptions: {
1593
+ plugins: [stripeClient({ subscription: true })],
1594
+ },
1595
+ },
1596
+ );
1597
+ const ctx = await auth.$context;
1598
+
1421
1599
  // Create a user
1422
- const userRes = await authClient.signUp.email(
1600
+ const userRes = await client.signUp.email(
1423
1601
  { ...testUser, email: "upgrade-existing@email.com" },
1424
1602
  { throw: true },
1425
1603
  );
1426
1604
 
1427
1605
  const headers = new Headers();
1428
- await authClient.signIn.email(
1606
+ await client.signIn.email(
1429
1607
  { ...testUser, email: "upgrade-existing@email.com" },
1430
1608
  {
1431
1609
  throw: true,
1432
- onSuccess: setCookieToHeader(headers),
1610
+ onSuccess: sessionSetter(headers),
1433
1611
  },
1434
1612
  );
1435
1613
 
@@ -1439,7 +1617,7 @@ describe("stripe", async () => {
1439
1617
  });
1440
1618
 
1441
1619
  // First create a starter subscription
1442
- await authClient.subscription.upgrade({
1620
+ await client.subscription.upgrade({
1443
1621
  plan: "starter",
1444
1622
  fetchOptions: { headers },
1445
1623
  });
@@ -1511,7 +1689,7 @@ describe("stripe", async () => {
1511
1689
  mockStripe.billingPortal.sessions.create.mockClear();
1512
1690
 
1513
1691
  // Now upgrade to premium plan - should use billing portal to update existing subscription
1514
- const upgradeRes = await authClient.subscription.upgrade({
1692
+ const upgradeRes = await client.subscription.upgrade({
1515
1693
  plan: "premium",
1516
1694
  fetchOptions: { headers },
1517
1695
  });
@@ -1550,23 +1728,37 @@ describe("stripe", async () => {
1550
1728
  });
1551
1729
 
1552
1730
  it("should prevent multiple free trials across different plans", async () => {
1731
+ const { client, auth, sessionSetter } = await getTestInstance(
1732
+ {
1733
+ database: memory,
1734
+ plugins: [stripe(stripeOptions)],
1735
+ },
1736
+ {
1737
+ disableTestUser: true,
1738
+ clientOptions: {
1739
+ plugins: [stripeClient({ subscription: true })],
1740
+ },
1741
+ },
1742
+ );
1743
+ const ctx = await auth.$context;
1744
+
1553
1745
  // Create a user
1554
- const userRes = await authClient.signUp.email(
1746
+ const userRes = await client.signUp.email(
1555
1747
  { ...testUser, email: "cross-plan-trial@email.com" },
1556
1748
  { throw: true },
1557
1749
  );
1558
1750
 
1559
1751
  const headers = new Headers();
1560
- await authClient.signIn.email(
1752
+ await client.signIn.email(
1561
1753
  { ...testUser, email: "cross-plan-trial@email.com" },
1562
1754
  {
1563
1755
  throw: true,
1564
- onSuccess: setCookieToHeader(headers),
1756
+ onSuccess: sessionSetter(headers),
1565
1757
  },
1566
1758
  );
1567
1759
 
1568
1760
  // First subscription with trial on starter plan
1569
- const firstUpgradeRes = await authClient.subscription.upgrade({
1761
+ const firstUpgradeRes = await client.subscription.upgrade({
1570
1762
  plan: "starter",
1571
1763
  fetchOptions: { headers },
1572
1764
  });
@@ -1604,7 +1796,7 @@ describe("stripe", async () => {
1604
1796
  });
1605
1797
 
1606
1798
  // Try to subscribe to a different plan - should NOT get a trial
1607
- const secondUpgradeRes = await authClient.subscription.upgrade({
1799
+ const secondUpgradeRes = await client.subscription.upgrade({
1608
1800
  plan: "premium",
1609
1801
  fetchOptions: { headers },
1610
1802
  });
@@ -1643,6 +1835,20 @@ describe("stripe", async () => {
1643
1835
  });
1644
1836
 
1645
1837
  it("should update stripe customer email when user email changes", async () => {
1838
+ const { client, auth } = await getTestInstance(
1839
+ {
1840
+ database: memory,
1841
+ plugins: [stripe(stripeOptions)],
1842
+ },
1843
+ {
1844
+ disableTestUser: true,
1845
+ clientOptions: {
1846
+ plugins: [stripeClient({ subscription: true })],
1847
+ },
1848
+ },
1849
+ );
1850
+ const ctx = await auth.$context;
1851
+
1646
1852
  // Setup mock for customer retrieve and update
1647
1853
  mockStripe.customers.retrieve = vi.fn().mockResolvedValue({
1648
1854
  id: "cus_mock123",
@@ -1655,7 +1861,7 @@ describe("stripe", async () => {
1655
1861
  });
1656
1862
 
1657
1863
  // Sign up a user
1658
- const userRes = await authClient.signUp.email(testUser, {
1864
+ const userRes = await client.signUp.email(testUser, {
1659
1865
  throw: true,
1660
1866
  });
1661
1867
 
@@ -1685,11 +1891,14 @@ describe("stripe", async () => {
1685
1891
  });
1686
1892
 
1687
1893
  // Update the user's email using internal adapter (which triggers hooks)
1688
- const endpointCtx = { context: ctx } as GenericEndpointContext;
1689
- await runWithEndpointContext(endpointCtx, () =>
1690
- ctx.internalAdapter.updateUserByEmail(testUser.email, {
1691
- email: "newemail@example.com",
1692
- }),
1894
+ await runWithEndpointContext(
1895
+ {
1896
+ context: ctx,
1897
+ },
1898
+ () =>
1899
+ ctx.internalAdapter.updateUserByEmail(testUser.email, {
1900
+ email: "newemail@example.com",
1901
+ }),
1693
1902
  );
1694
1903
 
1695
1904
  // Verify that Stripe customer.retrieve was called
@@ -1713,26 +1922,21 @@ describe("stripe", async () => {
1713
1922
  getCustomerCreateParams: getCustomerCreateParamsMock,
1714
1923
  } satisfies StripeOptions;
1715
1924
 
1716
- const testAuth = betterAuth({
1717
- database: memory,
1718
- baseURL: "http://localhost:3000",
1719
- emailAndPassword: {
1720
- enabled: true,
1925
+ const { client: testClient } = await getTestInstance(
1926
+ {
1927
+ database: memory,
1928
+ plugins: [stripe(testOptions)],
1721
1929
  },
1722
- plugins: [stripe(testOptions)],
1723
- });
1724
-
1725
- const testAuthClient = createAuthClient({
1726
- baseURL: "http://localhost:3000",
1727
- plugins: [bearer(), stripeClient({ subscription: true })],
1728
- fetchOptions: {
1729
- customFetchImpl: async (url, init) =>
1730
- testAuth.handler(new Request(url, init)),
1930
+ {
1931
+ disableTestUser: true,
1932
+ clientOptions: {
1933
+ plugins: [stripeClient({ subscription: true })],
1934
+ },
1731
1935
  },
1732
- });
1936
+ );
1733
1937
 
1734
1938
  // Sign up a user
1735
- const userRes = await testAuthClient.signUp.email(
1939
+ const userRes = await testClient.signUp.email(
1736
1940
  {
1737
1941
  email: "custom-params@email.com",
1738
1942
  password: "password",
@@ -1785,23 +1989,18 @@ describe("stripe", async () => {
1785
1989
  getCustomerCreateParams: getCustomerCreateParamsMock,
1786
1990
  } satisfies StripeOptions;
1787
1991
 
1788
- const testAuth = betterAuth({
1789
- database: memory,
1790
- baseURL: "http://localhost:3000",
1791
- emailAndPassword: {
1792
- enabled: true,
1992
+ const { client: testAuthClient } = await getTestInstance(
1993
+ {
1994
+ database: memory,
1995
+ plugins: [stripe(testOptions)],
1793
1996
  },
1794
- plugins: [stripe(testOptions)],
1795
- });
1796
-
1797
- const testAuthClient = createAuthClient({
1798
- baseURL: "http://localhost:3000",
1799
- plugins: [bearer(), stripeClient({ subscription: true })],
1800
- fetchOptions: {
1801
- customFetchImpl: async (url, init) =>
1802
- testAuth.handler(new Request(url, init)),
1997
+ {
1998
+ disableTestUser: true,
1999
+ clientOptions: {
2000
+ plugins: [stripeClient({ subscription: true })],
2001
+ },
1803
2002
  },
1804
- });
2003
+ );
1805
2004
 
1806
2005
  // Sign up a user
1807
2006
  await testAuthClient.signUp.email(
@@ -1849,23 +2048,18 @@ describe("stripe", async () => {
1849
2048
  getCustomerCreateParams: getCustomerCreateParamsMock,
1850
2049
  } satisfies StripeOptions;
1851
2050
 
1852
- const testAuth = betterAuth({
1853
- database: memory,
1854
- baseURL: "http://localhost:3000",
1855
- emailAndPassword: {
1856
- enabled: true,
2051
+ const { client: testAuthClient } = await getTestInstance(
2052
+ {
2053
+ database: memory,
2054
+ plugins: [stripe(testOptions)],
1857
2055
  },
1858
- plugins: [stripe(testOptions)],
1859
- });
1860
-
1861
- const testAuthClient = createAuthClient({
1862
- baseURL: "http://localhost:3000",
1863
- plugins: [bearer(), stripeClient({ subscription: true })],
1864
- fetchOptions: {
1865
- customFetchImpl: async (url, init) =>
1866
- testAuth.handler(new Request(url, init)),
2056
+ {
2057
+ disableTestUser: true,
2058
+ clientOptions: {
2059
+ plugins: [stripeClient({ subscription: true })],
2060
+ },
1867
2061
  },
1868
- });
2062
+ );
1869
2063
 
1870
2064
  // Sign up a user
1871
2065
  const userRes = await testAuthClient.signUp.email(
@@ -1903,23 +2097,18 @@ describe("stripe", async () => {
1903
2097
  // No getCustomerCreateParams provided
1904
2098
  } satisfies StripeOptions;
1905
2099
 
1906
- const testAuth = betterAuth({
1907
- database: memory,
1908
- baseURL: "http://localhost:3000",
1909
- emailAndPassword: {
1910
- enabled: true,
2100
+ const { client: testAuthClient } = await getTestInstance(
2101
+ {
2102
+ database: memory,
2103
+ plugins: [stripe(testOptions)],
1911
2104
  },
1912
- plugins: [stripe(testOptions)],
1913
- });
1914
-
1915
- const testAuthClient = createAuthClient({
1916
- baseURL: "http://localhost:3000",
1917
- plugins: [bearer(), stripeClient({ subscription: true })],
1918
- fetchOptions: {
1919
- customFetchImpl: async (url, init) =>
1920
- testAuth.handler(new Request(url, init)),
2105
+ {
2106
+ disableTestUser: true,
2107
+ clientOptions: {
2108
+ plugins: [stripeClient({ subscription: true })],
2109
+ },
1921
2110
  },
1922
- });
2111
+ );
1923
2112
 
1924
2113
  // Sign up a user
1925
2114
  const userRes = await testAuthClient.signUp.email(
@@ -1960,12 +2149,15 @@ describe("stripe", async () => {
1960
2149
  stripeWebhookSecret: "test_secret",
1961
2150
  };
1962
2151
 
1963
- const testAuth = betterAuth({
1964
- baseURL: "http://localhost:3000",
1965
- database: memory,
1966
- emailAndPassword: { enabled: true },
1967
- plugins: [stripe(testOptions)],
1968
- });
2152
+ const { auth: testAuth } = await getTestInstance(
2153
+ {
2154
+ database: memory,
2155
+ plugins: [stripe(testOptions)],
2156
+ },
2157
+ {
2158
+ disableTestUser: true,
2159
+ },
2160
+ );
1969
2161
 
1970
2162
  const mockRequest = new Request(
1971
2163
  "http://localhost:3000/api/auth/stripe/webhook",
@@ -1985,12 +2177,15 @@ describe("stripe", async () => {
1985
2177
  });
1986
2178
 
1987
2179
  it("should reject webhook request without stripe-signature header", async () => {
1988
- const testAuth = betterAuth({
1989
- baseURL: "http://localhost:3000",
1990
- database: memory,
1991
- emailAndPassword: { enabled: true },
1992
- plugins: [stripe(stripeOptions)],
1993
- });
2180
+ const { auth: testAuth } = await getTestInstance(
2181
+ {
2182
+ database: memory,
2183
+ plugins: [stripe(stripeOptions)],
2184
+ },
2185
+ {
2186
+ disableTestUser: true,
2187
+ },
2188
+ );
1994
2189
 
1995
2190
  const mockRequest = new Request(
1996
2191
  "http://localhost:3000/api/auth/stripe/webhook",
@@ -2023,12 +2218,15 @@ describe("stripe", async () => {
2023
2218
  stripeWebhookSecret: "test_secret",
2024
2219
  };
2025
2220
 
2026
- const testAuth = betterAuth({
2027
- baseURL: "http://localhost:3000",
2028
- database: memory,
2029
- emailAndPassword: { enabled: true },
2030
- plugins: [stripe(testOptions)],
2031
- });
2221
+ const { auth: testAuth } = await getTestInstance(
2222
+ {
2223
+ database: memory,
2224
+ plugins: [stripe(testOptions)],
2225
+ },
2226
+ {
2227
+ disableTestUser: true,
2228
+ },
2229
+ );
2032
2230
 
2033
2231
  const mockRequest = new Request(
2034
2232
  "http://localhost:3000/api/auth/stripe/webhook",
@@ -2086,14 +2284,18 @@ describe("stripe", async () => {
2086
2284
  },
2087
2285
  };
2088
2286
 
2089
- const testAuth = betterAuth({
2090
- baseURL: "http://localhost:3000",
2091
- database: memory,
2092
- emailAndPassword: { enabled: true },
2093
- plugins: [stripe(testOptions as StripeOptions)],
2094
- });
2287
+ const { auth: testAuth } = await getTestInstance(
2288
+ {
2289
+ database: memory,
2290
+ plugins: [stripe(testOptions as StripeOptions)],
2291
+ },
2292
+ {
2293
+ disableTestUser: true,
2294
+ },
2295
+ );
2296
+ const testCtx = await testAuth.$context;
2095
2297
 
2096
- await ctx.adapter.create({
2298
+ await testCtx.adapter.create({
2097
2299
  model: "subscription",
2098
2300
  data: {
2099
2301
  referenceId: "user_123",
@@ -2165,17 +2367,28 @@ describe("stripe", async () => {
2165
2367
  stripeWebhookSecret: "test_secret_async",
2166
2368
  };
2167
2369
 
2168
- const testAuth = betterAuth({
2169
- baseURL: "http://localhost:3000",
2170
- database: memory,
2171
- emailAndPassword: { enabled: true },
2172
- plugins: [stripe(testOptions)],
2370
+ const { auth: testAuth } = await getTestInstance(
2371
+ {
2372
+ database: memory,
2373
+ plugins: [stripe(testOptions)],
2374
+ },
2375
+ {
2376
+ disableTestUser: true,
2377
+ },
2378
+ );
2379
+ const testCtx = await testAuth.$context;
2380
+
2381
+ const { id: testUserId } = await testCtx.adapter.create({
2382
+ model: "user",
2383
+ data: {
2384
+ email: "async-test@email.com",
2385
+ },
2173
2386
  });
2174
2387
 
2175
- await ctx.adapter.create({
2388
+ await testCtx.adapter.create({
2176
2389
  model: "subscription",
2177
2390
  data: {
2178
- referenceId: userId,
2391
+ referenceId: testUserId,
2179
2392
  stripeCustomerId: "cus_test_async",
2180
2393
  stripeSubscriptionId: "sub_test_async",
2181
2394
  status: "incomplete",
@@ -2231,12 +2444,15 @@ describe("stripe", async () => {
2231
2444
  stripeWebhookSecret: "test_secret_params",
2232
2445
  };
2233
2446
 
2234
- const testAuth = betterAuth({
2235
- baseURL: "http://localhost:3000",
2236
- database: memory,
2237
- emailAndPassword: { enabled: true },
2238
- plugins: [stripe(testOptions)],
2239
- });
2447
+ const { auth: testAuth } = await getTestInstance(
2448
+ {
2449
+ database: memory,
2450
+ plugins: [stripe(testOptions)],
2451
+ },
2452
+ {
2453
+ disableTestUser: true,
2454
+ },
2455
+ );
2240
2456
 
2241
2457
  const mockRequest = new Request(
2242
2458
  "http://localhost:3000/api/auth/stripe/webhook",
@@ -2307,17 +2523,28 @@ describe("stripe", async () => {
2307
2523
  stripeWebhookSecret: "test_secret_v18",
2308
2524
  };
2309
2525
 
2310
- const testAuth = betterAuth({
2311
- baseURL: "http://localhost:3000",
2312
- database: memory,
2313
- emailAndPassword: { enabled: true },
2314
- plugins: [stripe(testOptions)],
2526
+ const { auth: testAuth } = await getTestInstance(
2527
+ {
2528
+ database: memory,
2529
+ plugins: [stripe(testOptions)],
2530
+ },
2531
+ {
2532
+ disableTestUser: true,
2533
+ },
2534
+ );
2535
+ const testCtx = await testAuth.$context;
2536
+
2537
+ const { id: testUserId } = await testCtx.adapter.create({
2538
+ model: "user",
2539
+ data: {
2540
+ email: "v18-test@email.com",
2541
+ },
2315
2542
  });
2316
2543
 
2317
- await ctx.adapter.create({
2544
+ await testCtx.adapter.create({
2318
2545
  model: "subscription",
2319
2546
  data: {
2320
- referenceId: userId,
2547
+ referenceId: testUserId,
2321
2548
  stripeCustomerId: "cus_test_v18",
2322
2549
  stripeSubscriptionId: "sub_test_v18",
2323
2550
  status: "incomplete",
@@ -2376,30 +2603,31 @@ describe("stripe", async () => {
2376
2603
  },
2377
2604
  ];
2378
2605
 
2379
- const testAuth = betterAuth({
2380
- baseURL: "http://localhost:3000",
2381
- database: memory,
2382
- emailAndPassword: { enabled: true },
2383
- plugins: [
2384
- stripe({
2385
- ...stripeOptions,
2386
- subscription: {
2387
- enabled: true,
2388
- plans: flexiblePlans,
2389
- },
2390
- }),
2391
- ],
2392
- });
2393
-
2394
- const testClient = createAuthClient({
2395
- baseURL: "http://localhost:3000",
2396
- plugins: [bearer(), stripeClient({ subscription: true })],
2397
- fetchOptions: {
2398
- customFetchImpl: async (url, init) => {
2399
- return testAuth.handler(new Request(url, init));
2606
+ const {
2607
+ client: testClient,
2608
+ auth: testAuth,
2609
+ sessionSetter: testSessionSetter,
2610
+ } = await getTestInstance(
2611
+ {
2612
+ database: memory,
2613
+ plugins: [
2614
+ stripe({
2615
+ ...stripeOptions,
2616
+ subscription: {
2617
+ enabled: true,
2618
+ plans: flexiblePlans,
2619
+ },
2620
+ }),
2621
+ ],
2622
+ },
2623
+ {
2624
+ disableTestUser: true,
2625
+ clientOptions: {
2626
+ plugins: [stripeClient({ subscription: true })],
2400
2627
  },
2401
2628
  },
2402
- });
2629
+ );
2630
+ const testCtx = await testAuth.$context;
2403
2631
 
2404
2632
  // Create user and sign in
2405
2633
  const headers = new Headers();
@@ -2407,18 +2635,18 @@ describe("stripe", async () => {
2407
2635
  { email: "limits@test.com", password: "password", name: "Test" },
2408
2636
  { throw: true },
2409
2637
  );
2410
- const userId = userRes.user.id;
2638
+ const limitUserId = userRes.user.id;
2411
2639
 
2412
2640
  await testClient.signIn.email(
2413
2641
  { email: "limits@test.com", password: "password" },
2414
- { throw: true, onSuccess: setCookieToHeader(headers) },
2642
+ { throw: true, onSuccess: testSessionSetter(headers) },
2415
2643
  );
2416
2644
 
2417
2645
  // Create subscription
2418
- await ctx.adapter.create({
2646
+ await testCtx.adapter.create({
2419
2647
  model: "subscription",
2420
2648
  data: {
2421
- referenceId: userId,
2649
+ referenceId: limitUserId,
2422
2650
  stripeCustomerId: "cus_limits_test",
2423
2651
  stripeSubscriptionId: "sub_limits_test",
2424
2652
  status: "active",
@@ -2477,21 +2705,19 @@ describe("stripe", async () => {
2477
2705
  createCustomerOnSignUp: true,
2478
2706
  } satisfies StripeOptions;
2479
2707
 
2480
- const testAuth = betterAuth({
2481
- database: memory,
2482
- baseURL: "http://localhost:3000",
2483
- emailAndPassword: { enabled: true },
2484
- plugins: [stripe(testOptionsWithHook)],
2485
- });
2486
-
2487
- const testAuthClient = createAuthClient({
2488
- baseURL: "http://localhost:3000",
2489
- plugins: [bearer(), stripeClient({ subscription: true })],
2490
- fetchOptions: {
2491
- customFetchImpl: async (url, init) =>
2492
- testAuth.handler(new Request(url, init)),
2708
+ const { client: testAuthClient, auth: testAuth } = await getTestInstance(
2709
+ {
2710
+ database: memory,
2711
+ plugins: [stripe(testOptionsWithHook)],
2493
2712
  },
2494
- });
2713
+ {
2714
+ disableTestUser: true,
2715
+ clientOptions: {
2716
+ plugins: [stripeClient({ subscription: true })],
2717
+ },
2718
+ },
2719
+ );
2720
+ const testCtx = await testAuth.$context;
2495
2721
 
2496
2722
  vi.clearAllMocks();
2497
2723
 
@@ -2515,7 +2741,7 @@ describe("stripe", async () => {
2515
2741
  expect(mockStripe.customers.create).not.toHaveBeenCalled();
2516
2742
 
2517
2743
  // Verify user has the EXISTING Stripe customer ID (not new duplicate)
2518
- const user = await ctx.adapter.findOne<
2744
+ const user = await testCtx.adapter.findOne<
2519
2745
  User & { stripeCustomerId?: string }
2520
2746
  >({
2521
2747
  model: "user",
@@ -2541,21 +2767,19 @@ describe("stripe", async () => {
2541
2767
  createCustomerOnSignUp: true,
2542
2768
  } satisfies StripeOptions;
2543
2769
 
2544
- const testAuth = betterAuth({
2545
- database: memory,
2546
- baseURL: "http://localhost:3000",
2547
- emailAndPassword: { enabled: true },
2548
- plugins: [stripe(testOptionsWithHook)],
2549
- });
2550
-
2551
- const testAuthClient = createAuthClient({
2552
- baseURL: "http://localhost:3000",
2553
- plugins: [bearer(), stripeClient({ subscription: true })],
2554
- fetchOptions: {
2555
- customFetchImpl: async (url, init) =>
2556
- testAuth.handler(new Request(url, init)),
2770
+ const { client: testAuthClient, auth: testAuth } = await getTestInstance(
2771
+ {
2772
+ database: memory,
2773
+ plugins: [stripe(testOptionsWithHook)],
2557
2774
  },
2558
- });
2775
+ {
2776
+ disableTestUser: true,
2777
+ clientOptions: {
2778
+ plugins: [stripeClient({ subscription: true })],
2779
+ },
2780
+ },
2781
+ );
2782
+ const testCtx = await testAuth.$context;
2559
2783
 
2560
2784
  vi.clearAllMocks();
2561
2785
 
@@ -2586,7 +2810,7 @@ describe("stripe", async () => {
2586
2810
  });
2587
2811
 
2588
2812
  // Verify user has the new Stripe customer ID
2589
- const user = await ctx.adapter.findOne<
2813
+ const user = await testCtx.adapter.findOne<
2590
2814
  User & { stripeCustomerId?: string }
2591
2815
  >({
2592
2816
  model: "user",