Jest捕获输入更改事件,并验证在受控的React组件上使用正确的值调用了该事件

91zkwejq  于 2023-08-01  发布在  Jest
关注(0)|答案(2)|浏览(116)

我尝试使用jest@testing-library/react来验证react组件(* Package 了HTML input元素 *)正在调用它的onChange回调,并使用正确的值来响应ChangeEvent。
这里是react组件

export const MyInput = ({ onChange, value }) => {
  const handleChange = (event) => {
    console.log(event.target.value);
    onChange(event);
  };

  return (
    <div>
      <input
        type="text"
        onChange={handleChange}
        label={"test-component"}
        data-testid={"test"}
        value={value}
      />
    </div>
  );
};

字符串
这是测试

test("onChange should work", () => {
  const onChangeMock = jest.fn();
  let inputValue = 1;

  const { getByTestId } = render(
    <MyInput onChange={onChangeMock} value={inputValue} />
  );
  const input = getByTestId("test");

  fireEvent.change(input, { target: { value: "23" } });

  expect(onChangeMock).toHaveBeenCalled();
  expect(onChangeMock).toHaveBeenCalledWith(
    expect.objectContaining({
      target: expect.objectContaining({
        value: "23"
      })
    })
  );
});


这是一个link to a codesandbox,它再现了这个问题。
我的测试中的第二个Assert失败了,因为onChangeMock的调用者是一个事件,其' target.value等于1,而不是23
更奇怪的是,当在handleChange函数中记录event.target.value时,它具有正确的值23。使用调试器进行检查还显示jest mock有一个正确的调用者(目标值为23的事件,直到调试器离开handleChange函数的作用域)。当我回到测试范围并执行Assert时,mock的事件的目标值为1。
所以我试图理解为什么我会观察到这种行为,是什么导致了它?

  • (我假设事件的目标已经设定好了(但是通过什么?)在事件处理程序作用域结束的那一刻,jest没有捕获事件的深层克隆,因为它被传递给了外部函数,但我找不到任何文档来支持这一点)*
dohp0rv5

dohp0rv51#

React使用合成事件而不是原生DOM事件,它们的行为相似但不完全相同,合成事件在处理程序处理程序执行后无效,为了说明,请尝试使用您代码中的事件处理程序:

const handleChange = (event) => {
  console.log(event.target.value);
  onChange(event); // 23
  setTimeout(() => {
    console.log(event.target.value);
  }, 3000); // 1
};

字符串

gmxoilav

gmxoilav2#

您的文本输入不会影响更改,因为您的代码没有将其视为受控输入。
简而言之,测试期待正确的事情,但是组件忽略了变化。
试试这个:

import React, {useState} from "react";

export const MyInput = ({ onChange, value }) => {
  const [controlledValue, setControlledValue] = useState(value);
  const handleChange = (event) => {
    console.log(event.target.value);
    setControlledValue(event.target.value);
    onChange(event);
  };

  return (
    <div>
      <input
        type="text"
        onChange={handleChange}
        label={"test-component"}
        data-testid={"test"}
        value={controlledValue}
      />
    </div>
  );
};

字符串
您将在Testing Library InputEvent docs中看到一个类似的示例

相关问题