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

如何测试React组件中遍历生成的每个按钮点击后是否禁用

问题解决

报错原因

  • screen.getAllByRole('button') 返回的是所有匹配按钮的 HTMLElement数组,而fireEvent.click仅支持传入单个DOM元素,因此触发类型不匹配报错。

不需要为每个按钮单独编写测试用例

你可以通过遍历按钮数组的方式批量验证所有按钮的点击禁用逻辑,示例代码如下:

// 先模拟组件所需的相关参数
const mockSortVariant = { payType: 'online' }; // 替换为你实际的sortVariant取值
const sortDirections = ['asc', 'desc', 'priceAsc', 'priceDesc']; // 替换为你实际的排序方向列表
const mockHandleSortFilters = jest.fn();

it('所有排序按钮点击后应进入禁用状态', () => {
  // 初始化排序筛选参数
  let testSortFilters = { direction: '', payType: '' };

  const { rerender } = render(
    <ProductSorter
      sortFilters={testSortFilters}
      handleSortFilters={mockHandleSortFilters}
      sortVariant={mockSortVariant} // 注意你原测试代码漏传了这个props,需要补上
    />
  );

  const buttons = screen.getAllByRole('button');
  expect(buttons).toHaveLength(4);

  // 遍历所有按钮逐个验证逻辑
  buttons.forEach((button, index) => {
    const expectedDirection = sortDirections[index];
    // 点击当前按钮
    fireEvent.click(button);
    
    // 验证回调函数接收到的参数正确
    expect(mockHandleSortFilters).toHaveBeenCalledWith({
      payType: mockSortVariant.payType,
      direction: expectedDirection
    });

    // 更新排序筛选参数后重渲染组件,模拟父组件状态更新的逻辑
    testSortFilters = {
      payType: mockSortVariant.payType,
      direction: expectedDirection
    };
    rerender(
      <ProductSorter
        sortFilters={testSortFilters}
        handleSortFilters={mockHandleSortFilters}
        sortVariant={mockSortVariant}
      />
    );

    // 验证当前按钮已禁用,其他按钮未禁用
    expect(button).toBeDisabled();
    buttons.forEach((otherBtn, otherIndex) => {
      if (otherIndex !== index) expect(otherBtn).not.toBeDisabled();
    });

    // 重置mock调用记录,避免影响下一轮循环校验
    mockHandleSortFilters.mockClear();
  });
});

注意事项

如果你的组件是内部维护sortFilters状态的非受控组件,不需要手动调用rerender,点击按钮后直接等待状态更新完成后验证禁用状态即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 13:06:02