diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index d8ae014e884..87542c6a9db 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -4049,11 +4049,6 @@ "count": 1 } }, - "web/app/components/workflow/nodes/human-input/components/timeout.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/workflow/nodes/human-input/types.ts": { "erasable-syntax-only/enums": { "count": 2 diff --git a/web/app/components/workflow/nodes/human-input/components/__tests__/timeout.spec.tsx b/web/app/components/workflow/nodes/human-input/components/__tests__/timeout.spec.tsx index e827bf3548c..8e002ef0a71 100644 --- a/web/app/components/workflow/nodes/human-input/components/__tests__/timeout.spec.tsx +++ b/web/app/components/workflow/nodes/human-input/components/__tests__/timeout.spec.tsx @@ -1,4 +1,4 @@ -import { fireEvent, render, screen } from '@testing-library/react' +import { render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { withSelectorKey } from '@/test/i18n-mock' import TimeoutInput from '../timeout' @@ -9,22 +9,6 @@ vi.mock('react-i18next', () => ({ useTranslation: () => mockUseTranslation(), })) -vi.mock('@/app/components/base/input', () => ({ - __esModule: true, - default: (props: { - value: number - disabled?: boolean - onChange: (event: { target: { value: string } }) => void - }) => ( - props.onChange({ target: { value: e.target.value } })} - /> - ), -})) - describe('TimeoutInput', () => { const onChange = vi.fn() @@ -35,29 +19,32 @@ describe('TimeoutInput', () => { }) }) - it('should update the numeric timeout value and switch units', async () => { + it('should update the timeout with the keyboard and switch units', async () => { const user = userEvent.setup() render() - fireEvent.change(screen.getByTestId('timeout-input'), { target: { value: '12' } }) + const timeoutInput = screen.getByRole('textbox', { name: 'nodes.humanInput.timeout.title' }) + await user.click(timeoutInput) + await user.keyboard('{ArrowUp}') await user.click(screen.getByRole('radio', { name: 'nodes.humanInput.timeout.hours' })) - expect(onChange).toHaveBeenNthCalledWith(1, { timeout: 12, unit: 'day' }) + expect(onChange).toHaveBeenNthCalledWith(1, { timeout: 4, unit: 'day' }) expect(onChange).toHaveBeenNthCalledWith(2, { timeout: 3, unit: 'hour' }) }) - it('should fall back to 1 on invalid input and stay read-only when disabled', async () => { + it('should fall back to 1 when cleared and stay read-only when disabled', async () => { const user = userEvent.setup() const { rerender } = render() - fireEvent.change(screen.getByTestId('timeout-input'), { target: { value: 'abc' } }) + const timeoutInput = screen.getByRole('textbox', { name: 'nodes.humanInput.timeout.title' }) + await user.clear(timeoutInput) expect(onChange).toHaveBeenCalledWith({ timeout: 1, unit: 'hour' }) rerender() await user.click(screen.getByRole('radio', { name: 'nodes.humanInput.timeout.days' })) expect(onChange).toHaveBeenCalledTimes(1) - expect(screen.getByTestId('timeout-input')).toBeDisabled() + expect(screen.getByRole('textbox', { name: 'nodes.humanInput.timeout.title' })).toBeDisabled() expect(screen.getByRole('radio', { name: 'nodes.humanInput.timeout.days' })).toBeDisabled() }) }) diff --git a/web/app/components/workflow/nodes/human-input/components/timeout.tsx b/web/app/components/workflow/nodes/human-input/components/timeout.tsx index 3af8bcb7845..66e2adb72c4 100644 --- a/web/app/components/workflow/nodes/human-input/components/timeout.tsx +++ b/web/app/components/workflow/nodes/human-input/components/timeout.tsx @@ -1,8 +1,7 @@ import type { FC } from 'react' +import { NumberField, NumberFieldGroup, NumberFieldInput } from '@langgenius/dify-ui/number-field' import { SegmentedControl, SegmentedControlItem } from '@langgenius/dify-ui/segmented-control' -import * as React from 'react' import { useTranslation } from 'react-i18next' -import Input from '@/app/components/base/input' const i18nPrefix = 'nodes.humanInput' @@ -22,21 +21,18 @@ const TimeoutInput: FC = ({ timeout, unit, onChange, readonly }) => { const daysLabel = t(($) => $[`${i18nPrefix}.timeout.days`], { ns: 'workflow' }) const hoursLabel = t(($) => $[`${i18nPrefix}.timeout.hours`], { ns: 'workflow' }) - const handleValueChange = (e: React.ChangeEvent) => { - const value = e.target.value - if (/^\d*$/.test(value)) onChange({ timeout: Number(value) || 1, unit }) - else onChange({ timeout: 1, unit }) - } return (
- onChange({ timeout: value ?? 1, unit })} disabled={readonly} - /> + > + + + + value={unit} onValueChange={(unit) => onChange({ timeout, unit })}