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

如何用React Testing Library测试react-select菜单滚动到底部事件

解决react-select的onMenuScrollToBottom测试触发问题

要触发onMenuScrollToBottom,你需要定位到react-select的下拉菜单容器(而非外层select元素),再模拟滚动到底部的行为——因为onMenuScrollToBottom是监听菜单容器的滚动事件,而非你点击的外层select元素。

具体修改步骤:

  1. 打开菜单后定位下拉容器:react-select的下拉菜单会渲染为带role="listbox"的元素,用这个角色定位最稳定;也可以通过你设置的classNamePrefix='select',查找类名含select-menu的容器。
  2. 模拟滚动到底部:给菜单容器设置scrollTop = scrollHeight - clientHeight(即滚动到容器最底部),再触发滚动事件。
  3. 验证触发逻辑:通过监听setSkip的调用,或检查skip值的变化,确认handleScroll是否被正确执行。

修改后的测试代码示例:

test("scroll in select triggers handleScroll", async () => {
  let value = jest.fn()
  let updateValue = jest.fn()
  let apiUrl = "/api/promoters/data"
  let ariaLabel = "selectPromoterFilter"

  const promotersOptions = [
    { id: 0, label: "Select Promoter", value: "" },
    { id: 1, label: "Ernesto Luna Hernández", value: 1 },
    { id: 2, label: "María Fernanda Lopéz Barilla", value: 2 },
    { id: 3, label: "Ricardo Gómez Robles", value: 3 },
    { id: 4, label: "Ricardo Gómez Robles", value: 3 },
    { id: 5, label: "Ricardo Gómez Robles", value: 5 },
    { id: 6, label: "Ricardo Gómez Robles", value: 6 },
    { id: 7, label: "Ricardo Gómez Robles", value: 7 },
    { id: 8, label: "Ricardo Gómez Robles", value: 8 },
    { id: 9, label: "Ricardo Gómez Robles", value: 9 },
    { id: 10, label: "Final", value: 10 },
    // 追加选项确保菜单出现滚动条
    { id: 11, label: "Extra Option 1", value: 11 },
    { id: 12, label: "Extra Option 2", value: 12 },
  ]
  jest.spyOn(axios, 'get').mockResolvedValueOnce({ data: promotersOptions});

  // 模拟setSkip用于验证
  const mockSetSkip = jest.fn();
  // 若组件内部用useState管理skip,可通过spy监听setSkip(示例:替换useState的返回)
  const originalUseState = React.useState;
  jest.spyOn(React, 'useState').mockImplementationOnce(initial => {
    const [state] = originalUseState(initial);
    return [state, mockSetSkip];
  });

  const { queryByLabelText, getByRole } = render(
    <Router>
      <Provider store={store}>
        <SelectApi
          value={value}
          updateValue={updateValue}
          apiUrl={apiUrl}
          ariaLabel={ariaLabel}
        />
      </Provider>
    </Router>
  )

  const selectPromoter = queryByLabelText(ariaLabel)
  if (selectPromoter) {
    // 点击打开下拉菜单
    fireEvent.click(selectPromoter);

    // 等待菜单渲染完成,获取listbox容器
    const menu = await waitFor(() => getByRole('listbox'));

    // 模拟滚动到底部的行为
    fireEvent.scroll(menu, {
      target: {
        scrollTop: menu.scrollHeight - menu.clientHeight,
        scrollHeight: menu.scrollHeight,
        clientHeight: menu.clientHeight,
      },
    });

    // 验证handleScroll是否触发:检查setSkip是否被调用
    expect(mockSetSkip).toHaveBeenCalled();
    // 若用redux管理状态,可直接检查store中skip的数值变化
    // expect(store.getState().yourNamespace.skip).toBe(limit);
  }
})

关键细节:

  • react-select的下拉菜单是独立DOM元素,不会挂载在你点击的select元素内部,必须单独定位。
  • 只有当菜单滚动位置到达最底部时,onMenuScrollToBottom才会触发,因此必须设置scrollTop = scrollHeight - clientHeight。
  • 打开菜单后要用waitFor确保菜单渲染完成,避免找不到元素的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 19:01:18