@@ -11,7 +11,9 @@ const mockStripe = {
1111 checkout : { sessions : { create : jest . fn ( ) } } ,
1212 billingPortal : { sessions : { create : jest . fn ( ) } } ,
1313 subscriptions : { retrieve : jest . fn ( ) , update : jest . fn ( ) } ,
14- invoices : { createPreview : jest . fn ( ) } ,
14+ prices : { retrieve : jest . fn ( ) } ,
15+ invoiceItems : { create : jest . fn ( ) } ,
16+ invoices : { create : jest . fn ( ) , pay : jest . fn ( ) } ,
1517 webhooks : { constructEvent : jest . fn ( ) } ,
1618} ;
1719jest . mock ( 'stripe' , ( ) => {
@@ -360,50 +362,21 @@ describe('BillingService', () => {
360362
361363 it ( 'returns preview for valid upgrade' , async ( ) => {
362364 mockRepository . findOne . mockResolvedValue ( mockSubscription ) ;
363- mockStripe . subscriptions . retrieve . mockResolvedValue ( {
364- items : { data : [ { id : 'si_item1' } ] } ,
365- } ) ;
366- mockStripe . invoices . createPreview . mockResolvedValue ( {
367- amount_due : 12900 ,
368- currency : 'usd' ,
369- lines : {
370- data : [
371- {
372- amount : - 1935 ,
373- parent : {
374- subscription_item_details : { proration : true } ,
375- } ,
376- } ,
377- {
378- amount : 5270 ,
379- parent : {
380- subscription_item_details : { proration : true } ,
381- } ,
382- } ,
383- {
384- amount : 7900 ,
385- parent : {
386- subscription_item_details : { proration : false } ,
387- } ,
388- } ,
389- ] ,
390- } ,
391- } ) ;
365+ mockStripe . prices . retrieve
366+ . mockResolvedValueOnce ( { unit_amount : 2900 , currency : 'usd' } )
367+ . mockResolvedValueOnce ( { unit_amount : 7900 , currency : 'usd' } ) ;
392368
393369 const result = await service . previewUpgrade ( userId , 'team' ) ;
394370 expect ( result ) . toEqual ( {
395- immediateAmountCents : 3335 ,
371+ immediateAmountCents : 5000 ,
396372 currency : 'usd' ,
397373 targetPlan : 'team' ,
398374 currentPeriodEnd : mockSubscription . currentPeriodEnd ! . toISOString ( ) ,
399375 } ) ;
400- expect ( mockStripe . invoices . createPreview ) . toHaveBeenCalledWith ( {
401- subscription : 'sub_test123' ,
402- subscription_details : {
403- items : [ { id : 'si_item1' , price : 'price_team_456' } ] ,
404- proration_behavior : 'create_prorations' ,
405- } ,
406- } ) ;
376+ expect ( mockStripe . prices . retrieve ) . toHaveBeenCalledWith (
377+ 'price_starter_123' ,
378+ ) ;
379+ expect ( mockStripe . prices . retrieve ) . toHaveBeenCalledWith ( 'price_team_456' ) ;
407380 } ) ;
408381 } ) ;
409382
@@ -422,12 +395,18 @@ describe('BillingService', () => {
422395 ) . rejects . toThrow ( BadRequestException ) ;
423396 } ) ;
424397
425- it ( 'upgrades subscription with proration ' , async ( ) => {
398+ it ( 'upgrades subscription with flat difference ' , async ( ) => {
426399 mockRepository . findOne . mockResolvedValue ( { ...mockSubscription } ) ;
400+ mockStripe . prices . retrieve
401+ . mockResolvedValueOnce ( { unit_amount : 2900 , currency : 'usd' } )
402+ . mockResolvedValueOnce ( { unit_amount : 7900 , currency : 'usd' } ) ;
427403 mockStripe . subscriptions . retrieve . mockResolvedValue ( {
428404 items : { data : [ { id : 'si_item1' } ] } ,
429405 } ) ;
430406 mockStripe . subscriptions . update . mockResolvedValue ( { } ) ;
407+ mockStripe . invoiceItems . create . mockResolvedValue ( { } ) ;
408+ mockStripe . invoices . create . mockResolvedValue ( { id : 'inv_123' } ) ;
409+ mockStripe . invoices . pay . mockResolvedValue ( { } ) ;
431410 mockRepository . save . mockResolvedValue ( {
432411 ...mockSubscription ,
433412 plan : 'team' ,
@@ -439,9 +418,20 @@ describe('BillingService', () => {
439418 'sub_test123' ,
440419 {
441420 items : [ { id : 'si_item1' , price : 'price_team_456' } ] ,
442- proration_behavior : 'create_prorations ' ,
421+ proration_behavior : 'none ' ,
443422 } ,
444423 ) ;
424+ expect ( mockStripe . invoiceItems . create ) . toHaveBeenCalledWith ( {
425+ customer : 'cus_test123' ,
426+ amount : 5000 ,
427+ currency : 'usd' ,
428+ description : 'Plan upgrade: starter → team' ,
429+ } ) ;
430+ expect ( mockStripe . invoices . create ) . toHaveBeenCalledWith ( {
431+ customer : 'cus_test123' ,
432+ auto_advance : true ,
433+ } ) ;
434+ expect ( mockStripe . invoices . pay ) . toHaveBeenCalledWith ( 'inv_123' ) ;
445435 expect ( mockRepository . save ) . toHaveBeenCalledWith (
446436 expect . objectContaining ( { plan : 'team' } ) ,
447437 ) ;
0 commit comments