【问题标题】:Why doesn't .simulate("mouseover") work in a Jest / Enzyme test?为什么 .simulate("mouseover") 在 Jest / Enzyme 测试中不起作用?
【发布时间】:2020-06-08 08:28:01
【问题描述】:

我有一个 Material-ui ListItem 的简单示例,我将鼠标悬停在它上面,然后一个包含另一个 ListItem 的 material-ui Popper 然后出现在 onMouseOver 事件上。这工作正常,但我无法复制相关 Jest/Enzyme 测试中的行为。

在此处减少测试失败的示例。

组件片段

export default function MyPopoutMenu() {
  const [popoverAnchorElement, setPopoverAnchorElement] = useState(null);
  const handleMouseEnter = event => {
    console.log("onMouseEnter - " + event.currentTarget.textContent);
    setPopoverAnchorElement(event.currentTarget);
  };

  const handleClose = (event, index) => {
    console.log("closing");
    setPopoverAnchorElement(null);
  };

  let isPopoverOpen = Boolean(popoverAnchorElement);
  return (
    <div className="App">
      <List style={{ maxWidth: "250px" }}>
        <ListItem button>
          <ListItemIcon>
            <FolderIcon />
          </ListItemIcon>
          <ListItemText onMouseEnter={handleMouseEnter}>
            Hover on me
          </ListItemText>
        </ListItem>
      </List>
      <Popper
        open={isPopoverOpen}
        onClose={handleClose}
        anchorEl={popoverAnchorElement}
        className="popper-item"
      >
        <ListItem button>
          <ListItemIcon>
            <KeyboardArrowRightIcon />
          </ListItemIcon>
          <ListItemText>I Appear</ListItemText>
        </ListItem>
      </Popper>
    </div>
  );
}

测试片段

/** Interaction tests testing user interaction with PilzButton */
test("Check that popover appears on hover", () => {
  const wrapper = mount(<MyPopoutMenu />);
  console.log("wrapper DEBUG - " + wrapper.debug());

  //1. Find the menu item to hover on
  const foundListItem = wrapper
    .find(".MuiListItemText-root")
    .filterWhere(item => item.contains("Hover on me"));
  expect(foundListItem).toHaveLength(1);

  //2. Hover on the item
  foundListItem.prop("onMouseEnter")({
    currentTarget: {
      textContent: "Hover on me"
    }
  });
  act(() => {
    //Now try to find the Popover
    const foundPopoverListItem = wrapper
      .find(".MuiListItemText-root")
      .filterWhere(item => item.contains("I Appear"));

    expect(foundPopoverListItem).toHaveLength(1);
  });
});

【问题讨论】:

  • 将其更改为foundListItem.simulate("mouseenter");会发生什么?
  • 同样的事情发生了:(

标签: javascript jestjs material-ui dom-events enzyme


【解决方案1】:

在行动之前更新包装器

在此处通过沙盒的测试:https://codesandbox.io/s/festive-leaf-7ko8v

【讨论】:

    【解决方案2】:

    你应该看看这个关于simulate使用的讨论:

    https://github.com/airbnb/enzyme/issues/1606

    因此,简而言之,建议完全不使用它,而是按以下方式操作:

    foundListItem.prop('onMouseEnter')();
    

    您甚至可以将模拟事件传递给handleMouseEnter 函数,如下所示:

    foundListItem.prop('onMouseEnter')({
      currentTarget: {
        textContent: 'I Appear'
      }
    });
    

    希望这会有所帮助!

    【讨论】:

    • 这行得通!但是,当我的处理程序在mouseEnter 事件被触发时被触发时,event 对象为空。奇怪的?! onMouseEnter={(event: Event) =&gt;
    • 请注意模拟事件的语法。特别是如果您需要在 handleMouseEntersetPopoverAnchorElement 函数期间处理一些非常具体的事情。确保这两种方法所需的一切都是模拟的。
    • 啊,是的,我明白了。我认为它可能确实如此,但看起来它可能需要在行为调用中进行额外的包装。得到以下警告 测试时,导致 React 状态更新的代码应该被包装到 act(...): 中。应该很容易排序。
    • 啊,好吧,我已经看到了。那是因为你在 React 中使用了 useState 钩子。你也需要模拟那些 React 钩子(无论如何,根据我的经验)。我不确定它背后的确切原因,但jest 没有使用开箱即用的 React 钩子。您将不得不模拟这些函数。
    • 不幸的是,上面的建议仍然不起作用。此处的代码框带有您建议的解决方案 - codesandbox.io/s/priceless-bose-6hi04 也在上面的原始问题中更新。
    猜你喜欢
    • 2023-03-06
    • 2018-09-14
    • 2018-12-16
    • 2019-01-28
    • 2017-07-08
    • 2018-09-08
    • 2017-02-12
    • 2020-08-07
    • 2017-11-26
    相关资源
    最近更新 更多