feat/TanStack-Form (#18346)

This commit is contained in:
Wu Tianwei 2025-04-18 15:54:22 +08:00 • committed by GitHub
commit 1e7418095f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 959 additions and 127 deletions

View file

@ -0,0 +1,82 @@
import { fireEvent, render, screen } from '@testing-library/react'
import ConfigSelect from './index'
jest.mock('react-sortablejs', () => ({
ReactSortable: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
}))
jest.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string) => key,
}),
}))
describe('ConfigSelect Component', () => {
const defaultProps = {
options: ['Option 1', 'Option 2'],
onChange: jest.fn(),
}
afterEach(() => {
jest.clearAllMocks()
})
it('renders all options', () => {
render(<ConfigSelect {...defaultProps} />)
defaultProps.options.forEach((option) => {
expect(screen.getByDisplayValue(option)).toBeInTheDocument()
})
})
it('renders add button', () => {
render(<ConfigSelect {...defaultProps} />)
expect(screen.getByText('appDebug.variableConfig.addOption')).toBeInTheDocument()
})
it('handles option deletion', () => {
render(<ConfigSelect {...defaultProps} />)
const optionContainer = screen.getByDisplayValue('Option 1').closest('div')
const deleteButton = optionContainer?.querySelector('div[role="button"]')
if (!deleteButton) return
fireEvent.click(deleteButton)
expect(defaultProps.onChange).toHaveBeenCalledWith(['Option 2'])
})
it('handles adding new option', () => {
render(<ConfigSelect {...defaultProps} />)
const addButton = screen.getByText('appDebug.variableConfig.addOption')
fireEvent.click(addButton)
expect(defaultProps.onChange).toHaveBeenCalledWith([...defaultProps.options, ''])
})
it('applies focus styles on input focus', () => {
render(<ConfigSelect {...defaultProps} />)
const firstInput = screen.getByDisplayValue('Option 1')
fireEvent.focus(firstInput)
expect(firstInput.closest('div')).toHaveClass('border-components-input-border-active')
})
it('applies delete hover styles', () => {
render(<ConfigSelect {...defaultProps} />)
const optionContainer = screen.getByDisplayValue('Option 1').closest('div')
const deleteButton = optionContainer?.querySelector('div[role="button"]')
if (!deleteButton) return
fireEvent.mouseEnter(deleteButton)
expect(optionContainer).toHaveClass('border-components-input-border-destructive')
})
it('renders empty state correctly', () => {
render(<ConfigSelect options={[]} onChange={defaultProps.onChange} />)
expect(screen.queryByRole('textbox')).not.toBeInTheDocument()
expect(screen.getByText('appDebug.variableConfig.addOption')).toBeInTheDocument()
})
})

View file

@ -51,7 +51,7 @@ const ConfigSelect: FC<IConfigSelectProps> = ({
<RiDraggable className='handle h-4 w-4 cursor-grab text-text-quaternary' />
<input
key={index}
type="input"
type='input'
value={o || ''}
onChange={(e) => {
const value = e.target.value
@ -67,6 +67,7 @@ const ConfigSelect: FC<IConfigSelectProps> = ({
onBlur={() => setFocusID(null)}
/>
<div
role='button'
className='absolute right-1.5 top-1/2 block translate-y-[-50%] cursor-pointer rounded-md p-1 text-text-tertiary hover:bg-state-destructive-hover hover:text-text-destructive'
onClick={() => {
onChange(options.filter((_, i) => index !== i))