针对变更的React-select或react-testing-library的嘲笑未针对目标变更触发

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

我目前正在尝试模拟react-select组件,无论我做什么,从react-testing-library中的firevent.change似乎只会在firevent.change的第一个调用上触发。

我想知道为什么更改仅触发一次以及如何解决。

我开玩笑的模拟如下:

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

如您所见,它是一个相当简单的选择块,我认为我应该可以打电话。

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

但是如果我然后将它们链接在一起,如下例所示,这将起作用:

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

我可以看到console.log(“ Called”)仅被触发了一次。测试失败之前,永远不会选择页面上的第二个选择。

我希望两个变更都调度一个变更事件。

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

但是它只设置了第一个。

非常感谢任何帮助。

javascript reactjs jestjs react-testing-library
2个回答
1
投票

您应该对选择元素进行另一个查询。我会更进一步地命名它们,以使测试更易于阅读/调试。

  // 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();

0
投票

render有效但renderWithRedux不能说明问题在于Redux状态管理。

要考虑的一件事-设置状态将队列放入React中的重新渲染,而将动作分派给Redux则将Redux自己的更新队列中的更改放入队列。 React测试工具可能不知道该如何处理。

尽管它更接近代码,但您可能需要考虑模拟dispatch并验证其是否已收到选择更改的预期结果。这样,您可以验证代码是否正常运行,而不必担心第三方代码在做什么。 (有点讽刺的是,当renderWithRedux是实际的第三方问题时,您试图避免使用react-select。:D)

[您可能还考虑直接调用onChange处理程序,将其从组件中的select中删除,而不是触发事件。这将是减少正在测试和模拟的第三方代码量的另一种方法。

© www.soinside.com 2019 - 2024. All rights reserved.