gongxiangp2/components/ui/Select.test.tsx

62 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState } from 'react'
import { act, fireEvent, render, screen, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import Select from './Select'
test('选项标签与提交值不同,仍调用原生表单回调并提交正确值', async () => {
const changed = jest.fn()
function Form() {
const [value, setValue] = useState('')
return <form aria-label="上传"><label htmlFor="method">出图方式</label><Select id="method" name="method" required value={value} onChange={(event) => { changed(event.target.value); setValue(event.currentTarget.value) }}><option value="">请选择</option><option value="photo">实拍</option><option value="ai">AI</option></Select></form>
}
const user = userEvent.setup()
render(<Form />)
await user.click(screen.getByRole('combobox', { name: '出图方式' }))
await user.click(screen.getByRole('option', { name: '实拍' }))
expect(changed).toHaveBeenCalledWith('photo')
expect(new FormData(screen.getByRole('form') as HTMLFormElement).get('method')).toBe('photo')
expect(screen.queryByRole('listbox')).not.toBeInTheDocument()
expect(screen.getByRole('combobox')).toHaveFocus()
})
test('键盘跳过禁用选项,Escape 只关闭菜单并恢复焦点', async () => {
const user = userEvent.setup(), changed = jest.fn(), parentKey = jest.fn()
render(<div onKeyDown={parentKey}><Select aria-label="方式" defaultValue="photo" onChange={changed}><option value="photo">实拍</option><option value="disabled" disabled>禁用项</option><option value="ai">AI</option></Select></div>)
screen.getByRole('combobox').focus()
await user.keyboard('{ArrowDown}{ArrowDown}{Enter}')
expect(changed).toHaveBeenCalledTimes(1)
expect(screen.getByRole('combobox')).toHaveTextContent('AI')
await user.click(screen.getByRole('combobox'))
parentKey.mockClear()
await user.keyboard('{Escape}')
expect(screen.queryByRole('listbox')).not.toBeInTheDocument()
expect(screen.getByRole('combobox')).toHaveFocus()
expect(parentKey).not.toHaveBeenCalled()
})
test('保留必填校验,原生校验失败将焦点交给可见控件', () => {
render(<form aria-label="表单"><Select required name="method" aria-label="方式" value=""><option value="">请选择</option><option value="ai">AI</option></Select></form>)
act(() => { expect((screen.getByRole('form') as HTMLFormElement).checkValidity()).toBe(false) })
expect(screen.getByRole('combobox')).toHaveFocus()
expect(screen.getByRole('combobox')).toHaveAttribute('aria-invalid', 'true')
})
test('支持回调内重置非受控字段与表单 reset', async () => {
const user = userEvent.setup()
const { container } = render(<form><Select name="method" defaultValue="" onChange={(event) => { event.target.value = '' }}><option value="">请选择</option><option value="ai">AI</option></Select></form>)
await user.click(screen.getByRole('combobox'))
await user.click(screen.getByRole('option', { name: 'AI' }))
expect(screen.getByRole('combobox')).toHaveTextContent('请选择')
fireEvent.reset(container.querySelector('form')!)
})
test('禁用状态不打开菜单;长选项和空列表也可显示', async () => {
const user = userEvent.setup()
const { rerender } = render(<Select disabled aria-label="方式"><option>实拍</option></Select>)
await user.click(screen.getByRole('combobox'))
expect(screen.queryByRole('listbox')).not.toBeInTheDocument()
rerender(<Select aria-label="方式" />)
await user.click(screen.getByRole('combobox'))
expect(within(screen.getByRole('listbox')).getByText('暂无可选项')).toBeInTheDocument()
})