fireEvent不会在React组件上单击按钮

问题描述

我正在为React组件编写测试。它是一个计时器,当您按下一个按钮时开始倒计时,然后在按下相同的按钮时停止计时。我有一个测试用例,试图按一下暂停按钮,等待一秒钟,然后再次按一下暂停按钮,检查计时器以确保已过去一秒钟:

Timer.test.js

render(<Timer />)
const pauseButton = screen.getByText('pause')
const timerOutput = screen.getAllByRole('heading')[1]

describe('Timer',() => {
  test('Timer starts counting down when unpaused',done => {
    function fetchTime(callback) {
      fireEvent.click(pauseButton)
      setTimeout(
        fireEvent.click(pauseButton),1250
      )
      return callback(timerOutput)
    }

    function callback(data) {
      try {
        expect(data).toHaveTextContent('24:59')
        done()
      } catch(error) {
        done(error)
      }
    }

    fetchTime(callback)
  })
})

问题是,测试似乎没有按我希望的方式点击pauseButton。 Jest在终端上告诉我,当我运行测试时,发现timerOutput'25:00'而不是'24:59',看来组件未通过测试。但这是测试的问题,而不是组件的问题。当我在浏览器中运行该应用程序并自己按下按钮时,它将按应有的方式工作。如何使此测试正常运行,并按我希望的方式按下按钮?

解决方法

很难获得关于组件本身的很少信息的准确答案。

首先,我建议在需要处理异步调用时使用async内的test()箭头功能,这样您就不必依赖回调地狱了。

除此之外,我将尝试使用jest.useFakeTimers(),以便您可以提前setTimeout计时器以进行正确测试。看来您的第二个fireEvent.click从未被解雇,因为测试是同步检查它的。

我只是注意到您最初是请求timerOutput的,但是在点击事件之后却没有请求。

我建议类似的东西

test('Timer starts counting down when unpaused',async () => {
      jest.useFakeTimers();
      fireEvent.click(pauseButton)
      setTimeout(
        () => {fireEvent.click(pauseButton)},1250
      )
      jest.runPendingTimers(); // This would run the above function
   
        expect(screen.getAllByRole('heading')[1]).toHaveTextContent('24:59')
    }
  })

实际上,从用户角度断言来看,期望语句会更好,例如:

expect(screen.getByText("24:59")).toBeVisible();

由于您不必担心包含该文本内容的HTML元素