From f96dc692e631a254caa7a9a6ce35c0d6b006311c Mon Sep 17 00:00:00 2001 From: Haohao-end <2227625024@qq.com> Date: Sun, 15 Mar 2026 15:34:40 +0800 Subject: [PATCH] fix: resolve i18n ordering and add panel onChange test coverage --- .../workflow/nodes/agent/panel.spec.tsx | 178 ++++++++++++++++++ web/i18n/en-US/workflow.json | 4 +- 2 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 web/app/components/workflow/nodes/agent/panel.spec.tsx diff --git a/web/app/components/workflow/nodes/agent/panel.spec.tsx b/web/app/components/workflow/nodes/agent/panel.spec.tsx new file mode 100644 index 0000000000..c6c675f928 --- /dev/null +++ b/web/app/components/workflow/nodes/agent/panel.spec.tsx @@ -0,0 +1,178 @@ +/** + * Agent Panel - Enable Human Clarification Test + * + * Tests the enable_human_clarification onChange handler in the agent panel. + * Covers panel.tsx line 114: setInputs({ ...inputs, enable_human_clarification: value }) + * + * Strategy: Mock FormInputBoolean to capture and trigger its onChange callback directly, + * avoiding dependency on component's internal text/UI. + */ + +import type { AgentNodeType } from './types' +import { render } from '@testing-library/react' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import AgentPanel from './panel' + +// Mock setInputs at the top level +const mockSetInputs = vi.fn() + +// Capture FormInputBoolean's onChange callback +let capturedOnChange: ((value: boolean) => void) | null = null + +// Mock useConfig to return minimal required data +vi.mock('./use-config', () => ({ + default: () => ({ + inputs: { + enable_human_clarification: false, + agent_strategy_name: 'test-strategy', + agent_strategy_provider_name: 'test-provider', + agent_strategy_label: 'Test Strategy', + meta: { version: '1.0' }, + agent_parameters: {}, + output_schema: {}, + memory: undefined, + }, + setInputs: mockSetInputs, + currentStrategy: null, + formData: {}, + onFormChange: vi.fn(), + isChatMode: false, + availableNodesWithParent: [], + availableVars: [], + readOnly: false, + outputSchema: [], + handleMemoryChange: vi.fn(), + }), +})) + +// Mock i18n +vi.mock('react-i18next', () => ({ + useTranslation: () => ({ + t: (key: string) => key, + }), +})) + +// Mock store +vi.mock('../../store', () => ({ + useStore: (selector: (state: Record) => unknown) => { + const state = { + setControlPromptEditorRerenderKey: vi.fn(), + } + return selector(state) + }, +})) + +// Mock utility +vi.mock('@/utils/plugin-version-feature', () => ({ + isSupportMCP: () => true, +})) + +// Mock heavy components +vi.mock('../_base/components/agent-strategy', () => ({ + AgentStrategy: () =>
, +})) + +vi.mock('../_base/components/mcp-tool-availability', () => ({ + MCPToolAvailabilityProvider: ({ children }: { children: React.ReactNode }) => <>{children}, +})) + +vi.mock('../_base/components/memory-config', () => ({ + default: () =>
, +})) + +vi.mock('../_base/components/output-vars', () => ({ + default: ({ children }: { children: React.ReactNode }) => <>{children}, + VarItem: () =>
, +})) + +vi.mock('../_base/components/split', () => ({ + default: () =>
, +})) + +// Mock FormInputBoolean to capture onChange callback +vi.mock('../_base/components/form-input-boolean', () => ({ + default: ({ onChange }: { value: boolean; onChange: (value: boolean) => void }) => { + capturedOnChange = onChange + return
+ }, +})) + +describe('AgentPanel - Enable Human Clarification', () => { + beforeEach(() => { + mockSetInputs.mockClear() + capturedOnChange = null + }) + + it('should call setInputs with enable_human_clarification=true when onChange is triggered with true', () => { + const mockData: AgentNodeType = { + id: 'test-node', + data: {}, + } as any + + render( + , + ) + + // Trigger the captured onChange callback + capturedOnChange?.(true) + + expect(mockSetInputs).toHaveBeenCalledWith( + expect.objectContaining({ + enable_human_clarification: true, + }), + ) + }) + + it('should call setInputs with enable_human_clarification=false when onChange is triggered with false', () => { + const mockData: AgentNodeType = { + id: 'test-node', + data: {}, + } as any + + render( + , + ) + + // Trigger the captured onChange callback + capturedOnChange?.(false) + + expect(mockSetInputs).toHaveBeenCalledWith( + expect.objectContaining({ + enable_human_clarification: false, + }), + ) + }) + + it('should preserve other inputs when updating enable_human_clarification', () => { + const mockData: AgentNodeType = { + id: 'test-node', + data: {}, + } as any + + render( + , + ) + + // Trigger the captured onChange callback + capturedOnChange?.(true) + + // Verify that spread operator preserves other inputs + expect(mockSetInputs).toHaveBeenCalledWith( + expect.objectContaining({ + agent_strategy_name: 'test-strategy', + agent_strategy_provider_name: 'test-provider', + agent_strategy_label: 'Test Strategy', + enable_human_clarification: true, + }), + ) + }) +}) diff --git a/web/i18n/en-US/workflow.json b/web/i18n/en-US/workflow.json index 56534dc295..9749fd1a72 100644 --- a/web/i18n/en-US/workflow.json +++ b/web/i18n/en-US/workflow.json @@ -324,6 +324,8 @@ "nodes.agent.checkList.strategyNotSelected": "Strategy not selected", "nodes.agent.clickToViewParameterSchema": "Click to view parameter schema", "nodes.agent.configureModel": "Configure Model", + "nodes.agent.enableHumanClarification.label": "Enable Human Clarification", + "nodes.agent.enableHumanClarification.tooltip": "Allow human intervention to clarify agent reasoning during execution", "nodes.agent.installPlugin.cancel": "Cancel", "nodes.agent.installPlugin.changelog": "Change log", "nodes.agent.installPlugin.desc": "About to install the following plugin", @@ -373,8 +375,6 @@ "nodes.agent.toolbox": "toolbox", "nodes.agent.tools": "Tools", "nodes.agent.unsupportedStrategy": "Unsupported strategy", - "nodes.agent.enableHumanClarification.label": "Enable Human Clarification", - "nodes.agent.enableHumanClarification.tooltip": "Allow human intervention to clarify agent reasoning during execution", "nodes.answer.answer": "Answer", "nodes.answer.outputVars": "Output Variables", "nodes.assigner.append": "Append",