如何测试Material-UI Popover的esc键关闭功能实现
问题根因
你的测试无法通过有两个核心原因:
@testing-library/user-eventv14及以上版本的所有交互方法都是异步的,你当前代码没有加await等待交互执行完成,就直接跑后续断言,导致事件未生效。另外新版本更推荐先调用userEvent.setup()初始化交互实例,避免全局状态污染。- MUI的Popover和Modal底层逻辑不同:Modal默认开启全局焦点锁定,打开后自动将焦点移入组件内部,所以ESC事件可以被正常捕获;但Popover默认不会自动转移焦点,打开后焦点仍停留在触发按钮上,你触发的ESC事件没有被Popover的事件监听器捕获,所以不会触发关闭。
修复方案
方案1:仅修改测试代码(无需改动组件逻辑)
主动在触发ESC前将焦点移入Popover内部即可,修改后的测试代码如下:
import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import SimpleModal from './SimpleModal'; test('should close when esc key is pressed', async () => { // 初始化userEvent实例 const user = userEvent.setup(); render(<SimpleModal />); // 等待点击操作完成 await user.click(screen.getByText('Open Modal')); const popoverContent = screen.getByText('Text in Modal'); expect(popoverContent).toBeInTheDocument(); // 主动将焦点移入Popover内部 popoverContent.focus(); // 等待ESC按键事件触发完成 await user.keyboard('{esc}'); expect(screen.queryByText('Text in Modal')).not.toBeInTheDocument(); });
方案2:修改组件代码(让Popover行为和Modal一致,自动获取焦点)
给Popover添加autoFocus属性,让它打开时自动获得焦点,这样无需修改测试逻辑也能符合交互预期:
组件代码修改点:
<Popover open={open} onClose={handleClose} autoFocus // 新增这一行即可 > <h1>Text in Modal</h1> </Popover>
测试代码使用方案1里修正了异步逻辑的版本即可。
内容的提问来源于stack exchange,提问作者TheChimp
相关产品推荐
相关产品推荐

