React, Jest and Material-UI: How to test for content rendered in a modal or popover

老子叫甜甜 提交于 2019-12-21 12:34:09

问题


There are a few material-ui components that do not render their results in the same place as the component is placed by their parent. Among these we have the Dialog, Menu, etc.

This makes it apparently impossible to test for their content's presence in a jest.js wrapper with some parent component mounted in it.

For example given the following component:

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

This test fails even though it should intuitively work:

it('renders some menu items', () => {
  const wrapper = mount(<AppMenu />);
  expect(wrapper).toContainReact(<MenuItem label="Home" />);
});

And this is Jest's output of the failure:

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>

As you can see, it's like if all that was rendered was the <Button>. And indeed, when you render the above component in a browser, and you expand the menu and inspect it's menu item elements, they are rendered elsewhere in the DOM, not within or even near the place where the button appears. They are in fact rendered inside a div <body><div data-mui-portal="true"> ... </div> directly under the document's <body> element.

So how can this menu contents be tested?


回答1:


The Menu won't be rendered until state changes, so you can simulate a click on the Button, let its handler setState, trigger a rerender, and find the specific MenuItem.

Also, this can probably be done without fully mounting:

it('renders some menu items', () => {
  const wrapper = shallow(<AppMenu />);

  // find the Menu Button
  const button = wrapper.findWhere(node => node.is(Button) && n.prop('children') === 'Menu');

  // simulate a click event so that state is changed
  button.simulate('click');

  // find the Home MenuItem
  const menuItem = wrapper.findWhere(node => node.is(MenuItem) && n.prop('label') === 'Home');

  // make sure it was rendered
  expect(menuItem.exists()).toBe(true);
});


来源:https://stackoverflow.com/questions/45551965/react-jest-and-material-ui-how-to-test-for-content-rendered-in-a-modal-or-popo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!