You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试Material-UI Popover的esc键关闭功能实现

问题根因

你的测试无法通过有两个核心原因:

  • @testing-library/user-event v14及以上版本的所有交互方法都是异步的,你当前代码没有加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 11:36:08