跳至主要内容

fireEvent 注意事项

交互 vs. 事件

根据 指导原则,您的测试应尽可能模拟用户与您的代码(组件、页面等)的交互方式。 考虑到这一点,您应该知道 fireEvent 并不是完全模拟用户与应用程序的交互方式,但对于大多数场景来说已经足够接近了。

考虑 fireEvent.click,它会创建一个点击事件并在给定的 DOM 节点上分发该事件。 当您只想测试元素被点击时会发生什么时,这种方法在大多数情况下都可以正常工作,但当用户实际点击您的元素时,通常会按照以下顺序触发这些事件:

  • fireEvent.mouseOver(element)
  • fireEvent.mouseMove(element)
  • fireEvent.mouseDown(element)
  • element.focus()(如果该元素可以获得焦点)
  • fireEvent.mouseUp(element)
  • fireEvent.click(element)

然后,如果该元素恰好是 label 的子元素,它还会将焦点移动到该标签所标记的表单控件。 因此,即使您真正想要测试的只是点击处理程序,简单地使用 fireEvent.click 也会忽略用户在此过程中可能触发的其他几个重要事件。

再说一次,大多数情况下,这对于您的测试来说并不重要,并且简单地使用 fireEvent.click 的折衷方案是值得的。

备选方案

我们将描述一些对测试进行的简单调整,这些调整将提高您对组件交互行为的信心。 对于其他交互,您可能想要考虑使用 user-event 或在真实环境中(例如,手动或使用 cypress 等自动进行)测试您的组件。

Keydown

keydown 事件会在当前获得焦点的元素、body 元素或 document 元素上分发。 在这之后,您应该更喜欢

- fireEvent.keyDown(getByText('click me'));
+ getByText('click me').focus();
+ fireEvent.keyDown(document.activeElement || document.body);

这也会测试所讨论的元素是否可以接收键盘事件。

Focus/Blur

如果元素获得焦点,则会分发 focus 事件,文档中的活动元素会发生变化,先前获得焦点的元素会失去焦点。 要模拟这种行为,您可以简单地用强制性焦点替换 fireEvent

- fireEvent.focus(getByText('focus me'));
+ getByText('focus me').focus();

这种方法的一个很好的副作用是,如果元素不可聚焦,任何对触发 focus 事件的断言都会失败。 如果您随后使用 keydown 事件,这一点尤其重要。