mirror of
https://github.com/langgenius/dify.git
synced 2026-04-21 03:07:39 +08:00
test(workflow): add unit tests for workflow components (#33910)
Co-authored-by: CodingOnStar <hanxujiang@dify.com>
This commit is contained in:
138
web/app/components/workflow/simple-node/__tests__/index.spec.tsx
Normal file
138
web/app/components/workflow/simple-node/__tests__/index.spec.tsx
Normal file
@ -0,0 +1,138 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { BlockEnum, NodeRunningStatus } from '../../types'
|
||||
import SimpleNode from '../index'
|
||||
|
||||
let mockNodesReadOnly = false
|
||||
|
||||
vi.mock('@/app/components/workflow/hooks', () => ({
|
||||
useNodesReadOnly: () => ({
|
||||
nodesReadOnly: mockNodesReadOnly,
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/block-icon', () => ({
|
||||
__esModule: true,
|
||||
default: ({ type }: { type: BlockEnum }) => <div>{`block-icon:${type}`}</div>,
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/components/node-control', () => ({
|
||||
__esModule: true,
|
||||
default: ({ id }: { id: string }) => <div>{`node-control:${id}`}</div>,
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/components/node-handle', () => ({
|
||||
NodeTargetHandle: ({ handleId }: { handleId: string }) => <div>{`node-handle:${handleId}`}</div>,
|
||||
}))
|
||||
|
||||
const createData = (overrides: Record<string, unknown> = {}) => ({
|
||||
title: 'Answer',
|
||||
desc: '',
|
||||
type: BlockEnum.Answer,
|
||||
...overrides,
|
||||
})
|
||||
|
||||
describe('simple-node', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockNodesReadOnly = false
|
||||
})
|
||||
|
||||
it('should render the block shell, target handle, and node control by default', () => {
|
||||
render(
|
||||
<SimpleNode
|
||||
id="simple-node"
|
||||
data={createData()}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('Answer')).toBeInTheDocument()
|
||||
expect(screen.getByText('block-icon:answer')).toBeInTheDocument()
|
||||
expect(screen.getByText('node-handle:target')).toBeInTheDocument()
|
||||
expect(screen.getByText('node-control:simple-node')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show the running state border and spinner', () => {
|
||||
const { container } = render(
|
||||
<SimpleNode
|
||||
id="simple-node"
|
||||
data={createData({
|
||||
_runningStatus: NodeRunningStatus.Running,
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(container.querySelector('.text-text-accent')).not.toBeNull()
|
||||
expect(container.innerHTML).toContain('!border-state-accent-solid')
|
||||
expect(screen.queryByText('node-control:simple-node')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show success, failed, and exception status indicators', () => {
|
||||
const { container, rerender } = render(
|
||||
<SimpleNode
|
||||
id="simple-node"
|
||||
data={createData({
|
||||
_runningStatus: NodeRunningStatus.Succeeded,
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(container.querySelector('.text-text-success')).not.toBeNull()
|
||||
expect(container.innerHTML).toContain('!border-state-success-solid')
|
||||
|
||||
rerender(
|
||||
<SimpleNode
|
||||
id="simple-node"
|
||||
data={createData({
|
||||
_runningStatus: NodeRunningStatus.Failed,
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(container.querySelector('.text-text-destructive')).not.toBeNull()
|
||||
expect(container.innerHTML).toContain('!border-state-destructive-solid')
|
||||
|
||||
rerender(
|
||||
<SimpleNode
|
||||
id="simple-node"
|
||||
data={createData({
|
||||
_runningStatus: NodeRunningStatus.Exception,
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(container.querySelector('.text-text-warning-secondary')).not.toBeNull()
|
||||
expect(container.innerHTML).toContain('!border-state-warning-solid')
|
||||
})
|
||||
|
||||
it('should hide handles and controls for candidate or read-only nodes and show selected waiting styles', () => {
|
||||
mockNodesReadOnly = true
|
||||
const { container } = render(
|
||||
<SimpleNode
|
||||
id="simple-node"
|
||||
data={createData({
|
||||
selected: true,
|
||||
_waitingRun: true,
|
||||
_isCandidate: true,
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.queryByText('node-handle:target')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('node-control:simple-node')).not.toBeInTheDocument()
|
||||
expect(container.querySelector('.border-components-option-card-option-selected-border')).not.toBeNull()
|
||||
expect(container.querySelector('.opacity-70')).not.toBeNull()
|
||||
})
|
||||
|
||||
it('should show a spinner when a single run is still running', () => {
|
||||
const { container } = render(
|
||||
<SimpleNode
|
||||
id="simple-node"
|
||||
data={createData({
|
||||
_singleRunningStatus: NodeRunningStatus.Running,
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(container.querySelector('.animate-spin')).not.toBeNull()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user