@@ -548,6 +548,98 @@ describe('deployOrReleaseConfirmationPrompt', () => {
548548 } ) ,
549549 ) . rejects . toThrow ( 'This deployment includes changes that require confirmation.' )
550550 } )
551+
552+ test ( 'non-TTY with only updates should suggest --allow-updates flag in error' , async ( ) => {
553+ // Given
554+ const breakdownInfo = buildEmptyBreakdownInfo ( )
555+ // Add only updates (no deletes)
556+ breakdownInfo . extensionIdentifiersBreakdown . toCreate = [ buildExtensionBreakdownInfo ( 'new extension' , 'uid-new' ) ]
557+ breakdownInfo . configExtensionIdentifiersBreakdown ! . newFieldNames = [ 'new field' ]
558+
559+ vi . spyOn ( metadata , 'addPublicMetadata' ) . mockImplementation ( async ( ) => { } )
560+ vi . spyOn ( ui , 'isTTY' ) . mockReturnValue ( false )
561+
562+ // When/Then
563+ await expect (
564+ deployOrReleaseConfirmationPrompt ( {
565+ ...breakdownInfo ,
566+ appTitle : 'app title' ,
567+ release : true ,
568+ force : false ,
569+ } ) ,
570+ ) . rejects . toMatchObject ( {
571+ message : 'This deployment includes changes that require confirmation.' ,
572+ // tryMessage contains the suggestion with the command token
573+ tryMessage : expect . arrayContaining ( [ { command : '--allow-updates' } ] ) ,
574+ } )
575+ } )
576+
577+ test ( 'non-TTY with only deletes should suggest --allow-deletes flag in error' , async ( ) => {
578+ // Given
579+ const breakdownInfo = buildEmptyBreakdownInfo ( )
580+ // Add only deletes (no updates)
581+ breakdownInfo . extensionIdentifiersBreakdown . onlyRemote = [
582+ buildExtensionBreakdownInfo ( 'remote extension' , 'uid-remote' ) ,
583+ ]
584+
585+ vi . spyOn ( metadata , 'addPublicMetadata' ) . mockImplementation ( async ( ) => { } )
586+ vi . spyOn ( ui , 'isTTY' ) . mockReturnValue ( false )
587+
588+ // When/Then
589+ await expect (
590+ deployOrReleaseConfirmationPrompt ( {
591+ ...breakdownInfo ,
592+ appTitle : 'app title' ,
593+ release : true ,
594+ force : false ,
595+ } ) ,
596+ ) . rejects . toMatchObject ( {
597+ message : 'This deployment includes changes that require confirmation.' ,
598+ // tryMessage contains the suggestion with the command token
599+ tryMessage : expect . arrayContaining ( [ { command : '--allow-deletes' } ] ) ,
600+ } )
601+ } )
602+
603+ test ( 'non-TTY with both updates and deletes should suggest both flags in error' , async ( ) => {
604+ // Given
605+ const breakdownInfo = buildCompleteBreakdownInfo ( )
606+ vi . spyOn ( metadata , 'addPublicMetadata' ) . mockImplementation ( async ( ) => { } )
607+ vi . spyOn ( ui , 'isTTY' ) . mockReturnValue ( false )
608+
609+ // When/Then
610+ await expect (
611+ deployOrReleaseConfirmationPrompt ( {
612+ ...breakdownInfo ,
613+ appTitle : 'app title' ,
614+ release : true ,
615+ force : false ,
616+ } ) ,
617+ ) . rejects . toMatchObject ( {
618+ message : 'This deployment includes changes that require confirmation.' ,
619+ // tryMessage contains the suggestion with both command flags joined
620+ tryMessage : expect . arrayContaining ( [ { command : '--allow-updates --allow-deletes' } ] ) ,
621+ } )
622+ } )
623+
624+ test ( 'non-TTY without any changes should not throw error' , async ( ) => {
625+ // Given
626+ const breakdownInfo = buildEmptyBreakdownInfo ( )
627+ const renderConfirmationPromptSpyOn = vi . spyOn ( ui , 'renderConfirmationPrompt' ) . mockResolvedValue ( true )
628+ vi . spyOn ( metadata , 'addPublicMetadata' ) . mockImplementation ( async ( ) => { } )
629+ vi . spyOn ( ui , 'isTTY' ) . mockReturnValue ( false )
630+
631+ // When
632+ const result = await deployOrReleaseConfirmationPrompt ( {
633+ ...breakdownInfo ,
634+ appTitle : 'app title' ,
635+ release : true ,
636+ force : false ,
637+ } )
638+
639+ // Then - should show the prompt normally since there are no changes requiring confirmation
640+ expect ( renderConfirmationPromptSpyOn ) . toHaveBeenCalled ( )
641+ expect ( result ) . toBe ( true )
642+ } )
551643 } )
552644} )
553645
0 commit comments