fix: web tests

This commit is contained in:
hjlarry 2026-04-11 09:17:00 +08:00
parent 7520d65a7e
commit 341fdc8201
11 changed files with 128 additions and 29 deletions

View File

@ -69,6 +69,7 @@ vi.mock('lexical', async (importOriginal) => {
getChildren: () => mocks.rootLines.map(line => ({
getTextContent: () => line,
})),
getAllTextNodes: () => [],
}),
TextNode: class TextNode {
__text: string

View File

@ -21,6 +21,16 @@ vi.mock('@/context/dataset-detail', () => ({
selector({ dataset: { doc_form: ChunkingMode.text } }),
}))
vi.mock('@/app/components/datasets/metadata/hooks/use-batch-edit-document-metadata', () => ({
default: () => ({
isShowEditModal: false,
showEditModal: vi.fn(),
hideEditModal: vi.fn(),
originalList: [],
handleSave: vi.fn(),
}),
}))
const createTestQueryClient = () => new QueryClient({
defaultOptions: {
queries: { retry: false, gcTime: 0 },

View File

@ -8,6 +8,7 @@ const mockUseStore = vi.hoisted(() => vi.fn())
const mockUseNodesInteractions = vi.hoisted(() => vi.fn())
const mockUsePanelInteractions = vi.hoisted(() => vi.fn())
const mockUseWorkflowStartRun = vi.hoisted(() => vi.fn())
const mockUseWorkflowMoveMode = vi.hoisted(() => vi.fn())
const mockUseOperator = vi.hoisted(() => vi.fn())
const mockUseDSL = vi.hoisted(() => vi.fn())
@ -23,6 +24,9 @@ vi.mock('@/app/components/workflow/store', () => ({
useStore: (selector: (state: {
panelMenu?: { left: number, top: number }
clipboardElements: unknown[]
pendingComment: null | { pageX: number, pageY: number, elementX: number, elementY: number }
setCommentPlacing: (placing: boolean) => void
setCommentQuickAdd: (quickAdd: boolean) => void
setShowImportDSLModal: (visible: boolean) => void
}) => unknown) => mockUseStore(selector),
}))
@ -31,6 +35,7 @@ vi.mock('@/app/components/workflow/hooks', () => ({
useNodesInteractions: () => mockUseNodesInteractions(),
usePanelInteractions: () => mockUsePanelInteractions(),
useWorkflowStartRun: () => mockUseWorkflowStartRun(),
useWorkflowMoveMode: () => mockUseWorkflowMoveMode(),
useDSL: () => mockUseDSL(),
}))
@ -62,14 +67,18 @@ describe('PanelContextmenu', () => {
const mockHandleAddNote = vi.fn()
const mockExportCheck = vi.fn()
const mockSetShowImportDSLModal = vi.fn()
const mockSetCommentPlacing = vi.fn()
const mockSetCommentQuickAdd = vi.fn()
let panelMenu: { left: number, top: number } | undefined
let clipboardElements: unknown[]
let pendingComment: null | { pageX: number, pageY: number, elementX: number, elementY: number }
let clickAwayHandler: (() => void) | undefined
beforeEach(() => {
vi.clearAllMocks()
panelMenu = undefined
clipboardElements = []
pendingComment = null
clickAwayHandler = undefined
mockUseClickAway.mockImplementation((handler: () => void) => {
@ -81,10 +90,16 @@ describe('PanelContextmenu', () => {
mockUseStore.mockImplementation((selector: (state: {
panelMenu?: { left: number, top: number }
clipboardElements: unknown[]
pendingComment: null | { pageX: number, pageY: number, elementX: number, elementY: number }
setCommentPlacing: (placing: boolean) => void
setCommentQuickAdd: (quickAdd: boolean) => void
setShowImportDSLModal: (visible: boolean) => void
}) => unknown) => selector({
panelMenu,
clipboardElements,
pendingComment,
setCommentPlacing: mockSetCommentPlacing,
setCommentQuickAdd: mockSetCommentQuickAdd,
setShowImportDSLModal: mockSetShowImportDSLModal,
}))
mockUseNodesInteractions.mockReturnValue({
@ -96,6 +111,9 @@ describe('PanelContextmenu', () => {
mockUseWorkflowStartRun.mockReturnValue({
handleStartWorkflowRun: mockHandleStartWorkflowRun,
})
mockUseWorkflowMoveMode.mockReturnValue({
isCommentModeAvailable: false,
})
mockUseOperator.mockReturnValue({
handleAddNote: mockHandleAddNote,
})

View File

@ -2,13 +2,10 @@ import { act, fireEvent, render, screen } from '@testing-library/react'
import UndoRedo from '../undo-redo'
const mockUnsubscribe = vi.fn()
const mockCanUndo = vi.fn()
const mockCanRedo = vi.fn()
const mockOnUndoRedoStateChange = vi.fn()
const mockHandleUndo = vi.fn()
const mockHandleRedo = vi.fn()
let latestUndoRedoListener: ((state: { canUndo: boolean, canRedo: boolean }) => void) | undefined
let latestTemporalListener: ((state: { pastStates: unknown[], futureStates: unknown[] }) => void) | undefined
let mockNodesReadOnly = false
vi.mock('@/app/components/workflow/header/view-workflow-history', () => ({
@ -23,22 +20,19 @@ vi.mock('@/app/components/workflow/hooks', () => ({
vi.mock('@/app/components/workflow/workflow-history-store', () => ({
useWorkflowHistoryStore: () => ({
store: {
temporal: {
subscribe: (listener: (state: { pastStates: unknown[], futureStates: unknown[] }) => void) => {
latestTemporalListener = listener
return mockUnsubscribe
},
},
},
shortcutsEnabled: true,
setShortcutsEnabled: vi.fn(),
}),
}))
vi.mock('@/app/components/workflow/collaboration/core/collaboration-manager', () => ({
collaborationManager: {
canUndo: () => mockCanUndo(),
canRedo: () => mockCanRedo(),
onUndoRedoStateChange: (listener: (state: { canUndo: boolean, canRedo: boolean }) => void) => {
latestUndoRedoListener = listener
return mockOnUndoRedoStateChange(listener)
},
},
}))
vi.mock('@/app/components/base/divider', () => ({
default: () => <div data-testid="divider" />,
}))
@ -51,19 +45,16 @@ describe('UndoRedo', () => {
beforeEach(() => {
vi.clearAllMocks()
mockNodesReadOnly = false
latestUndoRedoListener = undefined
mockCanUndo.mockReturnValue(false)
mockCanRedo.mockReturnValue(false)
mockOnUndoRedoStateChange.mockReturnValue(mockUnsubscribe)
latestTemporalListener = undefined
})
it('enables undo and redo when history exists and triggers the callbacks', () => {
render(<UndoRedo handleRedo={mockHandleRedo} handleUndo={mockHandleUndo} />)
act(() => {
latestUndoRedoListener?.({
canUndo: true,
canRedo: true,
latestTemporalListener?.({
pastStates: [{}],
futureStates: [{}],
})
})
@ -95,9 +86,9 @@ describe('UndoRedo', () => {
const redoButton = screen.getByRole('button', { name: 'workflow.common.redo' })
act(() => {
latestUndoRedoListener?.({
canUndo: true,
canRedo: true,
latestTemporalListener?.({
pastStates: [{}],
futureStates: [{}],
})
})

View File

@ -32,6 +32,18 @@ vi.mock('@/service/use-triggers', () => ({
useTriggerPluginDynamicOptions: () => mockTriggerDynamicOptionsState,
}))
vi.mock('@/app/components/workflow/hooks', () => ({
useIsChatMode: () => false,
useWorkflow: () => ({
getTreeLeafNodes: () => [],
getNodeById: () => undefined,
getBeforeNodesInSameBranchIncludeParent: () => [],
}),
useWorkflowVariables: () => ({
getNodeAvailableVars: () => [],
}),
}))
vi.mock('@/app/components/plugins/plugin-detail-panel/app-selector', () => ({
default: ({ onSelect }: { onSelect: (value: string) => void }) => (
<button onClick={() => onSelect('app-1')}>app-selector</button>

View File

@ -6,6 +6,18 @@ import { renderWorkflowFlowComponent } from '@/app/components/workflow/__tests__
import { VarKindType } from '../../types'
import FormInputItem from '../form-input-item'
vi.mock('@/app/components/workflow/hooks', () => ({
useIsChatMode: () => false,
useWorkflow: () => ({
getTreeLeafNodes: () => [],
getNodeById: () => undefined,
getBeforeNodesInSameBranchIncludeParent: () => [],
}),
useWorkflowVariables: () => ({
getNodeAvailableVars: () => [],
}),
}))
const createSchema = (
overrides: Partial<CredentialFormSchema & {
_type?: FormTypeEnum

View File

@ -20,6 +20,19 @@ vi.mock('@/service/use-plugins', () => ({
}),
}))
vi.mock('@/app/components/workflow/hooks', () => ({
useIsChatMode: () => false,
useWorkflow: () => ({
getTreeLeafNodes: () => [],
getNodeById: () => undefined,
getBeforeNodesInSameBranchIncludeParent: () => [],
}),
useWorkflowVariables: () => ({
getNodeAvailableVars: () => [],
getCurrentVariableType: () => undefined,
}),
}))
vi.mock('../var-reference-popup', () => ({
default: ({
onChange,

View File

@ -6,6 +6,19 @@ import { renderWorkflowFlowComponent } from '@/app/components/workflow/__tests__
import { BlockEnum, InputVarType, VarType } from '@/app/components/workflow/types'
import VarReferencePicker from '../var-reference-picker'
vi.mock('@/app/components/workflow/hooks', () => ({
useIsChatMode: () => false,
useWorkflow: () => ({
getTreeLeafNodes: () => [],
getNodeById: () => undefined,
getBeforeNodesInSameBranchIncludeParent: () => [],
}),
useWorkflowVariables: () => ({
getNodeAvailableVars: () => [],
getCurrentVariableType: () => undefined,
}),
}))
describe('VarReferencePicker', () => {
const startNode = createStartNode({
id: 'start-node',

View File

@ -7,6 +7,19 @@ import { BlockEnum, VarType } from '@/app/components/workflow/types'
import { AssignerNodeInputType, WriteMode } from '../../../types'
import VarList from '../index'
vi.mock('@/app/components/workflow/hooks', () => ({
useIsChatMode: () => false,
useWorkflow: () => ({
getTreeLeafNodes: () => [],
getNodeById: () => undefined,
getBeforeNodesInSameBranchIncludeParent: () => [],
}),
useWorkflowVariables: () => ({
getNodeAvailableVars: () => [],
getCurrentVariableType: () => undefined,
}),
}))
const sourceNode = createNode({
id: 'node-a',
data: {

View File

@ -19,6 +19,8 @@ const {
mockFindUsedVarNodes,
mockUpdateNodeVars,
mockVariableTriggerState,
mockUpdateEnvironmentVariables,
mockGetSocket,
} = vi.hoisted(() => ({
mockDoSyncWorkflowDraft: vi.fn(() => Promise.resolve()),
mockGetNodes: vi.fn<() => MockWorkflowNode[]>(() => []),
@ -34,6 +36,8 @@ const {
mockVariableTriggerState: {
savePayload: undefined as EnvironmentVariable | undefined,
},
mockUpdateEnvironmentVariables: vi.fn(() => Promise.resolve({})),
mockGetSocket: vi.fn(() => null),
}))
vi.mock('@/app/components/workflow/hooks/use-nodes-sync-draft', () => ({
@ -56,6 +60,16 @@ vi.mock('@/app/components/workflow/nodes/_base/components/variable/utils', () =>
updateNodeVars: mockUpdateNodeVars,
}))
vi.mock('@/service/workflow', () => ({
updateEnvironmentVariables: (payload: { appId: string, environmentVariables: EnvironmentVariable[] }) => mockUpdateEnvironmentVariables(payload),
}))
vi.mock('@/app/components/workflow/collaboration/core/websocket-manager', () => ({
webSocketClient: {
getSocket: (appId: string) => mockGetSocket(appId),
},
}))
vi.mock('@/app/components/workflow/nodes/_base/components/remove-effect-var-confirm', () => ({
default: ({
isShow,
@ -171,6 +185,8 @@ describe('EnvPanel container', () => {
mockGetNodes.mockReturnValue([])
mockFindUsedVarNodes.mockReturnValue([])
mockVariableTriggerState.savePayload = undefined
mockUpdateEnvironmentVariables.mockResolvedValue({})
mockGetSocket.mockReturnValue(null)
})
it('should close the panel from the header action', async () => {

View File

@ -8,15 +8,15 @@ describe('createWorkflowSlice', () => {
localStorage.clear()
})
it('defaults to hand mode until a persisted pointer mode is present', () => {
it('defaults to pointer mode and restores persisted control mode', () => {
const defaultStore = createStore(createWorkflowSlice)
expect(defaultStore.getState().controlMode).toBe('hand')
expect(defaultStore.getState().controlMode).toBe('pointer')
localStorage.setItem('workflow-operation-mode', 'pointer')
localStorage.setItem('workflow-operation-mode', 'hand')
const persistedStore = createStore(createWorkflowSlice)
expect(persistedStore.getState().controlMode).toBe('pointer')
expect(persistedStore.getState().controlMode).toBe('hand')
})
it('persists control mode updates and stores run state payloads', () => {