简体   繁体   English

用于 react-select 或 react-testing-library on change 的 Jest mock 不触发目标更改

[英]Jest mock for react-select or react-testing-library on change not firing on target change

I'm currenty trying to mock the react-select component and no matter what i do the firevent.change from react-testing-library seems to only fire on the first call of firevent.change.我目前正在尝试模拟 react-select 组件,无论我做什么,react-testing-library 中的 firevent.change 似乎只在第一次调用 firevent.change 时触发。

I was wondering why the change was only firing once and how to fix it.我想知道为什么更改只触发一次以及如何修复它。

My jest mock is as follows:我的笑话如下:

jest.mock("react-select", () => ({ options, value, onChange }) => {
  function handleChange(event) {
    console.log("called");

    const option = options.find(option => {
      return option.value == event.currentTarget.value;
    });

    onChange(option);
  }
  return (
    <select
      id="uc"
      data-testid="select"
      value={value}
      onChange={event => handleChange(event)}
    >
      {options?.map(({ label, value }) => (
        <option key={value} value={value}>
          {label}
        </option>
      ))}
    </select>
  );
});

As you can see its a fairly simple select block and i thought i should be able to call.正如你所看到的,它是一个相当简单的选择块,我认为我应该能够调用。

fireEvent.change(selectOptions[0], { target: { value: "0" } });

And this will work however if i then chain them together as in the following example:但是,如果我将它们链接在一起,如下例所示,这将起作用:

test("Should render add another button and function", () => {
  const mockSetOpen = jest.fn();

  const { queryAllByTestId, getByTestId, getByLabelText, debug } = renderWithRedux(
    <TabByRestraints setOpen={mockSetOpen} hidden={false} />,
    {
      userCatagories: userCategoriesMock,
      permissionGroups: permissionGroupsMock,
      roles: rolesMock
    }
  );

  // Check that the user catagories exist and user catagories values
  const selectOptions = queryAllByTestId("select");
  expect(selectOptions).toHaveLength(2);

  expect(getByTestId("user-category-row")).toBeTruthy();

  fireEvent.change(selectOptions[0], { target: { value: "0" } });
  fireEvent.change(selectOptions[1], { target: { value: "132" } });

  expect(getByLabelText("Add a new user category restraint")).toBeTruthy();
});

I can see that the console.log("called") is only fired once.我可以看到 console.log(" called") 只被触发一次。 The second select on the page is never has its value selected therfore the test fails.页面上的第二个选择永远不会选择其值,因此测试失败。

I would like both change to dispatch a change event.我希望两者都更改以发送更改事件。

fireEvent.change(selectOptions[0], { target: { value: "0" } });
fireEvent.change(selectOptions[1], { target: { value: "132" } }); 

However it only ever sets of the first.然而,它只设置了第一个。

Any help greatly appeciated.任何帮助都非常感谢。

You should do another query for the select elements.您应该对 select 元素执行另一个查询。 I would go further and name them differently to make the test easier to read/debug.我会更进一步并以不同的方式命名它们,以使测试更易于阅读/调试。

  // it's easier to have separate ids for each select, will be easier to read/maintain the test in the future
  const firstSelect = queryByTestId("select1");
  fireEvent.change(firstSelect, { target: { value: "0" } });

  // a rerender might have happened so you need to query for the second select after the first event.
  const secondSelect = queryByTestId("select2");
  fireEvent.change(secondSelect, { target: { value: "132" } });

  expect(getByLabelText("Add a new user category restraint")).toBeTruthy();

The fact that render works but renderWithRedux doesn't suggests the problem lies in the redux state management. render有效但renderWithRedux事实并不表明问题在于 redux 状态管理。

One thing to consider -- setting state queues a rerender within React, while dispatching an action to Redux queues the change in Redux's own update queue.需要考虑的一件事——在 React 中设置状态排队重新渲染,同时将操作分派到 Redux 将更改排队到 Redux 自己的更新队列中。 React testing tools may not know how to deal with that. React 测试工具可能不知道如何处理。

Although it's closer to the code, you may want to consider mocking dispatch and verifying that it is receiving the expected results of the select changes.尽管它更接近代码,但您可能需要考虑模拟dispatch并验证它是否正在接收选择更改的预期结果。 That way you can validate that your code is working, without worrying about what third party code is doing.这样您就可以验证您的代码是否正常工作,而无需担心第三方代码在做什么。 (Kind of ironic that you were trying to avoid using react-select when renderWithRedux was the actual third-party problem. :D ) (具有讽刺意味的是,当 renderWithRedux 是实际的第三方问题时,您试图避免使用 react-select。:D)

You may also want to consider directly calling your onChange handler, plucking it from the selects in your component instead of firing the events.您可能还想考虑直接调用 onChange 处理程序,从组件中的选择中提取它而不是触发事件。 This would be another way to reduce the amount of third-party code you are testing and mocking.这将是减少您正在测试和模拟的第三方代码数量的另一种方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 更新未包含在 act(...) 中,并且模拟 function 未触发。 反应测试库,开玩笑 - Update not wrapped in act(…) and the mock function not firing. react-testing-library, jest 如何使用 jest、react-testing-library 在 React 中模拟元素上的点击事件 - How to mock a click event on an element in React using jest , react-testing-library react-testing-library 输入更改测试总是通过 - react-testing-library input change test always passing 如何使用 react-testing-library 模拟 window.location 更改 - How to simulate window.location change with react-testing-library 如何在Jest和react-testing-library中使用react-hook - How to use react-hooks with Jest and react-testing-library Jest &amp; React &amp; Typescript &amp; React-Testing-Library 错误 - Jest & React & Typescript & React-Testing-Library error 使用React,Jest,React-Testing-Library测试失败的案例 - Test failing cases with React, Jest, React-Testing-Library 使用 react-testing-library 和 jest 测试是否调用了 prop 函数 - Testing if a prop function was called using react-testing-library and jest 使用 Jest + react-testing-library 测试异步 `componentDidMount()` - Testing async `componentDidMount()` with Jest + react-testing-library Jest + react-testing-library:警告更新未包含在 act() 中 - Jest + react-testing-library: Warning update was not wrapped in act()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM