如何在Jest+RTL中修改shadcn/ui Select组件的值?
解决shadcn/ui Select结合react-hook-form的单元测试问题
shadcn/ui的Select组件基于Radix UI实现,测试时需要遵循Radix组件的交互逻辑,以下是可行的测试方案:
核心思路
利用React Testing Library的语义化查询(ARIA角色)定位组件,结合@testing-library/user-event模拟真实用户交互流程:打开下拉 → 选择选项 → 验证结果。
完整测试代码示例
import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import ClientForm from './ClientForm'; // 你的表单组件 describe('Client Type Select Component', () => { it('should select an option and update form value correctly', async () => { // 初始化userEvent(需确保使用@testing-library/user-event@14+版本) const user = userEvent.setup(); // 渲染表单组件 render(<ClientForm />); // 1. 定位Select触发按钮:通过combobox角色和标签文本查找 const selectTrigger = screen.getByRole('combobox', { name: /client type/i }); // 2. 点击触发按钮打开下拉菜单 await user.click(selectTrigger); // 3. 定位目标选项:通过option角色和选项文本查找 const directOption = screen.getByRole('option', { name: 'Direct' }); // 4. 点击选中选项 await user.click(directOption); // 验证1:触发按钮显示选中的文本 expect(selectTrigger).toHaveTextContent('Direct'); // 验证2:react-hook-form的表单值更新(若需验证form内部状态) // 若组件暴露了form实例,可直接检查;否则可通过renderHook创建form传递给组件 // 示例: // const { result } = renderHook(() => useForm({ defaultValues: { clientType: '' } })); // render(<ClientForm form={result.current} />); // expect(result.current.getValues('clientType')).toBe('Direct'); }); });
关键注意事项
- 必须使用**@testing-library/user-event@14及以上版本**:旧版本API不支持
setup(),需改用userEvent.click()的异步写法。 - 依赖语义化查询:避免用className或id定位组件,Radix组件会生成标准ARIA角色(
combobox对应触发按钮,option对应下拉选项),这是最可靠的定位方式。 - 等待交互完成:所有userEvent的操作都是异步的,必须加
await确保组件状态更新后再执行验证。 - 避免使用
fireEvent:fireEvent是低级事件模拟,无法完整触发Radix组件内部的状态更新逻辑,必须用userEvent模拟真实用户行为。
内容的提问来源于stack exchange,提问作者James Bender
相关产品推荐
相关产品推荐

