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

React Jest测试含onFocus的输入组件时出现警告问题求助

问题描述

我开发的React组件包含如下表单输入字段:

<Form.Label>E-mail</Form.Label>
<Form.Control
  data-testid="inputemail"
  type="email"
  onFocus={() => setAttribute(false)}
  readOnly={attribute}
  placeholder="Enter e-mail"
/>
</Form.Group>

我编写了对应的Jest测试用例:

it("should change 'Email' input value", async () => {
  render(<LoginPage />);
  const textVariable = ""; 
  const inputemail = screen.getByTestId("inputemail");

  inputemail.focus();
  fireEvent.input(inputemail, { target: { value: textVariable } });
  expect(inputemail).toHaveFocus(); // 目前能通过

  await waitFor(() => {
    expect(inputemail.innerHTML).toBe(textVariable);
  });
});

测试用例执行通过,但出现了警告,请问该如何解决?


解决方案

警告根源

  1. 只读状态未更新时触发输入事件:组件中Form.Control的readOnly由attribute控制,只有在onFocus触发后才会调用setAttribute(false)解除只读。但测试中在focus()后立刻触发input事件,此时组件可能还没完成状态更新,对只读输入框触发输入操作会触发React警告。
  2. 错误的断言对象:输入框的值存储在value属性中,而非innerHTML——innerHTML用于获取元素内部的HTML内容,用它断言输入值属于无效操作,且没必要用waitFor包裹这个断言。

修复步骤

  1. 等待只读状态解除:在focus()后,用waitFor等待输入框的只读状态被移除,确保后续输入事件是合法的:
    await waitFor(() => {
      expect(inputemail).not.toHaveAttribute('readonly');
    });
    
  2. 修正断言逻辑:将expect(inputemail.innerHTML).toBe(textVariable)改为expect(inputemail.value).toBe(textVariable),且输入事件触发后value会同步更新,无需异步等待。
  3. 优化测试用例(可选):建议使用非空测试值,空值无法有效验证输入逻辑的正确性。优化后的完整测试代码如下:
    it("should change 'Email' input value", async () => {
      render(<LoginPage />);
      const testEmail = "test@example.com";
      const inputemail = screen.getByTestId("inputemail");
    
      inputemail.focus();
      // 等待只读状态解除
      await waitFor(() => {
        expect(inputemail).not.toHaveAttribute('readonly');
      });
      fireEvent.input(inputemail, { target: { value: testEmail } });
      
      expect(inputemail).toHaveFocus();
      expect(inputemail.value).toBe(testEmail);
    });
    

额外建议

  • 若需要验证setAttribute是否被正确调用,可以用jest.spyOn监听状态更新函数,比如:
    const mockSetAttribute = jest.fn();
    // 假设attribute是组件状态,通过props或mock传递
    render(<LoginPage setAttribute={mockSetAttribute} />);
    // ...后续测试中可以断言mockSetAttribute被调用
    expect(mockSetAttribute).toHaveBeenCalledWith(false);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:45:45