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

Jest Dom匹配器toBeEnabled与not.toBeDisabled行为异常咨询

问题原因及解决方法

你的测试出现这种矛盾结果,核心原因是Formik的表单验证与状态更新是异步过程,你在触发字段操作后立刻断言,此时DOM可能还没完成状态同步,导致断言捕获到的是按钮的旧状态(enabled),所以toBeEnabled()会通过;而测试运行时的时序差异又可能让toBeDisabled()偶尔通过,属于不稳定的测试表现。

具体解决步骤:

  1. 用waitFor等待异步状态更新
    Formik在字段失焦后触发的验证是异步的,必须等待验证完成、DOM更新后再做断言。把断言逻辑包裹在waitFor中并使用await等待:
test("Submit is disabled when user enters invalid values", async () => {
  const handleSubmit = jest.fn();
  render(<Reservations onSubmit={handleSubmit} />);

  // ... 字段操作代码 ...

  const submitButton = screen.getByRole("button", { name: /Submit/i });
  
  // 等待按钮状态更新后断言
  await waitFor(() => {
    expect(submitButton).toBeDisabled();
  });
});
  1. 替换fireEvent为userEvent
    RTL官方更推荐使用@testing-library/user-event,它模拟真实用户的操作流程(比如输入时自动触发focus、change、blur),能更可靠地触发Formik的状态更新,同时简化代码:

首先安装依赖:

npm install --save-dev @testing-library/user-event@latest

修改测试代码:

import userEvent from '@testing-library/user-event';

test("Submit is disabled when user enters invalid values", async () => {
  const user = userEvent.setup();
  const handleSubmit = jest.fn();
  render(<Reservations onSubmit={handleSubmit} />);

  const firstNameField = screen.getByLabelText(/First Name/i);
  await user.type(firstNameField, "S"); // 自动触发focus、change、blur

  const lastNameField = screen.getByLabelText(/Last Name/i);
  await user.type(lastNameField, "S");

  const emailField = screen.getByLabelText(/Email/i);
  await user.type(emailField, "S@s");

  const dateField = screen.getByLabelText(/Choose date/i);
  await user.type(dateField, "2024-12-12");

  const occasionField = screen.getByLabelText(/Occasion/i);
  await user.selectOptions(occasionField, "default");

  const guestField = screen.getByLabelText(/Number of guests/i);
  await user.clear(guestField);
  await user.type(guestField, "-1");

  const submitButton = screen.getByRole("button", { name: /Submit/i });
  await waitFor(() => {
    expect(submitButton).toBeDisabled();
  });
});
  1. 检查Formik按钮的disabled绑定
    确保你的提交按钮正确绑定了Formik的表单状态,比如:
<button 
  type="submit" 
  disabled={!formik.isValid || formik.isSubmitting}
>
  Submit
</button>

如果只绑定了isSubmitting,即使表单无效,按钮也会保持启用状态,这会直接导致你的断言不符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:33:14