Skip to content

Commit 8662179

Browse files
committed
ack
1 parent 0f2b59d commit 8662179

File tree

2 files changed

+161
-2
lines changed

2 files changed

+161
-2
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import { beforeEach, describe, expect, it, vi } from 'vitest'
2+
3+
const { mockLogger, queryClient, useFolderStoreMock, useWorkflowRegistryMock } = vi.hoisted(() => ({
4+
mockLogger: {
5+
info: vi.fn(),
6+
warn: vi.fn(),
7+
error: vi.fn(),
8+
debug: vi.fn(),
9+
},
10+
queryClient: {
11+
cancelQueries: vi.fn().mockResolvedValue(undefined),
12+
invalidateQueries: vi.fn().mockResolvedValue(undefined),
13+
},
14+
useFolderStoreMock: Object.assign(vi.fn(), {
15+
getState: vi.fn(),
16+
setState: vi.fn(),
17+
}),
18+
useWorkflowRegistryMock: Object.assign(vi.fn(), {
19+
getState: vi.fn(),
20+
setState: vi.fn(),
21+
}),
22+
}))
23+
24+
let folderState: {
25+
folders: Record<string, any>
26+
}
27+
28+
let workflowRegistryState: {
29+
workflows: Record<string, any>
30+
}
31+
32+
vi.mock('@sim/logger', () => ({
33+
createLogger: vi.fn(() => mockLogger),
34+
}))
35+
36+
vi.mock('@tanstack/react-query', () => ({
37+
keepPreviousData: {},
38+
useQuery: vi.fn(),
39+
useQueryClient: vi.fn(() => queryClient),
40+
useMutation: vi.fn((options) => options),
41+
}))
42+
43+
vi.mock('@/stores/folders/store', () => ({
44+
useFolderStore: useFolderStoreMock,
45+
}))
46+
47+
vi.mock('@/stores/workflows/registry/store', () => ({
48+
useWorkflowRegistry: useWorkflowRegistryMock,
49+
}))
50+
51+
vi.mock('@/hooks/queries/workflows', () => ({
52+
workflowKeys: {
53+
list: (workspaceId: string | undefined) => ['workflows', 'list', workspaceId ?? ''],
54+
},
55+
}))
56+
57+
import { useCreateFolder, useDuplicateFolderMutation } from '@/hooks/queries/folders'
58+
59+
function getOptimisticFolderByName(name: string) {
60+
return Object.values(folderState.folders).find((folder: any) => folder.name === name) as
61+
| { sortOrder: number }
62+
| undefined
63+
}
64+
65+
describe('folder optimistic top insertion ordering', () => {
66+
beforeEach(() => {
67+
vi.clearAllMocks()
68+
useFolderStoreMock.getState.mockImplementation(() => folderState)
69+
useFolderStoreMock.setState.mockImplementation((updater: any) => {
70+
if (typeof updater === 'function') {
71+
const next = updater(folderState)
72+
if (next) {
73+
folderState = { ...folderState, ...next }
74+
}
75+
return
76+
}
77+
78+
folderState = { ...folderState, ...updater }
79+
})
80+
useWorkflowRegistryMock.getState.mockImplementation(() => workflowRegistryState)
81+
82+
folderState = {
83+
folders: {
84+
'folder-parent-match': {
85+
id: 'folder-parent-match',
86+
name: 'Existing sibling folder',
87+
userId: 'user-1',
88+
workspaceId: 'ws-1',
89+
parentId: 'parent-1',
90+
color: '#808080',
91+
isExpanded: false,
92+
sortOrder: 5,
93+
createdAt: new Date(),
94+
updatedAt: new Date(),
95+
},
96+
'folder-other-parent': {
97+
id: 'folder-other-parent',
98+
name: 'Other parent folder',
99+
userId: 'user-1',
100+
workspaceId: 'ws-1',
101+
parentId: 'parent-2',
102+
color: '#808080',
103+
isExpanded: false,
104+
sortOrder: -100,
105+
createdAt: new Date(),
106+
updatedAt: new Date(),
107+
},
108+
},
109+
}
110+
111+
workflowRegistryState = {
112+
workflows: {
113+
'workflow-parent-match': {
114+
id: 'workflow-parent-match',
115+
name: 'Existing sibling workflow',
116+
workspaceId: 'ws-1',
117+
folderId: 'parent-1',
118+
sortOrder: 2,
119+
},
120+
'workflow-other-parent': {
121+
id: 'workflow-other-parent',
122+
name: 'Other parent workflow',
123+
workspaceId: 'ws-1',
124+
folderId: 'parent-2',
125+
sortOrder: -50,
126+
},
127+
},
128+
}
129+
})
130+
131+
it('creates folders at top of mixed non-root siblings', async () => {
132+
const mutation = useCreateFolder()
133+
134+
await mutation.onMutate({
135+
workspaceId: 'ws-1',
136+
name: 'New child folder',
137+
parentId: 'parent-1',
138+
})
139+
140+
const optimisticFolder = getOptimisticFolderByName('New child folder')
141+
expect(optimisticFolder).toBeDefined()
142+
expect(optimisticFolder?.sortOrder).toBe(1)
143+
})
144+
145+
it('duplicates folders at top of mixed non-root siblings', async () => {
146+
const mutation = useDuplicateFolderMutation()
147+
148+
await mutation.onMutate({
149+
workspaceId: 'ws-1',
150+
id: 'folder-parent-match',
151+
name: 'Duplicated child folder',
152+
parentId: 'parent-1',
153+
})
154+
155+
const optimisticFolder = getOptimisticFolderByName('Duplicated child folder')
156+
expect(optimisticFolder).toBeDefined()
157+
expect(optimisticFolder?.sortOrder).toBe(1)
158+
})
159+
})

apps/sim/hooks/queries/folders.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ export function useCreateFolder() {
155155
sortOrder:
156156
variables.sortOrder ??
157157
getTopInsertionSortOrder(
158-
previousFolders,
159158
currentWorkflows,
159+
previousFolders,
160160
variables.workspaceId,
161161
variables.parentId
162162
),
@@ -252,8 +252,8 @@ export function useDuplicateFolderMutation() {
252252
color: variables.color || sourceFolder?.color || '#808080',
253253
isExpanded: false,
254254
sortOrder: getTopInsertionSortOrder(
255-
previousFolders,
256255
currentWorkflows,
256+
previousFolders,
257257
variables.workspaceId,
258258
variables.parentId
259259
),

0 commit comments

Comments
 (0)