diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index 9d6abf0a5b4..623a6061d0c 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -4001,11 +4001,8 @@ } }, "web/app/components/workflow/nodes/loop/components/loop-variables/form-item.tsx": { - "no-restricted-imports": { - "count": 1 - }, "typescript/no-explicit-any": { - "count": 3 + "count": 2 } }, "web/app/components/workflow/nodes/loop/components/loop-variables/item.tsx": { diff --git a/web/app/components/workflow/nodes/loop/components/loop-variables/__tests__/form-item.spec.tsx b/web/app/components/workflow/nodes/loop/components/loop-variables/__tests__/form-item.spec.tsx new file mode 100644 index 00000000000..044dff59773 --- /dev/null +++ b/web/app/components/workflow/nodes/loop/components/loop-variables/__tests__/form-item.spec.tsx @@ -0,0 +1,62 @@ +import type { LoopVariable } from '@/app/components/workflow/nodes/loop/types' +import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { useState } from 'react' +import { ValueType, VarType } from '@/app/components/workflow/types' +import FormItem from '../form-item' + +describe('Loop variable constant input', () => { + it('reports numeric edits and clearing as strings to the loop draft', async () => { + const user = userEvent.setup() + const onChange = vi.fn() + function LoopDraft() { + const [value, setValue] = useState('12') + return ( + { + setValue(nextValue) + onChange(nextValue) + }} + /> + ) + } + render() + + const input = screen.getByRole('spinbutton', { name: 'count' }) + await user.clear(input) + expect(onChange).toHaveBeenLastCalledWith('') + await user.type(input, '-3.5') + expect(input).toHaveValue(-3.5) + expect(onChange).toHaveBeenLastCalledWith('-3.5') + }) + + it.each([ + [VarType.number, 'spinbutton'], + [VarType.string, 'textbox'], + ] as const)('names an unnamed %s constant until its variable is named', (varType, role) => { + const item: LoopVariable = { + id: 'new-variable', + label: '', + var_type: varType, + value_type: ValueType.constant, + value: '', + } + const { rerender } = render() + expect( + screen.getByRole(role, { name: 'workflow.errorMsg.fields.variableValue' }), + ).toBeInTheDocument() + + rerender( + , + ) + expect(screen.getByRole(role, { name: 'counter' })).toBeInTheDocument() + }) +}) diff --git a/web/app/components/workflow/nodes/loop/components/loop-variables/form-item.tsx b/web/app/components/workflow/nodes/loop/components/loop-variables/form-item.tsx index 91a3f7df7e1..aa57b679bf4 100644 --- a/web/app/components/workflow/nodes/loop/components/loop-variables/form-item.tsx +++ b/web/app/components/workflow/nodes/loop/components/loop-variables/form-item.tsx @@ -1,9 +1,9 @@ import type { LoopVariable } from '@/app/components/workflow/nodes/loop/types' import type { Var } from '@/app/components/workflow/types' +import { Input } from '@langgenius/dify-ui/input' import { Textarea } from '@langgenius/dify-ui/textarea' import { useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' -import Input from '@/app/components/base/input' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' import VarReferencePicker from '@/app/components/workflow/nodes/_base/components/variable/var-reference-picker' import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' @@ -26,17 +26,11 @@ type FormItemProps = { const FormItem = ({ nodeId, item, onChange }: FormItemProps) => { const { t } = useTranslation() const { value_type, var_type, value } = item + const valueLabel = item.label || t(($) => $['errorMsg.fields.variableValue'], { ns: 'workflow' }) const normalizedVarValue = useMemo(() => { return Array.isArray(value) ? value : [] }, [value]) - const handleInputChange = useCallback( - (e: any) => { - onChange(e.target.value) - }, - [onChange], - ) - const handleValueChange = useCallback( (value: string) => { onChange(value) @@ -85,14 +79,21 @@ const FormItem = ({ nodeId, item, onChange }: FormItemProps) => { )} {value_type === ValueType.constant && var_type === VarType.string && (