有一些material-ui组件不会将其结果呈现在其父对象放置在同一位置的位置。其中有DialogMenu等。

这显然使得无法在装有某些父组件的jest.js包装器中测试其内容的存在。

例如,给定以下组件:

class DropdownMenu extends React.Component {
  onButtonClick = (e) => {
    this.setState({ open: true, anchorEl: e.currentTarget });
  }

  render() {
    return (
      <div>
        <Button onClick={this.onButtonClick}>Menu</Button>
        <Menu
          open={this.state.open}
          onRequestClose={() => this.setState({ open: false })}
        >
          <MenuItem label="Home" />
          <MenuItem label="Sign in" />
        </Menu>
      </div>
    );
  }
}

即使此测试应直观地起作用,它也会失败:
it('renders some menu items', () => {
  const wrapper = mount(<AppMenu />);
  expect(wrapper).toContainReact(<MenuItem label="Home" />);
});

这是杰斯特失败的输出:
renders some menu items

Expected <AppMenu> to contain <withStyles(MenuItem) className="MenuItem" component={{...}} to={{...}}>Home</withStyles(MenuItem)> but it was not found.
HTML Output of <AppMenu>:
 <div><button tabindex="0" class="MuiButtonBase-root-3477017037 MuiButton-root-3294871568 MuiButton-flatContrast-53993421" type="button" role="button" aria-owns="simple-menu" aria-haspopup="true"><span class="MuiButton-label-49836587">Menu</span><span class="MuiTouchRipple-root-3868442396"></span></button><!-- react-empty: 5 --></div>

如您所见,这就像渲染的只是<Button>一样。确实,当您在浏览器中呈现上述组件,并展开菜单并检查其菜单项元素时,它们将呈现在DOM中的其他位置,而不是在按钮出现的位置内或附近。实际上,它们是在文档<body><div data-mui-portal="true"> ... </div>元素正下方的div <body>内部呈现的。

那么如何测试此菜单内容?

最佳答案

是的,这可能很棘手。问题有两个:

  • 触发点击事件意味着您需要使测试成为异步函数
  • 菜单项不在包装元素<AppMenu />中-正如您指出的,它们在DOM中的其他位置。

  • 对于菜单项,您需要将其定位在实际位置。打开菜单的按钮位于包装元素中,但菜单和菜单项将不存在,因此您需要按角色获取菜单,然后才能通过菜单项中的文本获取菜单项。
    这是我如何使用React Testing Library做到这一点的示例。
    import React, { ReactElement } from "react";
    import { render, screen } from "@testing-library/react";
    import AppMenu from "./AppMenu";
    import { getByText, fireEvent, getByLabelText } from "@testing-library/react";
    
    
    test("It renders some menu items", async () => {
      const { container } = render(<AppMenu />);
      const button = getByText(container, "Menu");
    
      fireEvent.click(button);
    
      const menuItem = screen.getByRole("menu");
    
      expect(await getByLabelText(menuItem, "Home")).toBeTruthy();
      expect(await getByLabelText(menuItem, "Sign in")).toBeTruthy();
    });
    

    10-06 04:21
    查看更多