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 事件,这一点尤其重要。