fix(workflow): clamp file list upload limit (#37474)

This commit is contained in:
Jingyi 2026-06-15 22:50:16 -07:00 committed by GitHub
parent 6f31e9ef8d
commit 30506f7221
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 75 additions and 3 deletions

View File

@ -11,6 +11,7 @@ type VarReferencePickerProps = {
}
let lastVarReferencePickerProps: VarReferencePickerProps | undefined
let fileUploadSettingMaxLength: number | undefined = 4
vi.mock('@/app/components/workflow/nodes/_base/components/variable/var-reference-picker', () => ({
default: (props: VarReferencePickerProps) => {
@ -66,7 +67,7 @@ vi.mock('@/app/components/workflow/nodes/_base/components/file-upload-setting',
allowed_file_extensions: ['.pdf'],
allowed_file_types: [SupportUploadFileTypes.document],
allowed_file_upload_methods: [TransferMethod.local_file],
max_length: 4,
max_length: fileUploadSettingMaxLength,
})}
>
file-upload-setting
@ -89,6 +90,7 @@ describe('InputField', () => {
beforeEach(() => {
vi.clearAllMocks()
lastVarReferencePickerProps = undefined
fileUploadSettingMaxLength = 4
})
it('should keep the header and actions visible while the field content scrolls internally', () => {
@ -627,6 +629,32 @@ describe('InputField', () => {
})
})
it('should normalize empty file-list upload limit on save', async () => {
const user = userEvent.setup()
const onChange = vi.fn()
fileUploadSettingMaxLength = Number.NaN
render(
<InputField
nodeId="node-14-normalize"
isEdit={false}
payload={createPayload()}
onChange={onChange}
onCancel={vi.fn()}
/>,
)
await user.click(screen.getByRole('button', { name: 'select-file-list' }))
await user.click(screen.getByRole('button', { name: 'file-upload-setting' }))
await user.click(screen.getByRole('button', { name: /workflow\.nodes\.humanInput\.insertInputField\.insert/i }))
expect(onChange).toHaveBeenCalledTimes(1)
expect(onChange.mock.calls[0]![0]).toEqual(expect.objectContaining({
type: InputVarType.multiFiles,
number_limits: 1,
}))
})
it('should clear paragraph default state when switching to file-list', async () => {
const user = userEvent.setup()
const onChange = vi.fn()

View File

@ -97,6 +97,16 @@ const InputField: React.FC<InputFieldProps> = ({
const handleSave = useCallback(() => {
if (!nameValid)
return
if (isFileListFormInput(tempPayload)) {
const value = tempPayload.number_limits ?? 5
if (!Number.isFinite(value)) {
onChange({
...tempPayload,
number_limits: 1,
})
return
}
}
onChange(tempPayload)
}, [nameValid, onChange, tempPayload])
const handleTypeChange = useCallback((item: TypeSelectItem) => {

View File

@ -1,6 +1,7 @@
import type { UploadFileSetting } from '@/app/components/workflow/types'
import { fireEvent, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { useState } from 'react'
import { useFileSizeLimit } from '@/app/components/base/file-uploader/hooks'
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
import { useFileUploadConfig } from '@/service/use-common'
@ -120,6 +121,35 @@ describe('File upload support components', () => {
}))
})
it('should keep upload limits within the configured range', () => {
const StatefulFileUploadSetting = () => {
const [payload, setPayload] = useState(createPayload())
return (
<FileUploadSetting
payload={payload}
isMultiple
onChange={setPayload}
/>
)
}
render(<StatefulFileUploadSetting />)
const input = screen.getByRole('spinbutton')
fireEvent.change(input, { target: { value: '20' } })
expect(input).toHaveValue(10)
fireEvent.change(input, { target: { value: '0' } })
expect(input).toHaveValue(1)
fireEvent.change(input, { target: { value: '' } })
expect(input).toHaveValue(null)
fireEvent.blur(input)
expect(input).toHaveValue(1)
})
it('should toggle built-in and custom file type selections', async () => {
const user = userEvent.setup()
const onChange = vi.fn()

View File

@ -89,11 +89,14 @@ const FileUploadSetting: FC<Props> = ({
}, [onChange, payload])
const handleMaxUploadNumLimitChange = useCallback((value: number) => {
const normalizedValue = Number.isFinite(value)
? Math.min(Math.max(value, 1), maxFileUploadLimit)
: value
const newPayload = produce(payload, (draft) => {
draft.max_length = value
draft.max_length = normalizedValue
})
onChange(newPayload)
}, [onChange, payload])
}, [maxFileUploadLimit, onChange, payload])
return (
<div>
@ -163,6 +166,7 @@ const FileUploadSetting: FC<Props> = ({
<InputNumberWithSlider
label={t('variableConfig.maxNumberOfUploads', { ns: 'appDebug' })!}
value={max_length}
defaultValue={1}
min={1}
max={maxFileUploadLimit}
onChange={handleMaxUploadNumLimitChange}