1- import { describe , it , expect , beforeEach , mock , spyOn } from 'bun:test '
1+ import { beforeEach , describe , expect , it } from '@jest/globals '
22
3- import {
4- DISPUTE_THRESHOLD ,
5- DISPUTE_WINDOW_DAYS ,
6- evaluateBanConditions ,
7- getUserByStripeCustomerId ,
8- banUser ,
9- type BanConditionContext ,
10- } from '../ban-conditions'
11-
12- // Mock the database module
13- const mockSelect = mock ( ( ) => ( {
14- from : mock ( ( ) => ( {
15- where : mock ( ( ) => ( {
16- limit : mock ( ( ) => Promise . resolve ( [ ] ) ) ,
17- } ) ) ,
18- } ) ) ,
19- } ) )
20-
21- const mockUpdate = mock ( ( ) => ( {
22- set : mock ( ( ) => ( {
23- where : mock ( ( ) => Promise . resolve ( ) ) ,
24- } ) ) ,
25- } ) )
26-
27- mock . module ( '@codebuff/internal/db' , ( ) => ( {
3+ jest . mock ( '@codebuff/internal/db' , ( ) => ( {
4+ __esModule : true ,
285 default : {
29- select : mockSelect ,
30- update : mockUpdate ,
6+ select : jest . fn ( ( ) => ( {
7+ from : jest . fn ( ( ) => ( {
8+ where : jest . fn ( ( ) => ( {
9+ limit : jest . fn ( ( ) => Promise . resolve ( [ ] ) ) ,
10+ } ) ) ,
11+ } ) ) ,
12+ } ) ) ,
13+ update : jest . fn ( ( ) => ( {
14+ set : jest . fn ( ( ) => ( {
15+ where : jest . fn ( ( ) => Promise . resolve ( ) ) ,
16+ } ) ) ,
17+ } ) ) ,
3118 } ,
3219} ) )
3320
34- mock . module ( '@codebuff/internal/db/schema' , ( ) => ( {
21+ jest . mock ( '@codebuff/internal/db/schema' , ( ) => ( {
22+ __esModule : true ,
3523 user : {
3624 id : 'id' ,
3725 banned : 'banned' ,
@@ -41,31 +29,45 @@ mock.module('@codebuff/internal/db/schema', () => ({
4129 } ,
4230} ) )
4331
44- // Mock Stripe server
45- const mockDisputesList = mock ( ( ) : Promise < { data : any [ ] } > =>
46- Promise . resolve ( {
47- data : [ ] ,
48- } ) ,
49- )
50-
51- mock . module ( '@codebuff/internal/util/stripe' , ( ) => ( {
32+ jest . mock ( '@codebuff/internal/util/stripe' , ( ) => ( {
33+ __esModule : true ,
5234 stripeServer : {
5335 disputes : {
54- list : mockDisputesList ,
36+ list : jest . fn ( ( ) =>
37+ Promise . resolve ( {
38+ data : [ ] ,
39+ } ) ,
40+ ) ,
5541 } ,
5642 } ,
5743} ) )
5844
59- // Mock drizzle-orm eq function
60- mock . module ( 'drizzle-orm' , ( ) => ( {
61- eq : mock ( ( a : any , b : any ) => ( { column : a , value : b } ) ) ,
45+ jest . mock ( ' drizzle-orm' , ( ) => ( {
46+ __esModule : true ,
47+ eq : jest . fn ( ( a : any , b : any ) => ( { column : a , value : b } ) ) ,
6248} ) )
6349
50+ import db from '@codebuff/internal/db'
51+ import { stripeServer } from '@codebuff/internal/util/stripe'
52+
53+ import {
54+ DISPUTE_THRESHOLD ,
55+ DISPUTE_WINDOW_DAYS ,
56+ banUser ,
57+ evaluateBanConditions ,
58+ getUserByStripeCustomerId ,
59+ type BanConditionContext ,
60+ } from '../ban-conditions'
61+
62+ const mockSelect = db . select as unknown as jest . Mock
63+ const mockUpdate = db . update as unknown as jest . Mock
64+ const mockDisputesList = stripeServer . disputes . list as unknown as jest . Mock
65+
6466const createMockLogger = ( ) => ( {
65- debug : mock ( ( ) => { } ) ,
66- info : mock ( ( ) => { } ) ,
67- warn : mock ( ( ) => { } ) ,
68- error : mock ( ( ) => { } ) ,
67+ debug : jest . fn ( ( ) => { } ) ,
68+ info : jest . fn ( ( ) => { } ) ,
69+ warn : jest . fn ( ( ) => { } ) ,
70+ error : jest . fn ( ( ) => { } ) ,
6971} )
7072
7173describe ( 'ban-conditions' , ( ) => {
@@ -104,11 +106,14 @@ describe('ban-conditions', () => {
104106
105107 it ( 'returns shouldBan: false when disputes are below threshold' , async ( ) => {
106108 // Create disputes for the customer (below threshold)
107- const disputes = Array . from ( { length : DISPUTE_THRESHOLD - 1 } , ( _ , i ) => ( {
108- id : `dp_${ i } ` ,
109- charge : { customer : 'cus_123' } ,
110- created : Math . floor ( Date . now ( ) / 1000 ) ,
111- } ) )
109+ const disputes = Array . from (
110+ { length : DISPUTE_THRESHOLD - 1 } ,
111+ ( _ , i ) => ( {
112+ id : `dp_${ i } ` ,
113+ charge : { customer : 'cus_123' } ,
114+ created : Math . floor ( Date . now ( ) / 1000 ) ,
115+ } ) ,
116+ )
112117
113118 mockDisputesList . mockResolvedValueOnce ( { data : disputes } )
114119
@@ -151,11 +156,14 @@ describe('ban-conditions', () => {
151156
152157 it ( 'returns shouldBan: true when disputes exceed threshold' , async ( ) => {
153158 // Create disputes for the customer (above threshold)
154- const disputes = Array . from ( { length : DISPUTE_THRESHOLD + 3 } , ( _ , i ) => ( {
155- id : `dp_${ i } ` ,
156- charge : { customer : 'cus_123' } ,
157- created : Math . floor ( Date . now ( ) / 1000 ) ,
158- } ) )
159+ const disputes = Array . from (
160+ { length : DISPUTE_THRESHOLD + 3 } ,
161+ ( _ , i ) => ( {
162+ id : `dp_${ i } ` ,
163+ charge : { customer : 'cus_123' } ,
164+ created : Math . floor ( Date . now ( ) / 1000 ) ,
165+ } ) ,
166+ )
159167
160168 mockDisputesList . mockResolvedValueOnce ( { data : disputes } )
161169
@@ -176,13 +184,37 @@ describe('ban-conditions', () => {
176184 // Mix of disputes from different customers
177185 const disputes = [
178186 // Disputes for our customer
179- { id : 'dp_1' , charge : { customer : 'cus_123' } , created : Math . floor ( Date . now ( ) / 1000 ) } ,
180- { id : 'dp_2' , charge : { customer : 'cus_123' } , created : Math . floor ( Date . now ( ) / 1000 ) } ,
187+ {
188+ id : 'dp_1' ,
189+ charge : { customer : 'cus_123' } ,
190+ created : Math . floor ( Date . now ( ) / 1000 ) ,
191+ } ,
192+ {
193+ id : 'dp_2' ,
194+ charge : { customer : 'cus_123' } ,
195+ created : Math . floor ( Date . now ( ) / 1000 ) ,
196+ } ,
181197 // Disputes for other customers (should be ignored)
182- { id : 'dp_3' , charge : { customer : 'cus_other' } , created : Math . floor ( Date . now ( ) / 1000 ) } ,
183- { id : 'dp_4' , charge : { customer : 'cus_different' } , created : Math . floor ( Date . now ( ) / 1000 ) } ,
184- { id : 'dp_5' , charge : { customer : 'cus_another' } , created : Math . floor ( Date . now ( ) / 1000 ) } ,
185- { id : 'dp_6' , charge : { customer : 'cus_more' } , created : Math . floor ( Date . now ( ) / 1000 ) } ,
198+ {
199+ id : 'dp_3' ,
200+ charge : { customer : 'cus_other' } ,
201+ created : Math . floor ( Date . now ( ) / 1000 ) ,
202+ } ,
203+ {
204+ id : 'dp_4' ,
205+ charge : { customer : 'cus_different' } ,
206+ created : Math . floor ( Date . now ( ) / 1000 ) ,
207+ } ,
208+ {
209+ id : 'dp_5' ,
210+ charge : { customer : 'cus_another' } ,
211+ created : Math . floor ( Date . now ( ) / 1000 ) ,
212+ } ,
213+ {
214+ id : 'dp_6' ,
215+ charge : { customer : 'cus_more' } ,
216+ created : Math . floor ( Date . now ( ) / 1000 ) ,
217+ } ,
186218 ]
187219
188220 mockDisputesList . mockResolvedValueOnce ( { data : disputes } )
@@ -265,10 +297,15 @@ describe('ban-conditions', () => {
265297 expect ( callArgs . expand ) . toEqual ( [ 'data.charge' ] )
266298
267299 // Verify the created.gte is within the expected window
268- const expectedWindowStart = beforeCall - DISPUTE_WINDOW_DAYS * 24 * 60 * 60
300+ const expectedWindowStart =
301+ beforeCall - DISPUTE_WINDOW_DAYS * 24 * 60 * 60
269302 const windowTolerance = afterCall - beforeCall + 1 // Allow for time passing during test
270- expect ( callArgs . created . gte ) . toBeGreaterThanOrEqual ( expectedWindowStart - windowTolerance )
271- expect ( callArgs . created . gte ) . toBeLessThanOrEqual ( expectedWindowStart + windowTolerance )
303+ expect ( callArgs . created . gte ) . toBeGreaterThanOrEqual (
304+ expectedWindowStart - windowTolerance ,
305+ )
306+ expect ( callArgs . created . gte ) . toBeLessThanOrEqual (
307+ expectedWindowStart + windowTolerance ,
308+ )
272309 } )
273310
274311 // REGRESSION TEST: Without expand: ['data.charge'], dispute.charge is a string ID,
@@ -287,7 +324,7 @@ describe('ban-conditions', () => {
287324 await evaluateBanConditions ( context )
288325
289326 const callArgs = ( mockDisputesList . mock . calls as any ) [ 0 ] ?. [ 0 ]
290-
327+
291328 // This is critical: without expand, dispute.charge is just a string ID like "ch_xxx"
292329 // and we cannot access dispute.charge.customer to filter by customer.
293330 // If this test fails, the ban condition will NEVER match any disputes.
@@ -320,9 +357,9 @@ describe('ban-conditions', () => {
320357 name : 'Test User' ,
321358 }
322359
323- const limitMock = mock ( ( ) => Promise . resolve ( [ mockUser ] ) )
324- const whereMock = mock ( ( ) => ( { limit : limitMock } ) )
325- const fromMock = mock ( ( ) => ( { where : whereMock } ) )
360+ const limitMock = jest . fn ( ( ) => Promise . resolve ( [ mockUser ] ) )
361+ const whereMock = jest . fn ( ( ) => ( { limit : limitMock } ) )
362+ const fromMock = jest . fn ( ( ) => ( { where : whereMock } ) )
326363 mockSelect . mockReturnValueOnce ( { from : fromMock } )
327364
328365 const result = await getUserByStripeCustomerId ( 'cus_123' )
@@ -331,9 +368,9 @@ describe('ban-conditions', () => {
331368 } )
332369
333370 it ( 'returns null when user not found' , async ( ) => {
334- const limitMock = mock ( ( ) => Promise . resolve ( [ ] ) )
335- const whereMock = mock ( ( ) => ( { limit : limitMock } ) )
336- const fromMock = mock ( ( ) => ( { where : whereMock } ) )
371+ const limitMock = jest . fn ( ( ) => Promise . resolve ( [ ] ) )
372+ const whereMock = jest . fn ( ( ) => ( { limit : limitMock } ) )
373+ const fromMock = jest . fn ( ( ) => ( { where : whereMock } ) )
337374 mockSelect . mockReturnValueOnce ( { from : fromMock } )
338375
339376 const result = await getUserByStripeCustomerId ( 'cus_nonexistent' )
@@ -342,9 +379,9 @@ describe('ban-conditions', () => {
342379 } )
343380
344381 it ( 'queries with correct stripe_customer_id' , async ( ) => {
345- const limitMock = mock ( ( ) => Promise . resolve ( [ ] ) )
346- const whereMock = mock ( ( ) => ( { limit : limitMock } ) )
347- const fromMock = mock ( ( ) => ( { where : whereMock } ) )
382+ const limitMock = jest . fn ( ( ) => Promise . resolve ( [ ] ) )
383+ const whereMock = jest . fn ( ( ) => ( { limit : limitMock } ) )
384+ const fromMock = jest . fn ( ( ) => ( { where : whereMock } ) )
348385 mockSelect . mockReturnValueOnce ( { from : fromMock } )
349386
350387 await getUserByStripeCustomerId ( 'cus_test_123' )
@@ -358,8 +395,8 @@ describe('ban-conditions', () => {
358395
359396 describe ( 'banUser' , ( ) => {
360397 it ( 'updates user banned status to true' , async ( ) => {
361- const whereMock = mock ( ( ) => Promise . resolve ( ) )
362- const setMock = mock ( ( ) => ( { where : whereMock } ) )
398+ const whereMock = jest . fn ( ( ) => Promise . resolve ( ) )
399+ const setMock = jest . fn ( ( ) => ( { where : whereMock } ) )
363400 mockUpdate . mockReturnValueOnce ( { set : setMock } )
364401
365402 const logger = createMockLogger ( )
@@ -371,8 +408,8 @@ describe('ban-conditions', () => {
371408 } )
372409
373410 it ( 'logs the ban action with user ID and reason' , async ( ) => {
374- const whereMock = mock ( ( ) => Promise . resolve ( ) )
375- const setMock = mock ( ( ) => ( { where : whereMock } ) )
411+ const whereMock = jest . fn ( ( ) => Promise . resolve ( ) )
412+ const setMock = jest . fn ( ( ) => ( { where : whereMock } ) )
376413 mockUpdate . mockReturnValueOnce ( { set : setMock } )
377414
378415 const logger = createMockLogger ( )
0 commit comments