Jest 捕获输入更改事件并验证在受控反应组件上使用正确的值调用它

问题描述 投票:0回答:2

我正在尝试使用

jest
@testing-library/react
来验证 React 组件(包装了 HTML
input
元素
)是否正在使用正确的值调用它的
onChange
回调以响应 ChangeEvent。

这是反应组件

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"
      })
    })
  );
});

这里有一个 codesandbox 的链接,它重现了问题。

我的测试中的第二个断言失败了,因为

onChangeMock
的调用者是一个事件,其
target.value
等于
1
,而不是
23

更奇怪的是,当在

event.target.value
函数中记录
handleChange
时 - 它具有正确的
23
值。使用调试器进行检查还表明,笑话模拟具有正确的调用者(目标值为
23
的事件,直到调试器离开
handleChange
函数的范围)。当我回到测试范围并执行断言时,模拟事件的目标值为 1。

所以我试图理解为什么我会观察到这种行为以及造成这种行为的原因是什么?

(我假设事件处理程序范围结束时,事件的目标被设置(通过什么?)到我的 html 输入元素,并且 jest 没有捕获事件的深层克隆,因为它被传递给外部函数,但我找不到任何文档来支持这一点)

javascript reactjs jestjs dom-events react-testing-library
2个回答
0
投票

您的文本输入不会影响更改,因为您的代码没有将其视为受控输入

简而言之,测试期待正确的事情,但组件忽略了更改。

试试这个:

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>
  );
};

您将在测试库InputEvent文档中看到类似的示例


0
投票

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

const handleChange = (event) => {
  console.log(event.target.value);
  onChange(event); // 23
  setTimeout(() => {
    console.log(event.target.value);
  }, 3000); // 1
};
© www.soinside.com 2019 - 2024. All rights reserved.