33 */
44import { dbChainMock , resetDbChainMock , schemaMock , workflowAuthzMockFns } from '@sim/testing'
55import { afterAll , beforeEach , describe , expect , it , vi } from 'vitest'
6+ import { knowledgeOperations } from '@/lib/knowledge/application/operations'
7+ import { workflowOperations } from '@/lib/workflows/application/operations'
8+ import { fileOperations } from '@/lib/workspace-files/application/operations'
69
710const mocks = vi . hoisted ( ( ) => ( {
811 ensureWorkspaceAccess : vi . fn ( ) ,
@@ -74,41 +77,28 @@ vi.mock('@/lib/copilot/tools/server/files/file-folder-application', () => ({
7477
7578vi . mock ( '@/lib/workspace-files/application/move-workspace-file-items' , ( ) => ( {
7679 moveWorkspaceFileItemsOperation : {
77- operation : { id : 'files .move' , minimumRole : 'write' , workspaceApiKey : 'allow' } ,
80+ operation : fileOperations . move ,
7881 execute : mocks . moveWorkspaceFileItems ,
7982 } ,
8083} ) )
8184
82- vi . mock ( '@/lib/workspace-files/application/operations' , ( ) => ( {
83- fileOperations : {
84- move : { id : 'files.move' , minimumRole : 'write' , workspaceApiKey : 'allow' } ,
85- rename : { id : 'files.rename' , minimumRole : 'write' , workspaceApiKey : 'allow' } ,
86- delete : { id : 'files.delete' , minimumRole : 'write' , workspaceApiKey : 'allow' } ,
87- updateFolder : {
88- id : 'files.folders.update' ,
89- minimumRole : 'write' ,
90- workspaceApiKey : 'allow' ,
91- } ,
92- } ,
93- } ) )
94-
9585vi . mock ( '@/lib/workspace-files/application/workspace-file-folders' , ( ) => ( {
9686 updateWorkspaceFileFolderOperation : {
97- operation : { id : 'files.folders.update' , minimumRole : 'write' , workspaceApiKey : 'allow' } ,
87+ operation : fileOperations . updateFolder ,
9888 execute : mocks . updateWorkspaceFileFolder ,
9989 } ,
10090} ) )
10191
10292vi . mock ( '@/lib/workspace-files/application/delete-workspace-file' , ( ) => ( {
10393 deleteWorkspaceFileOperation : {
104- operation : { id : 'files .delete' , minimumRole : 'write' , workspaceApiKey : 'allow' } ,
94+ operation : fileOperations . delete ,
10595 execute : mocks . deleteWorkspaceFile ,
10696 } ,
10797} ) )
10898
10999vi . mock ( '@/lib/workspace-files/application/archive-workspace-file-items' , ( ) => ( {
110100 archiveWorkspaceFileItemsOperation : {
111- operation : { id : 'files .delete' , minimumRole : 'write' , workspaceApiKey : 'allow' } ,
101+ operation : fileOperations . delete ,
112102 execute : mocks . deleteWorkspaceFile ,
113103 } ,
114104} ) )
@@ -117,26 +107,26 @@ vi.mock('@/lib/workspace-files/orchestration', () => ({}))
117107
118108vi . mock ( '@/lib/workspace-files/application/rename-workspace-file' , ( ) => ( {
119109 renameWorkspaceFile : {
120- operation : { id : 'files .rename' , minimumRole : 'write' , workspaceApiKey : 'allow' } ,
110+ operation : fileOperations . rename ,
121111 execute : mocks . renameWorkspaceFile ,
122112 } ,
123113} ) )
124114
125115vi . mock ( '@/lib/workflows/application/workflow-vfs' , ( ) => ( {
126116 moveWorkflowVfsItems : {
127- operation : { id : 'workflows.vfs.move' } ,
117+ operation : workflowOperations . moveVfsItems ,
128118 execute : mocks . moveWorkflowVfs ,
129119 } ,
130120 copyWorkflowVfsItems : {
131- operation : { id : 'workflows.vfs.copy' } ,
121+ operation : workflowOperations . copyVfsItems ,
132122 execute : mocks . copyWorkflowVfs ,
133123 } ,
134124 createWorkflowVfsFolders : {
135- operation : { id : 'workflows.vfs.folders.create' } ,
125+ operation : workflowOperations . createVfsFolders ,
136126 execute : mocks . createWorkflowVfsFolders ,
137127 } ,
138128 deleteWorkflowVfsItems : {
139- operation : { id : 'workflows.vfs.delete' } ,
129+ operation : workflowOperations . deleteVfsItems ,
140130 execute : mocks . deleteWorkflowVfs ,
141131 } ,
142132} ) )
@@ -148,15 +138,15 @@ vi.mock('@/lib/table/service', () => ({
148138
149139vi . mock ( '@/lib/knowledge/application/knowledge-bases' , ( ) => ( {
150140 listKnowledgeBases : {
151- operation : { id : 'knowledge .list' } ,
141+ operation : knowledgeOperations . list ,
152142 execute : mocks . listKnowledgeBases ,
153143 } ,
154144 updateKnowledgeBaseOperation : {
155- operation : { id : 'knowledge .update' } ,
145+ operation : knowledgeOperations . update ,
156146 execute : mocks . updateKnowledgeBase ,
157147 } ,
158148 deleteKnowledgeBaseOperation : {
159- operation : { id : 'knowledge .delete' } ,
149+ operation : knowledgeOperations . delete ,
160150 execute : mocks . deleteKnowledgeBase ,
161151 } ,
162152} ) )
@@ -473,6 +463,25 @@ describe('vfs mv/cp', () => {
473463 expect ( result . success ) . toBe ( true )
474464 } )
475465
466+ it ( 'preserves safe workflow application validation errors' , async ( ) => {
467+ mocks . moveWorkflowVfs . mockRejectedValueOnce (
468+ new OrchestrationError (
469+ 'validation' ,
470+ 'With multiple sources the destination must be a folder'
471+ )
472+ )
473+
474+ const result = await executeVfsMv (
475+ { sources : [ 'workflows/One' , 'workflows/Two' ] , destination : 'workflows/Renamed' } ,
476+ context
477+ )
478+
479+ expect ( result ) . toEqual ( {
480+ success : false ,
481+ error : 'With multiple sources the destination must be a folder' ,
482+ } )
483+ } )
484+
476485 it ( 'surfaces locked-workflow rejections per item' , async ( ) => {
477486 mocks . moveWorkflowVfs . mockResolvedValue ( {
478487 outcomes : [
0 commit comments