@@ -31,7 +31,7 @@ describe('Checkout', () => {
3131 } ) ;
3232
3333 // Mock billing to prevent actual API calls and stay in loading state
34- fixtures . clerk . billing . startCheckout . mockImplementation ( ( ) => new Promise ( ( ) => { } ) ) ;
34+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( { } as any ) ;
3535
3636 const { baseElement } = render (
3737 < Drawer . Root
@@ -67,7 +67,7 @@ describe('Checkout', () => {
6767 } ) ;
6868
6969 // Mock billing to prevent actual API calls
70- fixtures . clerk . billing . startCheckout . mockImplementation ( ( ) => new Promise ( ( ) => { } ) ) ;
70+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( { } as any ) ;
7171
7272 const { baseElement, getByRole } = render (
7373 < Drawer . Root
@@ -135,7 +135,7 @@ describe('Checkout', () => {
135135 } ) ;
136136
137137 // Mock billing to stay in loading state
138- fixtures . clerk . billing . startCheckout . mockImplementation ( ( ) => new Promise ( ( ) => { } ) ) ;
138+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( { } as any ) ;
139139
140140 const { baseElement } = render (
141141 < Drawer . Root
@@ -167,7 +167,7 @@ describe('Checkout', () => {
167167 f . withBilling ( ) ;
168168 } ) ;
169169
170- fixtures . clerk . billing . startCheckout . mockImplementation ( ( ) => new Promise ( ( ) => { } ) ) ;
170+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( { } as any ) ;
171171
172172 const { baseElement } = render (
173173 < Drawer . Root
@@ -209,7 +209,7 @@ describe('Checkout', () => {
209209 } ) ;
210210
211211 // Mock billing to prevent actual API calls
212- fixtures . clerk . billing . startCheckout . mockImplementation ( ( ) => new Promise ( ( ) => { } ) ) ;
212+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( { } as any ) ;
213213
214214 const { baseElement } = render (
215215 < Drawer . Root
@@ -235,7 +235,7 @@ describe('Checkout', () => {
235235 f . withUser ( { email_addresses :
[ '[email protected] ' ] } ) ; 236236 f . withBilling ( ) ;
237237 } ) ;
238- fixtures . clerk . billing . startCheckout . mockImplementation ( ( ) => new Promise ( ( ) => { } ) ) ;
238+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( { } as any ) ;
239239 const { baseElement } = render (
240240 < Drawer . Root
241241 open
@@ -257,7 +257,7 @@ describe('Checkout', () => {
257257 const { wrapper, fixtures } = await createFixtures ( f => {
258258 f . withUser ( { email_addresses :
[ '[email protected] ' ] } ) ; 259259 } ) ;
260- fixtures . clerk . billing . startCheckout . mockImplementation ( ( ) => new Promise ( ( ) => { } ) ) ;
260+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( { } as any ) ;
261261 const { baseElement } = render (
262262 < Drawer . Root
263263 open
@@ -281,7 +281,7 @@ describe('Checkout', () => {
281281 f . withBilling ( ) ;
282282 } ) ;
283283
284- fixtures . clerk . billing . startCheckout . mockImplementation ( ( ) => new Promise ( ( ) => { } ) ) ;
284+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( { } as any ) ;
285285
286286 const { baseElement } = render (
287287 < Drawer . Root
@@ -316,7 +316,6 @@ describe('Checkout', () => {
316316 } ) ;
317317
318318 const freeTrialEndsAt = new Date ( '2025-08-19' ) ;
319-
320319 fixtures . clerk . billing . startCheckout . mockResolvedValue ( {
321320 id : 'chk_trial_1' ,
322321 status : 'needs_confirmation' ,
@@ -475,6 +474,188 @@ describe('Checkout', () => {
475474 } ) ;
476475 } ) ;
477476
477+ it ( 'renders subscription start data on completed stage for downgrades' , async ( ) => {
478+ const { wrapper, fixtures } = await createFixtures ( f => {
479+ f . withUser ( { email_addresses :
[ '[email protected] ' ] } ) ; 480+ f . withBilling ( ) ;
481+ } ) ;
482+
483+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( {
484+ id : 'chk_payment_method_2' ,
485+ status : 'completed' ,
486+ externalClientSecret : 'cs_test_payment_method_2' ,
487+ externalGatewayId : 'gw_test' ,
488+ totals : {
489+ subtotal : { amount : 1000 , amountFormatted : '10.00' , currency : 'USD' , currencySymbol : '$' } ,
490+ grandTotal : { amount : 1000 , amountFormatted : '10.00' , currency : 'USD' , currencySymbol : '$' } ,
491+ taxTotal : { amount : 0 , amountFormatted : '0.00' , currency : 'USD' , currencySymbol : '$' } ,
492+ credit : { amount : 0 , amountFormatted : '0.00' , currency : 'USD' , currencySymbol : '$' } ,
493+ pastDue : { amount : 0 , amountFormatted : '0.00' , currency : 'USD' , currencySymbol : '$' } ,
494+ totalDueNow : { amount : 0 , amountFormatted : '0.00' , currency : 'USD' , currencySymbol : '$' } ,
495+ } ,
496+ isImmediatePlanChange : true ,
497+ planPeriod : 'month' ,
498+ plan : {
499+ id : 'plan_trial' ,
500+ name : 'Pro' ,
501+ description : 'Pro plan' ,
502+ features : [ ] ,
503+ fee : {
504+ amount : 1000 ,
505+ amountFormatted : '10.00' ,
506+ currency : 'USD' ,
507+ currencySymbol : '$' ,
508+ } ,
509+ annualFee : {
510+ amount : 12000 ,
511+ amountFormatted : '120.00' ,
512+ currency : 'USD' ,
513+ currencySymbol : '$' ,
514+ } ,
515+ annualMonthlyFee : {
516+ amount : 1000 ,
517+ amountFormatted : '10.00' ,
518+ currency : 'USD' ,
519+ currencySymbol : '$' ,
520+ } ,
521+ slug : 'pro' ,
522+ avatarUrl : '' ,
523+ publiclyVisible : true ,
524+ isDefault : true ,
525+ isRecurring : true ,
526+ hasBaseFee : false ,
527+ forPayerType : 'user' ,
528+ freeTrialDays : 7 ,
529+ freeTrialEnabled : true ,
530+ } ,
531+ paymentSource : {
532+ id : 'pm_test_visa' ,
533+ last4 : '4242' ,
534+ paymentMethod : 'card' ,
535+ cardType : 'visa' ,
536+ isDefault : true ,
537+ isRemovable : true ,
538+ status : 'active' ,
539+ walletType : undefined ,
540+ remove : jest . fn ( ) ,
541+ makeDefault : jest . fn ( ) ,
542+ pathRoot : '/' ,
543+ reload : jest . fn ( ) ,
544+ } ,
545+ planPeriodStart : new Date ( '2025-08-19' ) ,
546+ confirm : jest . fn ( ) ,
547+ freeTrialEndsAt : null ,
548+ } as any ) ;
549+
550+ const { getByText } = render (
551+ < Drawer . Root
552+ open
553+ onOpenChange = { ( ) => { } }
554+ >
555+ < Checkout
556+ planId = 'plan_payment_method_complete'
557+ planPeriod = 'month'
558+ />
559+ </ Drawer . Root > ,
560+ { wrapper } ,
561+ ) ;
562+
563+ await waitFor ( ( ) => {
564+ expect ( getByText ( 'Subscription begins' ) ) . toBeVisible ( ) ;
565+ expect ( getByText ( 'August 19, 2025' ) ) . toBeVisible ( ) ;
566+ } ) ;
567+ } ) ;
568+
569+ it ( 'renders payment method on completed stage' , async ( ) => {
570+ const { wrapper, fixtures } = await createFixtures ( f => {
571+ f . withUser ( { email_addresses :
[ '[email protected] ' ] } ) ; 572+ f . withBilling ( ) ;
573+ } ) ;
574+
575+ fixtures . clerk . billing . startCheckout . mockResolvedValue ( {
576+ id : 'chk_payment_method_2' ,
577+ status : 'completed' ,
578+ externalClientSecret : 'cs_test_payment_method_2' ,
579+ externalGatewayId : 'gw_test' ,
580+ totals : {
581+ subtotal : { amount : 1000 , amountFormatted : '10.00' , currency : 'USD' , currencySymbol : '$' } ,
582+ grandTotal : { amount : 1000 , amountFormatted : '10.00' , currency : 'USD' , currencySymbol : '$' } ,
583+ taxTotal : { amount : 0 , amountFormatted : '0.00' , currency : 'USD' , currencySymbol : '$' } ,
584+ credit : { amount : 0 , amountFormatted : '0.00' , currency : 'USD' , currencySymbol : '$' } ,
585+ pastDue : { amount : 0 , amountFormatted : '0.00' , currency : 'USD' , currencySymbol : '$' } ,
586+ totalDueNow : { amount : 1000 , amountFormatted : '10.00' , currency : 'USD' , currencySymbol : '$' } ,
587+ } ,
588+ isImmediatePlanChange : true ,
589+ planPeriod : 'month' ,
590+ plan : {
591+ id : 'plan_trial' ,
592+ name : 'Pro' ,
593+ description : 'Pro plan' ,
594+ features : [ ] ,
595+ fee : {
596+ amount : 1000 ,
597+ amountFormatted : '10.00' ,
598+ currency : 'USD' ,
599+ currencySymbol : '$' ,
600+ } ,
601+ annualFee : {
602+ amount : 12000 ,
603+ amountFormatted : '120.00' ,
604+ currency : 'USD' ,
605+ currencySymbol : '$' ,
606+ } ,
607+ annualMonthlyFee : {
608+ amount : 1000 ,
609+ amountFormatted : '10.00' ,
610+ currency : 'USD' ,
611+ currencySymbol : '$' ,
612+ } ,
613+ slug : 'pro' ,
614+ avatarUrl : '' ,
615+ publiclyVisible : true ,
616+ isDefault : true ,
617+ isRecurring : true ,
618+ hasBaseFee : false ,
619+ forPayerType : 'user' ,
620+ freeTrialDays : 7 ,
621+ freeTrialEnabled : true ,
622+ } ,
623+ paymentSource : {
624+ id : 'pm_test_visa' ,
625+ last4 : '4242' ,
626+ paymentMethod : 'card' ,
627+ cardType : 'visa' ,
628+ isDefault : true ,
629+ isRemovable : true ,
630+ status : 'active' ,
631+ walletType : undefined ,
632+ remove : jest . fn ( ) ,
633+ makeDefault : jest . fn ( ) ,
634+ pathRoot : '/' ,
635+ reload : jest . fn ( ) ,
636+ } ,
637+ confirm : jest . fn ( ) ,
638+ freeTrialEndsAt : null ,
639+ } as any ) ;
640+
641+ const { getByText } = render (
642+ < Drawer . Root
643+ open
644+ onOpenChange = { ( ) => { } }
645+ >
646+ < Checkout
647+ planId = 'plan_payment_method_complete'
648+ planPeriod = 'month'
649+ />
650+ </ Drawer . Root > ,
651+ { wrapper } ,
652+ ) ;
653+
654+ await waitFor ( ( ) => {
655+ expect ( getByText ( 'Visa ⋯ 4242' ) ) . toBeVisible ( ) ;
656+ } ) ;
657+ } ) ;
658+
478659 it ( 'renders existing payment sources during checkout confirmation' , async ( ) => {
479660 const { wrapper, fixtures } = await createFixtures ( f => {
480661 f . withUser ( { email_addresses :
[ '[email protected] ' ] } ) ;
0 commit comments