From 6f30ecd7179a5fda7c6e1f384e15e97ba2e91d98 Mon Sep 17 00:00:00 2001 From: hjlarry Date: Mon, 13 Apr 2026 11:43:47 +0800 Subject: [PATCH] fix: web unittests --- .../apps/app-list-browsing-flow.test.tsx | 4 ++ web/__tests__/apps/create-app-flow.test.tsx | 4 ++ .../__tests__/use-dataset-card-state.spec.ts | 4 +- .../extract-parameter/__tests__/list.spec.tsx | 38 ++++++++++++++----- .../__tests__/update.spec.tsx | 8 +++- .../components/__tests__/integration.spec.tsx | 8 +--- .../__tests__/parameter-table.spec.tsx | 30 ++++++++++----- .../variable-inspect/__tests__/panel.spec.tsx | 20 +++++----- 8 files changed, 77 insertions(+), 39 deletions(-) diff --git a/web/__tests__/apps/app-list-browsing-flow.test.tsx b/web/__tests__/apps/app-list-browsing-flow.test.tsx index 1be7e56086..a5ed79a7bd 100644 --- a/web/__tests__/apps/app-list-browsing-flow.test.tsx +++ b/web/__tests__/apps/app-list-browsing-flow.test.tsx @@ -93,6 +93,10 @@ vi.mock('@/service/tag', () => ({ fetchTagList: vi.fn().mockResolvedValue([]), })) +vi.mock('@/service/apps', () => ({ + fetchWorkflowOnlineUsers: vi.fn().mockResolvedValue({}), +})) + vi.mock('@/service/use-apps', () => ({ useInfiniteAppList: () => ({ data: { pages: mockPages }, diff --git a/web/__tests__/apps/create-app-flow.test.tsx b/web/__tests__/apps/create-app-flow.test.tsx index bc1f7a3a06..9abc870ecf 100644 --- a/web/__tests__/apps/create-app-flow.test.tsx +++ b/web/__tests__/apps/create-app-flow.test.tsx @@ -80,6 +80,10 @@ vi.mock('@/service/tag', () => ({ fetchTagList: vi.fn().mockResolvedValue([]), })) +vi.mock('@/service/apps', () => ({ + fetchWorkflowOnlineUsers: vi.fn().mockResolvedValue({}), +})) + vi.mock('@/service/use-apps', () => ({ useInfiniteAppList: () => ({ data: { pages: mockPages }, diff --git a/web/app/components/datasets/list/dataset-card/hooks/__tests__/use-dataset-card-state.spec.ts b/web/app/components/datasets/list/dataset-card/hooks/__tests__/use-dataset-card-state.spec.ts index f29d85b460..935f1329d1 100644 --- a/web/app/components/datasets/list/dataset-card/hooks/__tests__/use-dataset-card-state.spec.ts +++ b/web/app/components/datasets/list/dataset-card/hooks/__tests__/use-dataset-card-state.spec.ts @@ -157,7 +157,7 @@ describe('useDatasetCardState', () => { expect(result.current.modalState.showRenameModal).toBe(false) }) - it('should close confirm delete modal when closeConfirmDelete is called', () => { + it('should close confirm delete modal when closeConfirmDelete is called', async () => { const dataset = createMockDataset() const { result } = renderHook(() => useDatasetCardState({ dataset, onSuccess: vi.fn() }), @@ -168,7 +168,7 @@ describe('useDatasetCardState', () => { result.current.detectIsUsedByApp() }) - waitFor(() => { + await waitFor(() => { expect(result.current.modalState.showConfirmDelete).toBe(true) }) diff --git a/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/__tests__/list.spec.tsx b/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/__tests__/list.spec.tsx index 6e1391480f..3c62f113bb 100644 --- a/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/__tests__/list.spec.tsx +++ b/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/__tests__/list.spec.tsx @@ -1,4 +1,4 @@ -import { fireEvent, render, screen, waitFor } from '@testing-library/react' +import { fireEvent, render, screen, waitFor, within } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { ParamType } from '../../../types' import List from '../list' @@ -32,7 +32,7 @@ describe('parameter-extractor/extract-parameter/list', () => { it('edits and deletes parameters through the real item and modal flow', async () => { const user = userEvent.setup() const handleChange = vi.fn() - const { container, rerender } = render( + const { rerender } = render( { />, ) - const editAndDeleteButtons = container.querySelectorAll('.cursor-pointer.rounded-md.p-1') + const cityLabel = screen.getByText('city') + const cityRow = cityLabel.closest('.group.relative') + if (!cityRow) + throw new Error('Failed to locate city row') + const editAndDeleteButtons = cityRow.querySelectorAll('.cursor-pointer.rounded-md.p-1') fireEvent.click(editAndDeleteButtons[0] as HTMLElement) - fireEvent.change(screen.getByDisplayValue('city'), { target: { value: 'city_name' } }) - fireEvent.change(screen.getByDisplayValue('City name'), { target: { value: 'Updated city description' } }) - await user.click(screen.getByRole('button', { name: 'common.operation.save' })) + + await screen.findByRole('dialog') + const dialog = screen.getAllByRole('dialog').at(-1)! + fireEvent.change( + within(dialog).getByPlaceholderText('workflow.nodes.parameterExtractor.addExtractParameterContent.namePlaceholder'), + { target: { value: 'cityname' } }, + ) + fireEvent.change( + within(dialog).getByPlaceholderText('workflow.nodes.parameterExtractor.addExtractParameterContent.descriptionPlaceholder'), + { target: { value: 'Updated city description' } }, + ) + fireEvent.click(within(dialog).getByRole('button', { name: 'common.operation.save' })) await waitFor(() => { - expect(handleChange.mock.lastCall).toEqual([[{ - name: 'city_name', + expect(handleChange).toHaveBeenCalled() + expect(handleChange.mock.lastCall?.[0]).toEqual([{ + name: 'cityname', type: ParamType.string, description: 'Updated city description', required: false, - }], undefined]) + }]) }) handleChange.mockClear() @@ -65,7 +79,11 @@ describe('parameter-extractor/extract-parameter/list', () => { />, ) - const deleteButtons = container.querySelectorAll('.cursor-pointer.rounded-md.p-1') + const budgetLabel = screen.getByText('budget') + const budgetRow = budgetLabel.closest('.group.relative') + if (!budgetRow) + throw new Error('Failed to locate budget row') + const deleteButtons = budgetRow.querySelectorAll('.cursor-pointer.rounded-md.p-1') fireEvent.click(deleteButtons[1] as HTMLElement) expect(handleChange).toHaveBeenCalledWith([]) diff --git a/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/__tests__/update.spec.tsx b/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/__tests__/update.spec.tsx index 3d17557c1d..7e6c7f22dc 100644 --- a/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/__tests__/update.spec.tsx +++ b/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/__tests__/update.spec.tsx @@ -123,7 +123,9 @@ describe('parameter-extractor/extract-parameter/update', () => { await user.click(screen.getByRole('button', { name: 'common.operation.save' })) expect(handleSave).not.toHaveBeenCalled() - expect(mockToast.error).toHaveBeenCalled() + await waitFor(() => { + expect(mockToast.error).toHaveBeenCalled() + }) }) it('requires options before saving a select parameter', async () => { @@ -145,6 +147,8 @@ describe('parameter-extractor/extract-parameter/update', () => { await user.click(screen.getByRole('button', { name: 'common.operation.save' })) expect(handleSave).not.toHaveBeenCalled() - expect(mockToast.error).toHaveBeenCalled() + await waitFor(() => { + expect(mockToast.error).toHaveBeenCalled() + }) }) }) diff --git a/web/app/components/workflow/nodes/trigger-schedule/components/__tests__/integration.spec.tsx b/web/app/components/workflow/nodes/trigger-schedule/components/__tests__/integration.spec.tsx index 1007c44963..95ce746037 100644 --- a/web/app/components/workflow/nodes/trigger-schedule/components/__tests__/integration.spec.tsx +++ b/web/app/components/workflow/nodes/trigger-schedule/components/__tests__/integration.spec.tsx @@ -45,12 +45,8 @@ describe('trigger-schedule components', () => { const trigger = screen.getByRole('button', { name: 'workflow.nodes.triggerSchedule.frequency.daily' }) await user.click(trigger) - - await waitFor(() => { - expect(trigger).toHaveAttribute('aria-expanded', 'true') - }) - - await user.click(await screen.findByText('workflow.nodes.triggerSchedule.frequency.weekly')) + await user.keyboard('{ArrowDown}') + await user.keyboard('{Enter}') await waitFor(() => { expect(onChange).toHaveBeenCalledWith('weekly') diff --git a/web/app/components/workflow/nodes/trigger-webhook/components/__tests__/parameter-table.spec.tsx b/web/app/components/workflow/nodes/trigger-webhook/components/__tests__/parameter-table.spec.tsx index f9fde7bb5f..6ef395642a 100644 --- a/web/app/components/workflow/nodes/trigger-webhook/components/__tests__/parameter-table.spec.tsx +++ b/web/app/components/workflow/nodes/trigger-webhook/components/__tests__/parameter-table.spec.tsx @@ -1,17 +1,26 @@ import type { WebhookParameter } from '../../types' -import { act, fireEvent, render, screen, waitFor } from '@testing-library/react' +import { fireEvent, render, screen, waitFor, within } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { VarType } from '@/app/components/workflow/types' import ParameterTable from '../parameter-table' -const selectOption = async (triggerName: string, optionName: string) => { - await act(async () => { - fireEvent.click(screen.getAllByRole('button', { name: triggerName })[0]) - }) +const selectOption = async ({ + rowKey, + triggerName, +}: { + rowKey: string + triggerName: string +}) => { + const user = userEvent.setup() + const rowInput = screen.getByDisplayValue(rowKey) + const row = rowInput.closest('[style*="min-height"]') + if (!row) + throw new Error('Failed to locate parameter table row') - await act(async () => { - fireEvent.click(await screen.findByRole('option', { name: optionName })) - }) + const selectButton = within(row).getByRole('button', { name: triggerName }) + await user.click(selectButton) + await user.keyboard('{ArrowDown}') + await user.keyboard('{Enter}') } describe('trigger-webhook/parameter-table', () => { @@ -33,7 +42,10 @@ describe('trigger-webhook/parameter-table', () => { />, ) - await selectOption('String', 'Number') + await selectOption({ + rowKey: 'page', + triggerName: 'String', + }) await waitFor(() => { expect(onChange).toHaveBeenCalledWith([{ diff --git a/web/app/components/workflow/variable-inspect/__tests__/panel.spec.tsx b/web/app/components/workflow/variable-inspect/__tests__/panel.spec.tsx index 2bd1fbb00f..cafed9ce4e 100644 --- a/web/app/components/workflow/variable-inspect/__tests__/panel.spec.tsx +++ b/web/app/components/workflow/variable-inspect/__tests__/panel.spec.tsx @@ -57,16 +57,16 @@ vi.mock('../../hooks/use-nodes-interactions', () => ({ }), })) -vi.mock('../../hooks', async (importOriginal) => { - const actual = await importOriginal() - return { - ...actual, - useNodesInteractions: () => ({ - handleNodeSelect: mockHandleNodeSelect, - }), - useToolIcon: () => '', - } -}) +vi.mock('../../hooks', () => ({ + useNodesInteractions: () => ({ + handleNodeSelect: mockHandleNodeSelect, + }), + useToolIcon: () => '', +})) + +vi.mock('@/app/components/workflow/hooks/use-tool-icon', () => ({ + useGetToolIcon: () => () => '', +})) vi.mock('../../nodes/_base/hooks/use-node-crud', () => ({ default: () => ({