对 Material UI Select 组件的更改做出反应测试库

新手上路,请多包涵

我正在尝试使用 react-testing-library 测试 Select 组件onChange 事件。

我使用 getByTestId 来抓取元素,效果很好,然后设置元素的值,然后调用 fireEvent.change(select);onChange 永远不会被调用更新。

我已经尝试使用选择组件本身,也尝试通过获取对底层 input 元素的引用,但两者都不起作用。

有什么解决办法吗?或者这是一个已知问题?

原文由 Rob Sanders 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 600
2 个回答

当您使用 Material-UI 的 Selectnative={false} (这是默认设置)时,这会变得非常复杂。这是因为渲染的输入甚至没有 <select> HTML 元素,而是混合了 div、隐藏输入和一些 svg。然后,当您单击选择时,会显示一个表示层(有点像模式),其中包含您的所有选项(顺便说一下,它们不是 <option> HTML 元素),我相信它是单击其中一个选项会触发您传递的任何内容 onChange 回调到您的原始 Material-UI <Select>

综上所述,如果您愿意使用 <Select native={true}> ,那么您将拥有实际的 <select><option> HTML 元素可以使用如您所料, <select> 上的更改事件。

这是来自代码沙箱的测试代码,它可以工作:

 import React from "react";
import { render, cleanup, fireEvent } from "react-testing-library";
import Select from "@material-ui/core/Select";

beforeEach(() => {
  jest.resetAllMocks();
});

afterEach(() => {
  cleanup();
});

it("calls onChange if change event fired", () => {
  const mockCallback = jest.fn();
  const { getByTestId } = render(
    <div>
      <Select
        native={true}
        onChange={mockCallback}
        data-testid="my-wrapper"
        defaultValue="1"
      >
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </Select>
    </div>
  );
  const wrapperNode = getByTestId("my-wrapper")
  console.log(wrapperNode)
  // Dig deep to find the actual <select>
  const selectNode = wrapperNode.childNodes[0].childNodes[0];
  fireEvent.change(selectNode, { target: { value: "3" } });
  expect(mockCallback.mock.calls).toHaveLength(1);
});

您会注意到,一旦 Material-UI 渲染出其 <Select> ,您必须深入挖掘节点以找到实际的 <select> 所在的位置。但是一旦你找到它,你就可以在上面做一个 fireEvent.change

CodeSandbox 可以在这里找到:

编辑 material-ui 选择的触发更改事件

原文由 Alvin S. Lee 发布,翻译遵循 CC BY-SA 4.0 许可协议

material-ui 的 select 组件使用 mouseDown 事件触发弹出菜单出现。如果您使用 fireEvent.mouseDown 应该会触发弹出窗口,然后您可以在出现的列表框中单击您的选择。请参见下面的示例。

 import React from "react";
import { render, fireEvent, within } from "react-testing-library";
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
import Typography from "@material-ui/core/Typography";

it('selects the correct option', () => {
  const {getByRole} = render(
     <>
       <Select fullWidth value={selectedTab} onChange={onTabChange}>
         <MenuItem value="privacy">Privacy</MenuItem>
         <MenuItem value="my-account">My Account</MenuItem>
       </Select>
       <Typography variant="h1">{/* value set in state */}</Typography>
     </>
  );

  fireEvent.mouseDown(getByRole('button'));

  const listbox = within(getByRole('listbox'));

  fireEvent.click(listbox.getByText(/my account/i));

  expect(getByRole('heading')).toHaveTextContent(/my account/i);
});

原文由 haasdev 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进