在Jest中模拟动画完成回调

5
我正在尝试使用Jest为React组件编写单元测试,该组件利用了react-transition-group中的Transition。我需要模拟Transition,以便我的测试不必等待动画完成。但是,除了“跳过”动画之外,我还需要在模拟的Transition组件上触发onExited回调。
以下是我的Component.js如何使用Transition:
...
return (
  <Transition
    timeout={1500}
    in={this.state.show}
    onExited={handleExited}>
    {status =>
      <button onClick={this.setState({show: false}) className={`component-${status}`}>button</button>
    }
  </Transition>
)

这是我的Component.test.js文件:

import React from 'react'
import {render, fireEvent} from 'react-testing-library'

import Component from '../Component'

test('check', () => {
  const handleCompletion = jest.fn()
  const {getByText} = render(
    <Component
      onButtonClick={handleCompletion}
    />
  )
  const button = getByText('button')
  fireEvent.click(button)
  expect(handleCompletion).toHaveBeenCalledTimes(1)
})

这个想法是,一旦点击了一个 button,组件就会进行动画,然后在完成后触发回调函数。

我该如何正确模拟 Transition,以便跳过动画但仍然触发 onExited 回调?

1个回答

2
您可以通过 jest.mock 来模拟模块,如下所示:
jest.mock('react-transition-group', () => ({
    Transition: (props) => {
        props.onExited() // you can call it asynchronously too, if you wrap it in a timeout
        return <div>
            {props.in ? props.children() : null}
        </div>
    }
}))

谢谢您的建议。然而,props.onExited() 从未被调用... 我在 Component.js 中的 handleExited 方法中放置了一个 console.log(),但是消息从未被记录。我还检查了当我点击 button 时是否调用了 setState,它确实被调用了。有任何想法它在哪里失败了吗?我将您的代码插入到我的 Component.jest.js 中的 const {getByText} = render(... 之前。 - artooras
我的代码需要放在导入之后但在 test('check'... 之前。 - Herman Starikov
如果我将你的代码移动到import之后,它会破坏我的所有其他测试 :) 错误显示“警告: 函数不是React的有效子级。” 我已经在问题中更新了我的代码示例-我忘记包括Transition组件的子代实际上是一个函数{status => ...}。 我应该如何更新你的模拟来使其工作? - artooras
你需要调用 props.children,我已经更新了答案。 - Herman Starikov
谢谢!现在它可以工作了。只是最后,我将代码更改为Transition: props => { !props.in && props.onExited(); return props.children(); },因为我需要始终返回children,并且只有当in为false时才需要执行onExited() - artooras
我来晚了!有没有办法将DOM节点绑定到onExited调用上? - wariofan1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接