mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 02:43:49 +08:00
feat(web): add variable inspect for snippet
This commit is contained in:
parent
a8cdf6964c
commit
2f88da4a6d
@ -14,6 +14,24 @@ const mockSetPublishMenuOpen = vi.fn()
|
|||||||
const mockToggleInputPanel = vi.fn()
|
const mockToggleInputPanel = vi.fn()
|
||||||
const mockTogglePublishMenu = vi.fn()
|
const mockTogglePublishMenu = vi.fn()
|
||||||
const mockPublishSnippetMutateAsync = vi.fn()
|
const mockPublishSnippetMutateAsync = vi.fn()
|
||||||
|
const mockFetchInspectVars = vi.fn()
|
||||||
|
const mockInspectVarsCrud = {
|
||||||
|
hasNodeInspectVars: vi.fn(),
|
||||||
|
hasSetInspectVar: vi.fn(),
|
||||||
|
fetchInspectVarValue: vi.fn(),
|
||||||
|
editInspectVarValue: vi.fn(),
|
||||||
|
renameInspectVarName: vi.fn(),
|
||||||
|
appendNodeInspectVars: vi.fn(),
|
||||||
|
deleteInspectVar: vi.fn(),
|
||||||
|
deleteNodeInspectorVars: vi.fn(),
|
||||||
|
deleteAllInspectorVars: vi.fn(),
|
||||||
|
isInspectVarEdited: vi.fn(),
|
||||||
|
resetToLastRunVar: vi.fn(),
|
||||||
|
invalidateSysVarValues: vi.fn(),
|
||||||
|
resetConversationVar: vi.fn(),
|
||||||
|
invalidateConversationVarValues: vi.fn(),
|
||||||
|
}
|
||||||
|
let capturedHooksStore: Record<string, unknown> | undefined
|
||||||
|
|
||||||
vi.mock('@/hooks/use-breakpoints', () => ({
|
vi.mock('@/hooks/use-breakpoints', () => ({
|
||||||
default: () => 'desktop',
|
default: () => 'desktop',
|
||||||
@ -69,6 +87,16 @@ vi.mock('@/app/components/snippets/hooks/use-configs-map', () => ({
|
|||||||
}),
|
}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
vi.mock('@/app/components/workflow/hooks/use-fetch-workflow-inspect-vars', () => ({
|
||||||
|
useSetWorkflowVarsWithValue: () => ({
|
||||||
|
fetchInspectVars: mockFetchInspectVars,
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
vi.mock('@/app/components/snippets/hooks/use-inspect-vars-crud', () => ({
|
||||||
|
useInspectVarsCrud: () => mockInspectVarsCrud,
|
||||||
|
}))
|
||||||
|
|
||||||
vi.mock('@/app/components/snippets/hooks/use-nodes-sync-draft', () => ({
|
vi.mock('@/app/components/snippets/hooks/use-nodes-sync-draft', () => ({
|
||||||
useNodesSyncDraft: () => ({
|
useNodesSyncDraft: () => ({
|
||||||
doSyncWorkflowDraft: vi.fn(),
|
doSyncWorkflowDraft: vi.fn(),
|
||||||
@ -111,9 +139,19 @@ vi.mock('@/app/components/evaluation', () => ({
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@/app/components/workflow', () => ({
|
vi.mock('@/app/components/workflow', () => ({
|
||||||
WorkflowWithInnerContext: ({ children }: { children: React.ReactNode }) => (
|
WorkflowWithInnerContext: ({
|
||||||
<div data-testid="workflow-inner-context">{children}</div>
|
children,
|
||||||
),
|
hooksStore,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
hooksStore?: Record<string, unknown>
|
||||||
|
}) => {
|
||||||
|
capturedHooksStore = hooksStore
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div data-testid="workflow-inner-context">{children}</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@/app/components/snippets/components/snippet-children', () => ({
|
vi.mock('@/app/components/snippets/components/snippet-children', () => ({
|
||||||
@ -193,6 +231,7 @@ describe('SnippetMain', () => {
|
|||||||
vi.clearAllMocks()
|
vi.clearAllMocks()
|
||||||
mockSyncInputFieldsDraft.mockResolvedValue(undefined)
|
mockSyncInputFieldsDraft.mockResolvedValue(undefined)
|
||||||
mockPublishSnippetMutateAsync.mockResolvedValue(undefined)
|
mockPublishSnippetMutateAsync.mockResolvedValue(undefined)
|
||||||
|
capturedHooksStore = undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Input Fields Sync', () => {
|
describe('Input Fields Sync', () => {
|
||||||
@ -243,4 +282,26 @@ describe('SnippetMain', () => {
|
|||||||
expect(mockSetPublishMenuOpen).toHaveBeenCalledWith(false)
|
expect(mockSetPublishMenuOpen).toHaveBeenCalledWith(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Inspect Vars', () => {
|
||||||
|
it('should pass inspect vars handlers to WorkflowWithInnerContext', () => {
|
||||||
|
renderSnippetMain()
|
||||||
|
|
||||||
|
expect(capturedHooksStore?.fetchInspectVars).toBe(mockFetchInspectVars)
|
||||||
|
expect(capturedHooksStore?.hasNodeInspectVars).toBe(mockInspectVarsCrud.hasNodeInspectVars)
|
||||||
|
expect(capturedHooksStore?.hasSetInspectVar).toBe(mockInspectVarsCrud.hasSetInspectVar)
|
||||||
|
expect(capturedHooksStore?.fetchInspectVarValue).toBe(mockInspectVarsCrud.fetchInspectVarValue)
|
||||||
|
expect(capturedHooksStore?.editInspectVarValue).toBe(mockInspectVarsCrud.editInspectVarValue)
|
||||||
|
expect(capturedHooksStore?.renameInspectVarName).toBe(mockInspectVarsCrud.renameInspectVarName)
|
||||||
|
expect(capturedHooksStore?.appendNodeInspectVars).toBe(mockInspectVarsCrud.appendNodeInspectVars)
|
||||||
|
expect(capturedHooksStore?.deleteInspectVar).toBe(mockInspectVarsCrud.deleteInspectVar)
|
||||||
|
expect(capturedHooksStore?.deleteNodeInspectorVars).toBe(mockInspectVarsCrud.deleteNodeInspectorVars)
|
||||||
|
expect(capturedHooksStore?.deleteAllInspectorVars).toBe(mockInspectVarsCrud.deleteAllInspectorVars)
|
||||||
|
expect(capturedHooksStore?.isInspectVarEdited).toBe(mockInspectVarsCrud.isInspectVarEdited)
|
||||||
|
expect(capturedHooksStore?.resetToLastRunVar).toBe(mockInspectVarsCrud.resetToLastRunVar)
|
||||||
|
expect(capturedHooksStore?.invalidateSysVarValues).toBe(mockInspectVarsCrud.invalidateSysVarValues)
|
||||||
|
expect(capturedHooksStore?.resetConversationVar).toBe(mockInspectVarsCrud.resetConversationVar)
|
||||||
|
expect(capturedHooksStore?.invalidateConversationVarValues).toBe(mockInspectVarsCrud.invalidateConversationVarValues)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -21,9 +21,11 @@ import { useStore as useAppStore } from '@/app/components/app/store'
|
|||||||
import Evaluation from '@/app/components/evaluation'
|
import Evaluation from '@/app/components/evaluation'
|
||||||
import { WorkflowWithInnerContext } from '@/app/components/workflow'
|
import { WorkflowWithInnerContext } from '@/app/components/workflow'
|
||||||
import { useAvailableNodesMetaData } from '@/app/components/workflow-app/hooks'
|
import { useAvailableNodesMetaData } from '@/app/components/workflow-app/hooks'
|
||||||
|
import { useSetWorkflowVarsWithValue } from '@/app/components/workflow/hooks/use-fetch-workflow-inspect-vars'
|
||||||
import { BlockEnum } from '@/app/components/workflow/types'
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||||
import { useConfigsMap } from '../hooks/use-configs-map'
|
import { useConfigsMap } from '../hooks/use-configs-map'
|
||||||
|
import { useInspectVarsCrud } from '../hooks/use-inspect-vars-crud'
|
||||||
import { useNodesSyncDraft } from '../hooks/use-nodes-sync-draft'
|
import { useNodesSyncDraft } from '../hooks/use-nodes-sync-draft'
|
||||||
import { useSnippetRefreshDraft } from '../hooks/use-snippet-refresh-draft'
|
import { useSnippetRefreshDraft } from '../hooks/use-snippet-refresh-draft'
|
||||||
import { useSnippetDetailStore } from '../store'
|
import { useSnippetDetailStore } from '../store'
|
||||||
@ -65,6 +67,25 @@ const SnippetMain = ({
|
|||||||
} = useNodesSyncDraft(snippetId)
|
} = useNodesSyncDraft(snippetId)
|
||||||
const { handleRefreshWorkflowDraft } = useSnippetRefreshDraft(snippetId)
|
const { handleRefreshWorkflowDraft } = useSnippetRefreshDraft(snippetId)
|
||||||
const configsMap = useConfigsMap(snippetId)
|
const configsMap = useConfigsMap(snippetId)
|
||||||
|
const { fetchInspectVars } = useSetWorkflowVarsWithValue({
|
||||||
|
...configsMap,
|
||||||
|
})
|
||||||
|
const {
|
||||||
|
hasNodeInspectVars,
|
||||||
|
hasSetInspectVar,
|
||||||
|
fetchInspectVarValue,
|
||||||
|
editInspectVarValue,
|
||||||
|
renameInspectVarName,
|
||||||
|
appendNodeInspectVars,
|
||||||
|
deleteInspectVar,
|
||||||
|
deleteNodeInspectorVars,
|
||||||
|
deleteAllInspectorVars,
|
||||||
|
isInspectVarEdited,
|
||||||
|
resetToLastRunVar,
|
||||||
|
invalidateSysVarValues,
|
||||||
|
resetConversationVar,
|
||||||
|
invalidateConversationVarValues,
|
||||||
|
} = useInspectVarsCrud(snippetId)
|
||||||
const workflowAvailableNodesMetaData = useAvailableNodesMetaData()
|
const workflowAvailableNodesMetaData = useAvailableNodesMetaData()
|
||||||
const availableNodesMetaData = useMemo(() => {
|
const availableNodesMetaData = useMemo(() => {
|
||||||
const nodes = workflowAvailableNodesMetaData.nodes.filter(node =>
|
const nodes = workflowAvailableNodesMetaData.nodes.filter(node =>
|
||||||
@ -128,9 +149,45 @@ const SnippetMain = ({
|
|||||||
syncWorkflowDraftWhenPageClose,
|
syncWorkflowDraftWhenPageClose,
|
||||||
handleRefreshWorkflowDraft,
|
handleRefreshWorkflowDraft,
|
||||||
availableNodesMetaData,
|
availableNodesMetaData,
|
||||||
|
fetchInspectVars,
|
||||||
|
hasNodeInspectVars,
|
||||||
|
hasSetInspectVar,
|
||||||
|
fetchInspectVarValue,
|
||||||
|
editInspectVarValue,
|
||||||
|
renameInspectVarName,
|
||||||
|
appendNodeInspectVars,
|
||||||
|
deleteInspectVar,
|
||||||
|
deleteNodeInspectorVars,
|
||||||
|
deleteAllInspectorVars,
|
||||||
|
isInspectVarEdited,
|
||||||
|
resetToLastRunVar,
|
||||||
|
invalidateSysVarValues,
|
||||||
|
resetConversationVar,
|
||||||
|
invalidateConversationVarValues,
|
||||||
configsMap,
|
configsMap,
|
||||||
}
|
}
|
||||||
}, [availableNodesMetaData, configsMap, doSyncWorkflowDraft, handleRefreshWorkflowDraft, syncWorkflowDraftWhenPageClose])
|
}, [
|
||||||
|
appendNodeInspectVars,
|
||||||
|
availableNodesMetaData,
|
||||||
|
configsMap,
|
||||||
|
deleteAllInspectorVars,
|
||||||
|
deleteInspectVar,
|
||||||
|
deleteNodeInspectorVars,
|
||||||
|
doSyncWorkflowDraft,
|
||||||
|
editInspectVarValue,
|
||||||
|
fetchInspectVarValue,
|
||||||
|
fetchInspectVars,
|
||||||
|
handleRefreshWorkflowDraft,
|
||||||
|
hasNodeInspectVars,
|
||||||
|
hasSetInspectVar,
|
||||||
|
invalidateConversationVarValues,
|
||||||
|
invalidateSysVarValues,
|
||||||
|
isInspectVarEdited,
|
||||||
|
renameInspectVarName,
|
||||||
|
resetConversationVar,
|
||||||
|
resetToLastRunVar,
|
||||||
|
syncWorkflowDraftWhenPageClose,
|
||||||
|
])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex h-full overflow-hidden bg-background-body">
|
<div className="relative flex h-full overflow-hidden bg-background-body">
|
||||||
|
|||||||
@ -0,0 +1,95 @@
|
|||||||
|
import { renderHook } from '@testing-library/react'
|
||||||
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
|
import { useInspectVarsCrud } from '../use-inspect-vars-crud'
|
||||||
|
|
||||||
|
const mockApis = {
|
||||||
|
hasNodeInspectVars: vi.fn(),
|
||||||
|
hasSetInspectVar: vi.fn(),
|
||||||
|
fetchInspectVarValue: vi.fn(),
|
||||||
|
editInspectVarValue: vi.fn(),
|
||||||
|
renameInspectVarName: vi.fn(),
|
||||||
|
appendNodeInspectVars: vi.fn(),
|
||||||
|
deleteInspectVar: vi.fn(),
|
||||||
|
deleteNodeInspectorVars: vi.fn(),
|
||||||
|
deleteAllInspectorVars: vi.fn(),
|
||||||
|
isInspectVarEdited: vi.fn(),
|
||||||
|
resetToLastRunVar: vi.fn(),
|
||||||
|
invalidateSysVarValues: vi.fn(),
|
||||||
|
resetConversationVar: vi.fn(),
|
||||||
|
invalidateConversationVarValues: vi.fn(),
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockUseInspectVarsCrudCommon = vi.fn(() => mockApis)
|
||||||
|
vi.mock('../../../workflow/hooks/use-inspect-vars-crud-common', () => ({
|
||||||
|
useInspectVarsCrudCommon: (...args: Parameters<typeof mockUseInspectVarsCrudCommon>) => mockUseInspectVarsCrudCommon(...args),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const mockConfigsMap = {
|
||||||
|
flowId: 'snippet-123',
|
||||||
|
flowType: 'snippet',
|
||||||
|
fileSettings: {
|
||||||
|
image: { enabled: false },
|
||||||
|
fileUploadConfig: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vi.mock('../use-configs-map', () => ({
|
||||||
|
useConfigsMap: () => mockConfigsMap,
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe('useInspectVarsCrud', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Composition', () => {
|
||||||
|
it('should pass configsMap to useInspectVarsCrudCommon', () => {
|
||||||
|
renderHook(() => useInspectVarsCrud('snippet-123'))
|
||||||
|
|
||||||
|
expect(mockUseInspectVarsCrudCommon).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
flowId: 'snippet-123',
|
||||||
|
flowType: 'snippet',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return all APIs from useInspectVarsCrudCommon', () => {
|
||||||
|
const { result } = renderHook(() => useInspectVarsCrud('snippet-123'))
|
||||||
|
|
||||||
|
expect(result.current.hasNodeInspectVars).toBe(mockApis.hasNodeInspectVars)
|
||||||
|
expect(result.current.fetchInspectVarValue).toBe(mockApis.fetchInspectVarValue)
|
||||||
|
expect(result.current.editInspectVarValue).toBe(mockApis.editInspectVarValue)
|
||||||
|
expect(result.current.deleteInspectVar).toBe(mockApis.deleteInspectVar)
|
||||||
|
expect(result.current.deleteAllInspectorVars).toBe(mockApis.deleteAllInspectorVars)
|
||||||
|
expect(result.current.resetToLastRunVar).toBe(mockApis.resetToLastRunVar)
|
||||||
|
expect(result.current.resetConversationVar).toBe(mockApis.resetConversationVar)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('API Surface', () => {
|
||||||
|
it('should expose all expected API methods', () => {
|
||||||
|
const { result } = renderHook(() => useInspectVarsCrud('snippet-123'))
|
||||||
|
|
||||||
|
const expectedKeys = [
|
||||||
|
'hasNodeInspectVars',
|
||||||
|
'hasSetInspectVar',
|
||||||
|
'fetchInspectVarValue',
|
||||||
|
'editInspectVarValue',
|
||||||
|
'renameInspectVarName',
|
||||||
|
'appendNodeInspectVars',
|
||||||
|
'deleteInspectVar',
|
||||||
|
'deleteNodeInspectorVars',
|
||||||
|
'deleteAllInspectorVars',
|
||||||
|
'isInspectVarEdited',
|
||||||
|
'resetToLastRunVar',
|
||||||
|
'invalidateSysVarValues',
|
||||||
|
'resetConversationVar',
|
||||||
|
'invalidateConversationVarValues',
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const key of expectedKeys)
|
||||||
|
expect(result.current).toHaveProperty(key)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
13
web/app/components/snippets/hooks/use-inspect-vars-crud.ts
Normal file
13
web/app/components/snippets/hooks/use-inspect-vars-crud.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { useInspectVarsCrudCommon } from '../../workflow/hooks/use-inspect-vars-crud-common'
|
||||||
|
import { useConfigsMap } from './use-configs-map'
|
||||||
|
|
||||||
|
export const useInspectVarsCrud = (snippetId: string) => {
|
||||||
|
const configsMap = useConfigsMap(snippetId)
|
||||||
|
const apis = useInspectVarsCrudCommon({
|
||||||
|
...configsMap,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
...apis,
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user