@@ -7,11 +7,21 @@ import type { ExecutionContext } from '@/lib/copilot/request/types'
77const { mocks } = vi . hoisted ( ( ) => ( {
88 mocks : {
99 apiKey : vi . fn ( ) ,
10+ cancelWorkflowExecutionRoute : vi . fn ( ) ,
1011 executeWorkflowUseCase : vi . fn ( ) ,
12+ generateInternalToken : vi . fn ( ) ,
1113 hasExecutionResult : vi . fn ( ) ,
1214 } ,
1315} ) )
1416
17+ vi . mock ( '@/app/api/workflows/[id]/executions/[executionId]/cancel/route' , ( ) => ( {
18+ POST : mocks . cancelWorkflowExecutionRoute ,
19+ } ) )
20+
21+ vi . mock ( '@/lib/auth/internal' , ( ) => ( {
22+ generateInternalToken : mocks . generateInternalToken ,
23+ } ) )
24+
1525vi . mock ( '@/lib/copilot/application/execute-workflow-use-case' , ( ) => ( {
1626 executeCopilotWorkflowUseCase : mocks . executeWorkflowUseCase ,
1727 messageForCopilotWorkflowError : ( _error : unknown , fallback = 'Workflow operation failed' ) =>
@@ -51,12 +61,14 @@ const context = {
5161 workspaceId : 'workspace-1' ,
5262 workflowId : 'workflow-1' ,
5363 toolCallId : 'tool-call-1' ,
64+ copilotToolExecution : true ,
5465 billingAttribution : { workspaceId : 'workspace-1' } ,
5566} as ExecutionContext
5667
5768describe ( 'workflow mutation Copilot adapters' , ( ) => {
5869 beforeEach ( ( ) => {
5970 vi . clearAllMocks ( )
71+ mocks . generateInternalToken . mockResolvedValue ( 'internal-token' )
6072 mocks . hasExecutionResult . mockReturnValue ( false )
6173 } )
6274
@@ -159,18 +171,18 @@ describe('workflow mutation Copilot adapters', () => {
159171 )
160172 } )
161173
162- it ( 'cancels a workflow run through the registered application command ' , async ( ) => {
163- mocks . executeWorkflowUseCase . mockResolvedValue ( {
164- success : true ,
165- executionId : 'execution-1' ,
166- redisAvailable : true ,
167- durablyRecorded : true ,
168- locallyAborted : false ,
169- pausedCancelled : false ,
170- reason : 'recorded' ,
171- workflowId : 'workflow-1 ' ,
172- workspaceId : 'workspace-1' ,
173- } )
174+ it ( 'cancels a workflow run through the same route as the logs UI ' , async ( ) => {
175+ mocks . cancelWorkflowExecutionRoute . mockResolvedValue (
176+ Response . json ( {
177+ success : true ,
178+ executionId : 'execution-1' ,
179+ redisAvailable : true ,
180+ durablyRecorded : true ,
181+ locallyAborted : false ,
182+ pausedCancelled : false ,
183+ reason : 'recorded ' ,
184+ } )
185+ )
174186
175187 const result = await executeCancelWorkflowRun (
176188 { workflowId : 'workflow-1' , executionId : 'execution-1' } ,
@@ -188,19 +200,40 @@ describe('workflow mutation Copilot adapters', () => {
188200 reason : 'recorded' ,
189201 } ,
190202 } )
191- expect ( mocks . executeWorkflowUseCase ) . toHaveBeenCalledWith (
192- context ,
193- expect . objectContaining ( {
194- operation : expect . objectContaining ( { id : 'workflows.runs.cancel' } ) ,
195- } ) ,
196- { workflowId : 'workflow-1' , runId : 'execution-1' }
203+ expect ( mocks . generateInternalToken ) . toHaveBeenCalledWith ( 'user-1' )
204+ expect ( mocks . cancelWorkflowExecutionRoute ) . toHaveBeenCalledOnce ( )
205+ const [ request , routeContext ] = mocks . cancelWorkflowExecutionRoute . mock . calls [ 0 ]
206+ expect ( request . method ) . toBe ( 'POST' )
207+ expect ( request . headers . get ( 'authorization' ) ) . toBe ( 'Bearer internal-token' )
208+ expect ( request . nextUrl . pathname ) . toBe ( '/api/workflows/workflow-1/executions/execution-1/cancel' )
209+ await expect ( routeContext . params ) . resolves . toEqual ( {
210+ id : 'workflow-1' ,
211+ executionId : 'execution-1' ,
212+ } )
213+ expect ( mocks . executeWorkflowUseCase ) . not . toHaveBeenCalled ( )
214+ } )
215+
216+ it ( 'returns the cancellation route error to the Run agent' , async ( ) => {
217+ mocks . cancelWorkflowExecutionRoute . mockResolvedValue (
218+ Response . json ( { error : 'Execution cannot be cancelled while completed' } , { status : 409 } )
197219 )
220+
221+ const result = await executeCancelWorkflowRun (
222+ { workflowId : 'workflow-1' , executionId : 'execution-1' } ,
223+ context
224+ )
225+
226+ expect ( result ) . toEqual ( {
227+ success : false ,
228+ error : 'Execution cannot be cancelled while completed' ,
229+ } )
198230 } )
199231
200232 it ( 'requires an execution ID before attempting workflow-run cancellation' , async ( ) => {
201233 const result = await executeCancelWorkflowRun ( { workflowId : 'workflow-1' } , context )
202234
203235 expect ( result ) . toEqual ( { success : false , error : 'executionId is required' } )
236+ expect ( mocks . cancelWorkflowExecutionRoute ) . not . toHaveBeenCalled ( )
204237 expect ( mocks . executeWorkflowUseCase ) . not . toHaveBeenCalled ( )
205238 } )
206239
0 commit comments