diff --git a/web/app/components/snippets/hooks/__tests__/use-snippet-refresh-draft.spec.ts b/web/app/components/snippets/hooks/__tests__/use-snippet-refresh-draft.spec.ts new file mode 100644 index 0000000000..c85bfe3bc5 --- /dev/null +++ b/web/app/components/snippets/hooks/__tests__/use-snippet-refresh-draft.spec.ts @@ -0,0 +1,101 @@ +import type { SnippetWorkflow } from '@/types/snippet' +import { renderHook, waitFor } from '@testing-library/react' +import { useSnippetRefreshDraft } from '../use-snippet-refresh-draft' + +const mockFetchSnippetDraftWorkflow = vi.fn() +const mockHandleUpdateWorkflowCanvas = vi.fn() +const mockSnippetSetState = vi.fn() +const mockSetDraftUpdatedAt = vi.fn() +const mockSetIsSyncingWorkflowDraft = vi.fn() +const mockSetSyncWorkflowDraftHash = vi.fn() + +const workflowStoreState = { + setDraftUpdatedAt: mockSetDraftUpdatedAt, + setIsSyncingWorkflowDraft: mockSetIsSyncingWorkflowDraft, + setSyncWorkflowDraftHash: mockSetSyncWorkflowDraftHash, +} + +vi.mock('@/service/use-snippet-workflows', () => ({ + fetchSnippetDraftWorkflow: (...args: unknown[]) => mockFetchSnippetDraftWorkflow(...args), +})) + +vi.mock('@/app/components/workflow/hooks', () => ({ + useWorkflowUpdate: () => ({ + handleUpdateWorkflowCanvas: mockHandleUpdateWorkflowCanvas, + }), +})) + +vi.mock('@/app/components/workflow/store', () => ({ + useWorkflowStore: () => ({ + getState: () => workflowStoreState, + }), +})) + +vi.mock('../../store', () => ({ + useSnippetDetailStore: { + setState: (...args: unknown[]) => mockSnippetSetState(...args), + }, +})) + +const createDraftWorkflow = (overrides: Partial = {}): SnippetWorkflow => ({ + id: 'draft-1', + graph: { + nodes: [{ id: 'node-1' }], + edges: [], + viewport: { x: 10, y: 20, zoom: 1.2 }, + }, + features: {}, + input_fields: [], + hash: 'draft-hash', + created_at: 1_712_300_000, + updated_at: 1_712_345_678, + ...overrides, +} as SnippetWorkflow) + +describe('useSnippetRefreshDraft', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('should refresh the draft workflow through the silent draft fetcher', async () => { + const draftWorkflow = createDraftWorkflow() + const onSuccess = vi.fn() + mockFetchSnippetDraftWorkflow.mockResolvedValueOnce(draftWorkflow) + + const { result } = renderHook(() => useSnippetRefreshDraft('snippet-1')) + + result.current.handleRefreshWorkflowDraft(onSuccess) + + await waitFor(() => { + expect(mockHandleUpdateWorkflowCanvas).toHaveBeenCalledWith({ + nodes: [{ id: 'node-1' }], + edges: [], + viewport: { x: 10, y: 20, zoom: 1.2 }, + }) + }) + expect(mockFetchSnippetDraftWorkflow).toHaveBeenCalledWith('snippet-1') + expect(mockSnippetSetState).toHaveBeenCalledWith({ + fields: [], + }) + expect(mockSetSyncWorkflowDraftHash).toHaveBeenCalledWith('draft-hash') + expect(mockSetDraftUpdatedAt).toHaveBeenCalledWith(1_712_345_678) + expect(onSuccess).toHaveBeenCalledWith(draftWorkflow) + expect(mockSetIsSyncingWorkflowDraft).toHaveBeenNthCalledWith(1, true) + expect(mockSetIsSyncingWorkflowDraft).toHaveBeenLastCalledWith(false) + }) + + it('should silently finish when the draft workflow does not exist yet', async () => { + mockFetchSnippetDraftWorkflow.mockResolvedValueOnce(undefined) + + const { result } = renderHook(() => useSnippetRefreshDraft('snippet-1')) + + result.current.handleRefreshWorkflowDraft() + + await waitFor(() => { + expect(mockSetIsSyncingWorkflowDraft).toHaveBeenLastCalledWith(false) + }) + expect(mockFetchSnippetDraftWorkflow).toHaveBeenCalledWith('snippet-1') + expect(mockHandleUpdateWorkflowCanvas).not.toHaveBeenCalled() + expect(mockSnippetSetState).not.toHaveBeenCalled() + }) +}) diff --git a/web/app/components/snippets/hooks/use-snippet-refresh-draft.ts b/web/app/components/snippets/hooks/use-snippet-refresh-draft.ts index 33420911de..12174e731e 100644 --- a/web/app/components/snippets/hooks/use-snippet-refresh-draft.ts +++ b/web/app/components/snippets/hooks/use-snippet-refresh-draft.ts @@ -4,7 +4,7 @@ import type { SnippetWorkflow } from '@/types/snippet' import { useCallback } from 'react' import { useWorkflowUpdate } from '@/app/components/workflow/hooks' import { useWorkflowStore } from '@/app/components/workflow/store' -import { consoleClient } from '@/service/client' +import { fetchSnippetDraftWorkflow } from '@/service/use-snippet-workflows' import { useSnippetDetailStore } from '../store' export const useSnippetRefreshDraft = (snippetId: string) => { @@ -22,9 +22,10 @@ export const useSnippetRefreshDraft = (snippetId: string) => { return setIsSyncingWorkflowDraft(true) - consoleClient.snippets.draftWorkflow({ - params: { snippetId }, - }).then((response) => { + fetchSnippetDraftWorkflow(snippetId).then((response) => { + if (!response) + return + const inputFields = Array.isArray(response.input_fields) ? response.input_fields as SnippetInputField[] : []