@@ -811,6 +811,56 @@ describe('AppContainer State Management', () => {
811811 } ) ;
812812
813813 describe ( 'Context Providers' , ( ) => {
814+ const renderRespondingInput = (
815+ slashCommands : Array < {
816+ name : string ;
817+ description : string ;
818+ kind : 'built-in' ;
819+ canRunDuringStreaming ?: boolean ;
820+ } > ,
821+ ) => {
822+ const handleSlashCommand = vi . fn ( ) ;
823+ const submitQuery = vi . fn ( ) ;
824+ const addMessage = vi . fn ( ) ;
825+ mockedUseSlashCommandProcessor . mockReturnValue ( {
826+ handleSlashCommand,
827+ slashCommands,
828+ pendingHistoryItems : [ ] ,
829+ commandContext : { } ,
830+ shellConfirmationRequest : null ,
831+ confirmationRequest : null ,
832+ } ) ;
833+ mockedUseGeminiStream . mockReturnValue ( {
834+ streamingState : 'responding' ,
835+ submitQuery,
836+ initError : null ,
837+ pendingHistoryItems : [ ] ,
838+ thought : null ,
839+ cancelOngoingRequest : vi . fn ( ) ,
840+ retryLastPrompt : vi . fn ( ) ,
841+ streamingResponseLengthRef : { current : 0 } ,
842+ isReceivingContent : false ,
843+ } ) ;
844+ mockedUseMessageQueue . mockReturnValue ( {
845+ messageQueue : [ ] ,
846+ addMessage,
847+ clearQueue : vi . fn ( ) ,
848+ getQueuedMessagesText : vi . fn ( ) . mockReturnValue ( '' ) ,
849+ popAllMessages : vi . fn ( ) . mockReturnValue ( null ) ,
850+ drainQueue : vi . fn ( ) . mockReturnValue ( [ ] ) ,
851+ popNextTurn : vi . fn ( ) . mockReturnValue ( null ) ,
852+ } ) ;
853+ render (
854+ < AppContainer
855+ config = { mockConfig }
856+ settings = { mockSettings }
857+ version = "1.0.0"
858+ initializationResult = { mockInitResult }
859+ /> ,
860+ ) ;
861+ return { handleSlashCommand, submitQuery, addMessage } ;
862+ } ;
863+
814864 it ( 'provides AppContext with correct values' , ( ) => {
815865 const { unmount } = render (
816866 < AppContainer
@@ -1393,6 +1443,66 @@ describe('AppContainer State Management', () => {
13931443 expect ( mockQueueMessage ) . not . toHaveBeenCalled ( ) ;
13941444 } ) ;
13951445
1446+ it ( 'runs opted-in slash commands outside the active turn while responding' , ( ) => {
1447+ const { handleSlashCommand, submitQuery, addMessage } =
1448+ renderRespondingInput ( [
1449+ {
1450+ name : 'settings' ,
1451+ description : 'Open settings' ,
1452+ kind : 'built-in' ,
1453+ canRunDuringStreaming : true ,
1454+ } ,
1455+ ] ) ;
1456+
1457+ capturedUIActions . handleFinalSubmit ( '/settings' , {
1458+ submittedPrompt : '/settings' ,
1459+ } ) ;
1460+
1461+ expect ( handleSlashCommand ) . toHaveBeenCalledWith ( '/settings' ) ;
1462+ expect ( submitQuery ) . not . toHaveBeenCalled ( ) ;
1463+ expect ( addMessage ) . not . toHaveBeenCalled ( ) ;
1464+ } ) ;
1465+
1466+ it ( 'keeps opted-in slash commands queued when Ctrl+Q defers them' , ( ) => {
1467+ const { handleSlashCommand, submitQuery, addMessage } =
1468+ renderRespondingInput ( [
1469+ {
1470+ name : 'settings' ,
1471+ description : 'Open settings' ,
1472+ kind : 'built-in' ,
1473+ canRunDuringStreaming : true ,
1474+ } ,
1475+ ] ) ;
1476+
1477+ capturedUIActions . handleFinalSubmit ( '/settings' , {
1478+ deferUntilIdle : true ,
1479+ submittedPrompt : '/settings' ,
1480+ } ) ;
1481+
1482+ expect ( addMessage ) . toHaveBeenCalledWith ( '/settings' , true , '/settings' ) ;
1483+ expect ( handleSlashCommand ) . not . toHaveBeenCalled ( ) ;
1484+ expect ( submitQuery ) . not . toHaveBeenCalled ( ) ;
1485+ } ) ;
1486+
1487+ it ( 'keeps turn-dependent slash commands queued while responding' , ( ) => {
1488+ const { handleSlashCommand, submitQuery, addMessage } =
1489+ renderRespondingInput ( [
1490+ {
1491+ name : 'model' ,
1492+ description : 'Change model' ,
1493+ kind : 'built-in' ,
1494+ } ,
1495+ ] ) ;
1496+
1497+ capturedUIActions . handleFinalSubmit ( '/model' , {
1498+ submittedPrompt : '/model' ,
1499+ } ) ;
1500+
1501+ expect ( addMessage ) . toHaveBeenCalledWith ( '/model' , false , '/model' ) ;
1502+ expect ( handleSlashCommand ) . not . toHaveBeenCalled ( ) ;
1503+ expect ( submitQuery ) . not . toHaveBeenCalled ( ) ;
1504+ } ) ;
1505+
13961506 it ( 'submits slash commands immediately instead of queueing while idle' , ( ) => {
13971507 const mockSubmitQuery = vi . fn ( ) ;
13981508 const mockQueueMessage = vi . fn ( ) ;
0 commit comments