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

React Select测试中下拉菜单无法保持展开,但浏览器中正常

AsyncReactSelect测试中选中选项后菜单意外关闭(已设置closeMenuOnSelect={false})

问题场景

我用以下配置的AsyncReactSelect组件,开启了多选且设置closeMenuOnSelect={false},浏览器里选中选项后菜单能正常保持展开:

<AsyncReactSelect 
  defaultOptions 
  loadOptions={async () => [ 
    { value: "Pear", label: "Pear" }, 
    { value: "Banana", label: "Banana" }, 
    { value: "Raspberry", label: "Raspberry" }, 
  ]} 
  closeMenuOnSelect={false} 
  isMulti 
/>

但在测试代码里,用userEvent.type触发Enter选中选项后,菜单直接关闭了,fireEvent.click也没用,甚至onMenuClose回调在测试里被莫名触发(浏览器里只有点击菜单外部才会触发):

await act(async () => { 
  // 打开下拉框
  const selectDropdown = screen.getAllByRole("combobox")[0] 
  await userEvent.click(selectDropdown) 
  await screen.findByText("Pear") 
  screen.debug() // 第一次debug能看到所有选项
  await userEvent.type(selectDropdown, "{enter}") 
  screen.debug() // 第二次debug菜单已关闭
})

解决方法

1. 直接点击选项元素(最推荐)

测试里给combobox发Enter事件的逻辑,和组件内部的事件处理可能不匹配,换成直接点击对应的选项元素,更贴近真实用户操作:

await act(async () => {
  const selectDropdown = screen.getAllByRole("combobox")[0];
  await userEvent.click(selectDropdown);
  // 找到Pear选项并点击
  const pearOption = await screen.findByText("Pear");
  await userEvent.click(pearOption);
  screen.debug(); // 此时菜单应该保持展开状态
});

2. 等待组件状态完全同步

AsyncReactSelect的异步加载可能在测试环境里有状态更新延迟,虽然已经用findByText等选项出现,但可以加个微任务等待状态稳定:

await act(async () => {
  const selectDropdown = screen.getAllByRole("combobox")[0];
  await userEvent.click(selectDropdown);
  await screen.findByText("Pear");
  // 等待组件内部状态完成更新
  await new Promise(resolve => setTimeout(resolve, 0));
  await userEvent.click(await screen.findByText("Pear"));
  screen.debug();
});

3. 调整键盘事件触发方式或升级userEvent

不同版本的@testing-library/user-event对键盘事件的模拟有差异,试试用keyboard方法替代type,或者升级到最新稳定版:

await act(async () => {
  const selectDropdown = screen.getAllByRole("combobox")[0];
  await userEvent.click(selectDropdown);
  await screen.findByText("Pear");
  // 用keyboard方法触发Enter键
  await userEvent.keyboard("{enter}");
  screen.debug();
});

4. 手动控制组件状态(备选方案)

如果上面的方法都不行,可以通过ref直接操作组件实例,手动选中选项并强制保持菜单展开:

// 组件里先设置ref
const selectRef = useRef(null);
<AsyncReactSelect ref={selectRef} ... />

// 测试代码中调用
await act(async () => {
  const selectDropdown = screen.getAllByRole("combobox")[0];
  await userEvent.click(selectDropdown);
  await screen.findByText("Pear");
  // 手动选中选项并强制打开菜单
  selectRef.current.selectOption({ value: "Pear", label: "Pear" });
  selectRef.current.setState({ menuIsOpen: true });
  screen.debug();
});

内容的提问来源于stack exchange,提问作者Red Baron

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 23:47:51