@@ -681,74 +681,81 @@ describe('workflow execute async route', () => {
681681 expect ( mockEnqueue ) . not . toHaveBeenCalled ( )
682682 } )
683683
684- it ( 'binds a Copilot workflow tool only to its server log and waits before terminal SSE' , async ( ) => {
685- let releasePostExecution : ( ( ) => void ) | undefined
686- loggingSessionMockFns . mockWaitForPostExecution . mockImplementationOnce (
687- ( ) =>
688- new Promise < void > ( ( resolve ) => {
689- releasePostExecution = resolve
690- } )
691- )
684+ it . each ( [ true , false ] ) (
685+ 'binds a Copilot tool and waits for logs before terminal SSE (draft=%s)' ,
686+ async ( useDraftState ) => {
687+ let releasePostExecution : ( ( ) => void ) | undefined
688+ loggingSessionMockFns . mockWaitForPostExecution . mockImplementationOnce (
689+ ( ) =>
690+ new Promise < void > ( ( resolve ) => {
691+ releasePostExecution = resolve
692+ } )
693+ )
692694
693- const response = await POST ( createBoundCopilotExecutionRequest ( ) , {
694- params : Promise . resolve ( { id : 'workflow-1' } ) ,
695- } )
696- const bodyPromise = response . text ( )
695+ const response = await POST ( createBoundCopilotExecutionRequest ( { useDraftState } ) , {
696+ params : Promise . resolve ( { id : 'workflow-1' } ) ,
697+ } )
698+ const bodyPromise = response . text ( )
697699
698- await vi . waitFor ( ( ) => {
699- expect ( loggingSessionMockFns . mockWaitForPostExecution ) . toHaveBeenCalledTimes ( 1 )
700- } )
701- let streamCompleted = false
702- void bodyPromise . then ( ( ) => {
703- streamCompleted = true
704- } )
705- await Promise . resolve ( )
700+ await vi . waitFor ( ( ) => {
701+ expect ( loggingSessionMockFns . mockWaitForPostExecution ) . toHaveBeenCalledTimes ( 1 )
702+ } )
703+ let streamCompleted = false
704+ void bodyPromise . then ( ( ) => {
705+ streamCompleted = true
706+ } )
707+ await Promise . resolve ( )
706708
707- expect ( response . status ) . toBe ( 200 )
708- expect ( streamCompleted ) . toBe ( false )
709- expect ( mockSettleClientWorkflowToolExecution ) . not . toHaveBeenCalled ( )
710- expect ( mockClaimWorkflowToolExecution ) . toHaveBeenCalledWith (
711- 'copilot-tool-1' ,
712- 'execution-123' ,
713- 'client'
714- )
715- expect ( mockReleaseWorkflowToolExecutionClaim ) . not . toHaveBeenCalled ( )
716- expect ( loggingSessionMockFns . mockSetTrustedExecutionCorrelation ) . toHaveBeenCalledWith ( {
717- executionId : 'execution-123' ,
718- requestId : 'req-12345678' ,
719- source : 'workflow' ,
720- workflowId : 'workflow-1' ,
721- triggerType : 'copilot' ,
722- copilotToolCallId : 'copilot-tool-1' ,
723- } )
724- const executionArgs = mockExecuteWorkflowCore . mock . calls [ 0 ] [ 0 ]
725- expect ( executionArgs ) . not . toHaveProperty ( 'copilotToolCallId' )
726- expect ( executionArgs . snapshot . metadata ) . not . toHaveProperty ( 'copilotToolCallId' )
727-
728- releasePostExecution ?.( )
729- const body = await bodyPromise
730- expect ( body ) . toContain ( 'execution:completed' )
731- await vi . waitFor ( ( ) =>
732- expect ( mockSettleClientWorkflowToolExecution ) . toHaveBeenCalledExactlyOnceWith (
709+ expect ( response . status ) . toBe ( 200 )
710+ expect ( streamCompleted ) . toBe ( false )
711+ expect ( mockSettleClientWorkflowToolExecution ) . not . toHaveBeenCalled ( )
712+ expect ( mockClaimWorkflowToolExecution ) . toHaveBeenCalledWith (
733713 'copilot-tool-1' ,
734- expect . any ( String )
714+ 'execution-123' ,
715+ 'client'
735716 )
736- )
737- } )
717+ expect ( mockReleaseWorkflowToolExecutionClaim ) . not . toHaveBeenCalled ( )
718+ expect ( loggingSessionMockFns . mockSetTrustedExecutionCorrelation ) . toHaveBeenCalledWith ( {
719+ executionId : 'execution-123' ,
720+ requestId : 'req-12345678' ,
721+ source : 'workflow' ,
722+ workflowId : 'workflow-1' ,
723+ triggerType : 'copilot' ,
724+ copilotToolCallId : 'copilot-tool-1' ,
725+ } )
726+ const executionArgs = mockExecuteWorkflowCore . mock . calls [ 0 ] [ 0 ]
727+ expect ( executionArgs . snapshot . metadata . useDraftState ) . toBe ( useDraftState )
728+ expect ( executionArgs ) . not . toHaveProperty ( 'copilotToolCallId' )
729+ expect ( executionArgs . snapshot . metadata ) . not . toHaveProperty ( 'copilotToolCallId' )
730+
731+ releasePostExecution ?.( )
732+ const body = await bodyPromise
733+ expect ( body ) . toContain ( 'execution:completed' )
734+ await vi . waitFor ( ( ) =>
735+ expect ( mockSettleClientWorkflowToolExecution ) . toHaveBeenCalledExactlyOnceWith (
736+ 'copilot-tool-1' ,
737+ expect . any ( String )
738+ )
739+ )
740+ }
741+ )
738742
739- it ( 'settles failed Copilot execution after the route finishes error handling' , async ( ) => {
740- mockExecuteWorkflowCore . mockRejectedValueOnce ( new Error ( 'Execution rejected' ) )
741- const response = await POST ( createBoundCopilotExecutionRequest ( ) , {
742- params : Promise . resolve ( { id : 'workflow-1' } ) ,
743- } )
744- expect ( await response . text ( ) ) . toContain ( 'execution:error' )
745- await vi . waitFor ( ( ) =>
746- expect ( mockSettleClientWorkflowToolExecution ) . toHaveBeenCalledExactlyOnceWith (
747- 'copilot-tool-1' ,
748- expect . any ( String )
743+ it . each ( [ true , false ] ) (
744+ 'settles failed Copilot execution after error handling (draft=%s)' ,
745+ async ( useDraftState ) => {
746+ mockExecuteWorkflowCore . mockRejectedValueOnce ( new Error ( 'Execution rejected' ) )
747+ const response = await POST ( createBoundCopilotExecutionRequest ( { useDraftState } ) , {
748+ params : Promise . resolve ( { id : 'workflow-1' } ) ,
749+ } )
750+ expect ( await response . text ( ) ) . toContain ( 'execution:error' )
751+ await vi . waitFor ( ( ) =>
752+ expect ( mockSettleClientWorkflowToolExecution ) . toHaveBeenCalledExactlyOnceWith (
753+ 'copilot-tool-1' ,
754+ expect . any ( String )
755+ )
749756 )
750- )
751- } )
757+ }
758+ )
752759
753760 it ( 'settles a detached Copilot stream only after its cancelled execution and cleanup end' , async ( ) => {
754761 let releaseCleanup : ( ( ) => void ) | undefined
0 commit comments