diff --git a/web/app/components/base/chat/chat/answer/human-input-content/__tests__/human-input-form.spec.tsx b/web/app/components/base/chat/chat/answer/human-input-content/__tests__/human-input-form.spec.tsx
index d49b71d086..8feb97eaac 100644
--- a/web/app/components/base/chat/chat/answer/human-input-content/__tests__/human-input-form.spec.tsx
+++ b/web/app/components/base/chat/chat/answer/human-input-content/__tests__/human-input-form.spec.tsx
@@ -1,16 +1,33 @@
+import type { FileEntity } from '@/app/components/base/file-uploader/types'
import type { FormInputItem } from '@/app/components/workflow/nodes/human-input/types'
import type { HumanInputFormData } from '@/types/workflow'
import { act, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { describe, expect, it, vi } from 'vitest'
import { UserActionButtonType } from '@/app/components/workflow/nodes/human-input/types'
+import { InputVarType } from '@/app/components/workflow/types'
+import { TransferMethod } from '@/types/app'
import HumanInputForm from '../human-input-form'
vi.mock('../content-item', () => ({
- default: ({ content, onInputChange }: { content: string, onInputChange: (name: string, value: string) => void }) => (
+ default: ({ content, onInputChange }: { content: string, onInputChange: (name: string, value: unknown) => void }) => (
{content}
+
),
}))
@@ -76,6 +93,52 @@ describe('HumanInputForm', () => {
})
})
+ it('should submit non-string field values without coercion', async () => {
+ const user = userEvent.setup()
+ const mockOnSubmit = vi.fn().mockResolvedValue(undefined)
+ const formDataWithFileList: HumanInputFormData = {
+ ...mockFormData,
+ form_content: '{{#$output.field1#}} {{#$output.field3#}}',
+ inputs: [
+ {
+ type: InputVarType.paragraph,
+ output_variable_name: 'field1',
+ default: { type: 'constant', value: 'initial', selector: [] },
+ },
+ {
+ type: InputVarType.multiFiles,
+ output_variable_name: 'field3',
+ allowed_file_extensions: [],
+ allowed_file_types: [],
+ allowed_file_upload_methods: [],
+ max_upload_count: 5,
+ },
+ ] as FormInputItem[],
+ }
+
+ render()
+
+ await user.click(screen.getAllByTestId('update-input')[0]!)
+ await user.click(screen.getAllByTestId('update-input-file')[0]!)
+ await user.click(screen.getByRole('button', { name: 'Submit' }))
+
+ expect(mockOnSubmit).toHaveBeenCalledWith('token_123', {
+ action: 'action_1',
+ inputs: {
+ field1: 'new value',
+ field3: [{
+ id: 'file-1',
+ name: 'avatar.png',
+ size: 128,
+ type: 'image/png',
+ progress: 100,
+ transferMethod: TransferMethod.local_file,
+ supportFileType: 'image',
+ } satisfies FileEntity],
+ },
+ })
+ })
+
it('should disable buttons during submission', async () => {
const user = userEvent.setup()
let resolveSubmit: (value: void | PromiseLike) => void
@@ -109,17 +172,17 @@ describe('HumanInputForm', () => {
expect(screen.getAllByTestId('mock-content-item')).toHaveLength(3)
})
- it('should handle unsupported input types in initializeInputs', () => {
+ it('should handle mixed supported input types in initializeInputs', () => {
const formDataWithUnsupported = {
...mockFormData,
inputs: [
{
- type: 'select',
+ type: InputVarType.select,
output_variable_name: 'field2',
option_source: { type: 'variable', value: [], selector: [] },
} as FormInputItem,
{
- type: 'file',
+ type: InputVarType.singleFile,
output_variable_name: 'field3',
allowed_file_extensions: [],
allowed_file_types: [],