React18升级后Jest测试中userEvent.type报错:Expected key descriptor but found ""
测试用例在React16环境运行正常,升级React18后执行输入过滤表格的测试时失败。示例代码如下:
const Wrapper = () => ( <Provider store={store}> <TestComponent testId={'table-view'} /> </Provider> ); it('Recently Added Search : test', async () => { await render(<Wrapper />); await waitFor( async () => { store.dispatch(setTabIndex(1)); const searchComp = screen.getByTestId('recent-search-input'); userEvent.type(searchComp, 'ABC'); const table = await screen.getByRole('recentTable'); expect(table).toHaveAttribute('aria-colcount', '4'); expect(table).toHaveAttribute('aria-rowcount', '0'); }, { timeout: 5000 } ); });
错误信息:
Expected key descriptor but found "" in ""
at assertDescriptor
(node_modules/@testing-library/user-event/dist/cjs/utils/keyDef/readNextDescriptor.js:77:15) at readPrintableChar
(node_modules/@testing-library/user-event/dist/cjs/utils/keyDef/readNextDescriptor.js:33:5)
at Object.readNextDescriptor
(node_modules/@testing-library/user-event/dist/cjs/utils/keyDef/readNextDescriptor.js:28:26) at Object.parseKeyDef
(node_modules/@testing-library/user-event/dist/cjs/keyboard/parseKeyDef.js:26:125)
at Object.keyboard
(node_modules/@testing-library/user-event/dist/cjs/keyboard/index.js:17:33) at Object.type
(node_modules/@testing-library/user-event/dist/cjs/utility/type.js:26:16)
at Object.asyncWrapper
(node_modules/@testing-library/react/dist/pure.js:73:22)
已尝试添加await调用userEvent.type,问题仍未解决。
以下是针对性的修复步骤,按优先级尝试:
1. 升级@testing-library/user-event到兼容版本
React18要求使用@testing-library/user-event v14及以上版本,旧版本与React18的并发渲染机制不兼容,会触发输入解析错误。执行升级命令:
npm install @testing-library/user-event@latest # 或 yarn add @testing-library/user-event@latest
2. 使用userEvent.setup()创建实例(v14+强制要求)
新版本user-event不再支持直接调用静态方法,需先初始化实例再操作:
it('Recently Added Search : test', async () => { const user = await userEvent.setup(); await render(<Wrapper />); await waitFor(async () => { store.dispatch(setTabIndex(1)); // 用findByTestId确保元素已挂载且可交互 const searchComp = await screen.findByTestId('recent-search-input'); await user.type(searchComp, 'ABC'); // 修正表格查询:getByRole参数为标准ARIA角色,自定义ID用getByTestId const table = screen.getByTestId('recentTable'); expect(table).toHaveAttribute('aria-colcount', '4'); expect(table).toHaveAttribute('aria-rowcount', '0'); }, { timeout: 5000 }); });
3. 调整元素查询与状态同步逻辑
- 替换同步查询
screen.getByTestId为异步的await screen.findByTestId:React18并发渲染下,元素可能延迟挂载,findBy会自动等待元素出现。 - 新增状态同步等待:dispatch动作后,等待Redux状态更新到组件,避免操作未就绪的元素:
it('Recently Added Search : test', async () => { const user = await userEvent.setup(); await render(<Wrapper />); store.dispatch(setTabIndex(1)); // 等待Tab索引状态更新完成 await waitFor(() => expect(store.getState().tabIndex).toBe(1)); const searchComp = await screen.findByTestId('recent-search-input'); await user.type(searchComp, 'ABC'); const table = await screen.findByTestId('recentTable'); expect(table).toHaveAttribute('aria-colcount', '4'); expect(table).toHaveAttribute('aria-rowcount', '0'); });
内容的提问来源于stack exchange,提问作者SivaShanker

