mirror of
https://github.com/langgenius/dify.git
synced 2026-06-26 06:41:10 +08:00
feat(web): restore snippet selection hook tests
This commit is contained in:
parent
9f814ec267
commit
4cdffe0bbb
@ -0,0 +1,275 @@
|
||||
import type { ReactElement } from 'react'
|
||||
import type { Edge, Node } from '@/app/components/workflow/types'
|
||||
import type { SnippetCanvasData, SnippetInputField } from '@/models/snippet'
|
||||
import { act, renderHook } from '@testing-library/react'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { PipelineInputVarType } from '@/models/pipeline'
|
||||
import { useCreateSnippetFromSelection } from '../use-create-snippet-from-selection'
|
||||
|
||||
const SNIPPET_INPUT_FIELD_NODE_ID = 'start'
|
||||
const mockHandleOpenCreateSnippetDialog = vi.fn()
|
||||
const mockHandleCloseCreateSnippetDialog = vi.fn()
|
||||
const mockHandleCreateSnippet = vi.fn()
|
||||
|
||||
vi.mock('../use-create-snippet', () => ({
|
||||
useCreateSnippet: () => ({
|
||||
createSnippetMutation: {
|
||||
isPending: false,
|
||||
},
|
||||
handleCloseCreateSnippetDialog: mockHandleCloseCreateSnippetDialog,
|
||||
handleCreateSnippet: mockHandleCreateSnippet,
|
||||
handleOpenCreateSnippetDialog: mockHandleOpenCreateSnippetDialog,
|
||||
isCreateSnippetDialogOpen: true,
|
||||
isCreatingSnippet: false,
|
||||
}),
|
||||
}))
|
||||
|
||||
type DialogProps = {
|
||||
selectedGraph?: SnippetCanvasData
|
||||
inputFields?: SnippetInputField[]
|
||||
}
|
||||
|
||||
const createNode = (
|
||||
id: string,
|
||||
data: Record<string, unknown>,
|
||||
): Node => ({
|
||||
id,
|
||||
type: 'custom',
|
||||
position: { x: 0, y: 0 },
|
||||
width: 200,
|
||||
height: 100,
|
||||
data,
|
||||
} as unknown as Node)
|
||||
|
||||
describe('useCreateSnippetFromSelection', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should convert environment, conversation, and system variables into snippet input fields', () => {
|
||||
const selectedNodes = [
|
||||
createNode('llm', {
|
||||
type: BlockEnum.LLM,
|
||||
prompt: [
|
||||
'{{#env.API_KEY#}}',
|
||||
'{{#conversation.user_name#}}',
|
||||
'{{#sys.user_id#}}',
|
||||
'{{#rag.query#}}',
|
||||
'{{#source.result#}}',
|
||||
].join(' '),
|
||||
model_selector: ['env', 'MODEL_NAME'],
|
||||
}),
|
||||
]
|
||||
const edges: Edge[] = []
|
||||
const onClose = vi.fn()
|
||||
|
||||
const { result } = renderHook(() => useCreateSnippetFromSelection({
|
||||
edges,
|
||||
selectedNodes,
|
||||
onClose,
|
||||
}))
|
||||
|
||||
act(() => {
|
||||
result.current.handleOpenCreateSnippet()
|
||||
})
|
||||
|
||||
const dialogProps = (result.current.createSnippetDialog as ReactElement<DialogProps>).props
|
||||
|
||||
expect(dialogProps.inputFields).toEqual([
|
||||
{
|
||||
label: 'API_KEY',
|
||||
variable: 'API_KEY',
|
||||
type: PipelineInputVarType.textInput,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'user_name',
|
||||
variable: 'user_name',
|
||||
type: PipelineInputVarType.textInput,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'user_id',
|
||||
variable: 'user_id',
|
||||
type: PipelineInputVarType.textInput,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'result',
|
||||
variable: 'result',
|
||||
type: PipelineInputVarType.textInput,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'MODEL_NAME',
|
||||
variable: 'MODEL_NAME',
|
||||
type: PipelineInputVarType.textInput,
|
||||
required: true,
|
||||
},
|
||||
])
|
||||
const nodeData = dialogProps.selectedGraph?.nodes[0]?.data as Record<string, unknown> | undefined
|
||||
|
||||
expect(nodeData?.prompt).toBe([
|
||||
`{{#${SNIPPET_INPUT_FIELD_NODE_ID}.API_KEY#}}`,
|
||||
`{{#${SNIPPET_INPUT_FIELD_NODE_ID}.user_name#}}`,
|
||||
`{{#${SNIPPET_INPUT_FIELD_NODE_ID}.user_id#}}`,
|
||||
'{{#rag.query#}}',
|
||||
`{{#${SNIPPET_INPUT_FIELD_NODE_ID}.result#}}`,
|
||||
].join(' '))
|
||||
expect(nodeData?.model_selector).toEqual([
|
||||
SNIPPET_INPUT_FIELD_NODE_ID,
|
||||
'MODEL_NAME',
|
||||
])
|
||||
expect(onClose).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should convert system variables used by if-else and variable aggregator nodes', () => {
|
||||
const selectedNodes = [
|
||||
createNode('llm', {
|
||||
type: BlockEnum.LLM,
|
||||
title: 'LLM',
|
||||
}),
|
||||
createNode('if-else', {
|
||||
type: BlockEnum.IfElse,
|
||||
cases: [{
|
||||
case_id: 'case-1',
|
||||
conditions: [{
|
||||
id: 'condition-1',
|
||||
variable_selector: ['sys', 'query'],
|
||||
comparison_operator: 'contains',
|
||||
value: 'hello',
|
||||
}],
|
||||
}],
|
||||
}),
|
||||
createNode('variable-aggregator', {
|
||||
type: BlockEnum.VariableAggregator,
|
||||
variables: [
|
||||
['sys', 'files'],
|
||||
['llm', 'text'],
|
||||
],
|
||||
advanced_settings: {
|
||||
group_enabled: true,
|
||||
groups: [{
|
||||
groupId: 'group-1',
|
||||
group_name: 'Group1',
|
||||
variables: [
|
||||
['sys', 'workflow_id'],
|
||||
],
|
||||
}],
|
||||
},
|
||||
}),
|
||||
]
|
||||
const onClose = vi.fn()
|
||||
|
||||
const { result } = renderHook(() => useCreateSnippetFromSelection({
|
||||
edges: [],
|
||||
selectedNodes,
|
||||
onClose,
|
||||
}))
|
||||
|
||||
act(() => {
|
||||
result.current.handleOpenCreateSnippet()
|
||||
})
|
||||
|
||||
const dialogProps = (result.current.createSnippetDialog as ReactElement<DialogProps>).props
|
||||
|
||||
expect(dialogProps.inputFields).toEqual([
|
||||
{
|
||||
label: 'query',
|
||||
variable: 'query',
|
||||
type: PipelineInputVarType.textInput,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'files',
|
||||
variable: 'files',
|
||||
type: PipelineInputVarType.multiFiles,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'workflow_id',
|
||||
variable: 'workflow_id',
|
||||
type: PipelineInputVarType.textInput,
|
||||
required: true,
|
||||
},
|
||||
])
|
||||
|
||||
const ifElseNode = dialogProps.selectedGraph?.nodes.find(node => node.id === 'if-else')
|
||||
const aggregatorNode = dialogProps.selectedGraph?.nodes.find(node => node.id === 'variable-aggregator')
|
||||
const ifElseData = ifElseNode?.data as Record<string, unknown>
|
||||
const aggregatorData = aggregatorNode?.data as {
|
||||
variables?: string[][]
|
||||
advanced_settings?: { groups?: Array<{ variables?: string[][] }> }
|
||||
}
|
||||
|
||||
expect(ifElseData.cases).toEqual([{
|
||||
case_id: 'case-1',
|
||||
conditions: [{
|
||||
id: 'condition-1',
|
||||
variable_selector: [SNIPPET_INPUT_FIELD_NODE_ID, 'query'],
|
||||
comparison_operator: 'contains',
|
||||
value: 'hello',
|
||||
}],
|
||||
}])
|
||||
expect(aggregatorData.variables).toEqual([
|
||||
[SNIPPET_INPUT_FIELD_NODE_ID, 'files'],
|
||||
['llm', 'text'],
|
||||
])
|
||||
expect(aggregatorData.advanced_settings?.groups?.[0]?.variables).toEqual([
|
||||
[SNIPPET_INPUT_FIELD_NODE_ID, 'workflow_id'],
|
||||
])
|
||||
})
|
||||
|
||||
it('should keep #context# prompt placeholders when creating a snippet from workflow selection', () => {
|
||||
const selectedNodes = [
|
||||
createNode('llm', {
|
||||
type: BlockEnum.LLM,
|
||||
context: {
|
||||
enabled: true,
|
||||
variable_selector: ['code', 'result'],
|
||||
},
|
||||
prompt: '{{#context#}} {{#code.summary#}}',
|
||||
}),
|
||||
]
|
||||
const onClose = vi.fn()
|
||||
|
||||
const { result } = renderHook(() => useCreateSnippetFromSelection({
|
||||
edges: [],
|
||||
selectedNodes,
|
||||
onClose,
|
||||
}))
|
||||
|
||||
act(() => {
|
||||
result.current.handleOpenCreateSnippet()
|
||||
})
|
||||
|
||||
const dialogProps = (result.current.createSnippetDialog as ReactElement<DialogProps>).props
|
||||
const nodeData = dialogProps.selectedGraph?.nodes[0]?.data as {
|
||||
context?: {
|
||||
enabled: boolean
|
||||
variable_selector: string[]
|
||||
}
|
||||
prompt?: string
|
||||
}
|
||||
|
||||
expect(dialogProps.inputFields).toEqual([
|
||||
{
|
||||
label: 'result',
|
||||
variable: 'result',
|
||||
type: PipelineInputVarType.textInput,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'summary',
|
||||
variable: 'summary',
|
||||
type: PipelineInputVarType.textInput,
|
||||
required: true,
|
||||
},
|
||||
])
|
||||
expect(nodeData.context).toEqual({
|
||||
enabled: true,
|
||||
variable_selector: [SNIPPET_INPUT_FIELD_NODE_ID, 'result'],
|
||||
})
|
||||
expect(nodeData.prompt).toBe(`{{#context#}} {{#${SNIPPET_INPUT_FIELD_NODE_ID}.summary#}}`)
|
||||
})
|
||||
})
|
||||
Loading…
Reference in New Issue
Block a user