@@ -404,147 +404,6 @@ describe('Balance Calculator - calculateUsageAndBalance', () => {
404404 } )
405405} )
406406
407- describe ( 'shouldBlockFreeUserOverdraw' , ( ) => {
408- afterEach ( ( ) => {
409- clearMockedModules ( )
410- } )
411-
412- async function importModule ( ) {
413- await mockModule ( '@codebuff/internal/db' , ( ) => ( {
414- default : { } ,
415- } ) )
416- await mockModule ( '@codebuff/common/analytics' , ( ) => ( {
417- trackEvent : ( ) => { } ,
418- } ) )
419- return import ( '@codebuff/billing/balance-calculator' )
420- }
421-
422- it ( 'should block when exhausted free-tier user tries to consume' , async ( ) => {
423- const { shouldBlockFreeUserOverdraw } = await importModule ( )
424- expect (
425- shouldBlockFreeUserOverdraw ( [ { balance : 0 , type : 'free' } ] , 100 ) ,
426- ) . toBe ( true )
427- } )
428-
429- it ( 'should block when free-tier user balance is less than charge' , async ( ) => {
430- const { shouldBlockFreeUserOverdraw } = await importModule ( )
431- expect (
432- shouldBlockFreeUserOverdraw ( [ { balance : 50 , type : 'free' } ] , 100 ) ,
433- ) . toBe ( true )
434- } )
435-
436- it ( 'should not block when free-tier user has sufficient balance' , async ( ) => {
437- const { shouldBlockFreeUserOverdraw } = await importModule ( )
438- expect (
439- shouldBlockFreeUserOverdraw ( [ { balance : 500 , type : 'free' } ] , 100 ) ,
440- ) . toBe ( false )
441- } )
442-
443- it ( 'should not block when user has a subscription grant even with zero balance' , async ( ) => {
444- const { shouldBlockFreeUserOverdraw } = await importModule ( )
445- expect (
446- shouldBlockFreeUserOverdraw (
447- [
448- { balance : 0 , type : 'free' } ,
449- { balance : 0 , type : 'subscription' } ,
450- ] ,
451- 100 ,
452- ) ,
453- ) . toBe ( false )
454- } )
455-
456- it ( 'should not block when user has a purchase grant' , async ( ) => {
457- const { shouldBlockFreeUserOverdraw } = await importModule ( )
458- expect (
459- shouldBlockFreeUserOverdraw (
460- [
461- { balance : 0 , type : 'free' } ,
462- { balance : 10 , type : 'purchase' } ,
463- ] ,
464- 100 ,
465- ) ,
466- ) . toBe ( false )
467- } )
468-
469- it ( 'should not block when credits to charge is 0 (free-mode agent)' , async ( ) => {
470- const { shouldBlockFreeUserOverdraw } = await importModule ( )
471- expect (
472- shouldBlockFreeUserOverdraw ( [ { balance : 0 , type : 'free' } ] , 0 ) ,
473- ) . toBe ( false )
474- } )
475-
476- it ( 'should block referral-only user with insufficient credits' , async ( ) => {
477- const { shouldBlockFreeUserOverdraw } = await importModule ( )
478- expect (
479- shouldBlockFreeUserOverdraw ( [ { balance : 50 , type : 'referral' } ] , 100 ) ,
480- ) . toBe ( true )
481- } )
482-
483- it ( 'should block user in debt with no paid grants' , async ( ) => {
484- const { shouldBlockFreeUserOverdraw } = await importModule ( )
485- expect (
486- shouldBlockFreeUserOverdraw ( [ { balance : - 100 , type : 'free' } ] , 50 ) ,
487- ) . toBe ( true )
488- } )
489-
490- it ( 'should aggregate balance across multiple unpaid grants' , async ( ) => {
491- const { shouldBlockFreeUserOverdraw } = await importModule ( )
492- // Total balance: 110, charge: 100 → not blocked
493- expect (
494- shouldBlockFreeUserOverdraw (
495- [
496- { balance : 30 , type : 'free' } ,
497- { balance : 80 , type : 'referral' } ,
498- ] ,
499- 100 ,
500- ) ,
501- ) . toBe ( false )
502- } )
503- } )
504-
505- describe ( 'InsufficientCreditsError' , ( ) => {
506- afterEach ( ( ) => {
507- clearMockedModules ( )
508- } )
509-
510- async function importModule ( ) {
511- await mockModule ( '@codebuff/internal/db' , ( ) => ( {
512- default : { } ,
513- } ) )
514- await mockModule ( '@codebuff/common/analytics' , ( ) => ( {
515- trackEvent : ( ) => { } ,
516- } ) )
517- return import ( '@codebuff/billing/balance-calculator' )
518- }
519-
520- it ( 'should be an instance of Error with the correct name and fields' , async ( ) => {
521- const { InsufficientCreditsError } = await importModule ( )
522- const err = new InsufficientCreditsError ( - 50 , 200 )
523- expect ( err ) . toBeInstanceOf ( Error )
524- expect ( err ) . toBeInstanceOf ( InsufficientCreditsError )
525- expect ( err . name ) . toBe ( 'InsufficientCreditsError' )
526- expect ( err . netBalance ) . toBe ( - 50 )
527- expect ( err . chargeAmount ) . toBe ( 200 )
528- expect ( err . message ) . toBe (
529- 'Insufficient credits for free-tier user: balance=-50, charge=200' ,
530- )
531- } )
532-
533- it ( 'should be exported from the billing barrel (@codebuff/billing)' , async ( ) => {
534- await mockModule ( '@codebuff/internal/db' , ( ) => ( {
535- default : { } ,
536- } ) )
537- await mockModule ( '@codebuff/common/analytics' , ( ) => ( {
538- trackEvent : ( ) => { } ,
539- } ) )
540- const billing = await import ( '@codebuff/billing' )
541- expect ( typeof billing . InsufficientCreditsError ) . toBe ( 'function' )
542- const err = new billing . InsufficientCreditsError ( 0 , 100 )
543- expect ( err ) . toBeInstanceOf ( Error )
544- expect ( err . name ) . toBe ( 'InsufficientCreditsError' )
545- } )
546- } )
547-
548407describe ( 'consumeFromOrderedGrants - credit consumption bugs' , ( ) => {
549408 // Regression tests for two compounding bugs:
550409 // 1. Pass 1 ("repay debt") was directionally wrong: consumption reduced debt instead of
0 commit comments