mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 10:28:10 +08:00
Merge branch 'main' into sandboxed-agent-rebase
Made-with: Cursor # Conflicts: # api/tests/unit_tests/controllers/console/app/test_message.py # api/tests/unit_tests/controllers/console/app/test_statistic.py # api/tests/unit_tests/controllers/console/app/test_workflow_draft_variable.py # api/tests/unit_tests/controllers/console/auth/test_data_source_bearer_auth.py # api/tests/unit_tests/controllers/console/auth/test_data_source_oauth.py # api/tests/unit_tests/controllers/console/auth/test_oauth_server.py # web/app/components/header/account-setting/data-source-page/data-source-notion/operate/index.tsx # web/app/components/header/account-setting/data-source-page/data-source-website/config-firecrawl-modal.tsx # web/app/components/header/account-setting/data-source-page/data-source-website/config-jina-reader-modal.tsx # web/app/components/header/account-setting/data-source-page/data-source-website/config-watercrawl-modal.tsx # web/app/components/header/account-setting/data-source-page/panel/config-item.tsx # web/app/components/header/account-setting/data-source-page/panel/index.tsx # web/app/components/workflow/nodes/knowledge-retrieval/node.tsx # web/package.json # web/pnpm-lock.yaml
This commit is contained in:
@ -0,0 +1,224 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import type { Variable } from '../../../types'
|
||||
import type { TemplateTransformNodeType } from '../types'
|
||||
import type { PanelProps } from '@/types/workflow'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { BlockEnum, VarType } from '../../../types'
|
||||
import Node from '../node'
|
||||
import Panel from '../panel'
|
||||
import useConfig from '../use-config'
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/components/field', () => ({
|
||||
__esModule: true,
|
||||
default: ({ title, operations, children }: { title: ReactNode, operations?: ReactNode, children: ReactNode }) => (
|
||||
<div>
|
||||
<div>{title}</div>
|
||||
<div>{operations}</div>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/components/output-vars', () => ({
|
||||
__esModule: true,
|
||||
default: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
||||
VarItem: ({ name, type }: { name: string, type: string }) => <div>{`${name}:${type}`}</div>,
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/components/split', () => ({
|
||||
__esModule: true,
|
||||
default: () => <div>split</div>,
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/components/variable/var-list', () => ({
|
||||
__esModule: true,
|
||||
default: ({
|
||||
onChange,
|
||||
onVarNameChange,
|
||||
}: {
|
||||
onChange: (value: Variable[]) => void
|
||||
onVarNameChange: (oldName: string, newName: string) => void
|
||||
}) => (
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onChange([{
|
||||
variable: 'updated_input',
|
||||
value_selector: ['node-1', 'updated_input'],
|
||||
value_type: VarType.string,
|
||||
}])}
|
||||
>
|
||||
change-var-list
|
||||
</button>
|
||||
<button type="button" onClick={() => onVarNameChange('input_text', 'renamed_input')}>
|
||||
rename-var
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars', () => ({
|
||||
__esModule: true,
|
||||
default: ({
|
||||
onAddVar,
|
||||
headerRight,
|
||||
value,
|
||||
onChange,
|
||||
}: {
|
||||
onAddVar: (value: Variable) => void
|
||||
headerRight?: ReactNode
|
||||
value: string
|
||||
onChange: (value: string) => void
|
||||
}) => (
|
||||
<div>
|
||||
<div>{headerRight}</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onAddVar({
|
||||
variable: 'result_text',
|
||||
value_selector: ['node-2', 'result_text'],
|
||||
value_type: VarType.string,
|
||||
})}
|
||||
>
|
||||
add-var
|
||||
</button>
|
||||
<textarea
|
||||
aria-label="template-editor"
|
||||
value={value}
|
||||
onChange={event => onChange(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock('../use-config', () => ({
|
||||
__esModule: true,
|
||||
default: vi.fn(),
|
||||
}))
|
||||
|
||||
const mockUseConfig = vi.mocked(useConfig)
|
||||
|
||||
const createVariable = (overrides: Partial<Variable> = {}): Variable => ({
|
||||
variable: 'input_text',
|
||||
value_selector: ['node-1', 'input_text'],
|
||||
value_type: VarType.string,
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const createData = (overrides: Partial<TemplateTransformNodeType> = {}): TemplateTransformNodeType => ({
|
||||
title: 'Template Transform',
|
||||
desc: '',
|
||||
type: BlockEnum.TemplateTransform,
|
||||
variables: [createVariable()],
|
||||
template: '{{ input_text }}',
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const createConfigResult = (overrides: Partial<ReturnType<typeof useConfig>> = {}): ReturnType<typeof useConfig> => ({
|
||||
readOnly: false,
|
||||
inputs: createData(),
|
||||
availableVars: [],
|
||||
handleVarListChange: vi.fn(),
|
||||
handleVarNameChange: vi.fn(),
|
||||
handleAddVariable: vi.fn(),
|
||||
handleAddEmptyVariable: vi.fn(),
|
||||
handleCodeChange: vi.fn(),
|
||||
filterVar: () => true,
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const panelProps: PanelProps = {
|
||||
getInputVars: vi.fn(() => []),
|
||||
toVarInputs: vi.fn(() => []),
|
||||
runInputData: {},
|
||||
runInputDataRef: { current: {} },
|
||||
setRunInputData: vi.fn(),
|
||||
runResult: null,
|
||||
}
|
||||
|
||||
describe('template-transform path', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockUseConfig.mockReturnValue(createConfigResult())
|
||||
})
|
||||
|
||||
it('should render the node shell without summary content', () => {
|
||||
const { container } = render(
|
||||
<Node
|
||||
id="template-node"
|
||||
data={createData()}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(container.firstElementChild).toBeEmptyDOMElement()
|
||||
})
|
||||
|
||||
it('should wire variable list and code editor actions from the panel', async () => {
|
||||
const user = userEvent.setup()
|
||||
const handleVarListChange = vi.fn()
|
||||
const handleVarNameChange = vi.fn()
|
||||
const handleAddVariable = vi.fn()
|
||||
const handleAddEmptyVariable = vi.fn()
|
||||
const handleCodeChange = vi.fn()
|
||||
|
||||
mockUseConfig.mockReturnValueOnce(createConfigResult({
|
||||
handleVarListChange,
|
||||
handleVarNameChange,
|
||||
handleAddVariable,
|
||||
handleAddEmptyVariable,
|
||||
handleCodeChange,
|
||||
}))
|
||||
|
||||
render(
|
||||
<Panel
|
||||
id="template-node"
|
||||
data={createData()}
|
||||
panelProps={panelProps}
|
||||
/>,
|
||||
)
|
||||
|
||||
await user.click(screen.getByTestId('add-button'))
|
||||
await user.click(screen.getByRole('button', { name: 'change-var-list' }))
|
||||
await user.click(screen.getByRole('button', { name: 'rename-var' }))
|
||||
await user.click(screen.getByRole('button', { name: 'add-var' }))
|
||||
fireEvent.change(screen.getByLabelText('template-editor'), { target: { value: '{{ renamed_input }}' } })
|
||||
|
||||
expect(handleAddEmptyVariable).toHaveBeenCalled()
|
||||
expect(handleVarListChange).toHaveBeenCalledWith([
|
||||
{
|
||||
variable: 'updated_input',
|
||||
value_selector: ['node-1', 'updated_input'],
|
||||
value_type: VarType.string,
|
||||
},
|
||||
])
|
||||
expect(handleVarNameChange).toHaveBeenCalledWith('input_text', 'renamed_input')
|
||||
expect(handleAddVariable).toHaveBeenCalledWith({
|
||||
variable: 'result_text',
|
||||
value_selector: ['node-2', 'result_text'],
|
||||
value_type: VarType.string,
|
||||
})
|
||||
expect(handleCodeChange).toHaveBeenCalledWith('{{ renamed_input }}')
|
||||
expect(screen.getByText('output:string')).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: /workflow.nodes.templateTransform.codeSupportTip/i })).toHaveAttribute(
|
||||
'href',
|
||||
'https://jinja.palletsprojects.com/en/3.1.x/templates/',
|
||||
)
|
||||
})
|
||||
|
||||
it('should hide the add-variable operation when the panel is read only', () => {
|
||||
mockUseConfig.mockReturnValueOnce(createConfigResult({
|
||||
readOnly: true,
|
||||
}))
|
||||
|
||||
render(
|
||||
<Panel
|
||||
id="template-node"
|
||||
data={createData()}
|
||||
panelProps={panelProps}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.queryByTestId('add-button')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user