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

fireEvent doesn't click button on React component

我正在为 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。当我 运行 我的测试 timerOutput 结果是 '25:00' 而不是 '24:59' 时,Jest 在终端告诉我,似乎组件没有通过测试。但这是测试的问题,而不是组件的问题;当我 运行 浏览器中的应用程序并自己按下按钮时,它会按应有的方式工作。我如何让这个测试正常工作,并按我想要的方式按下按钮?

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

首先,我建议在需要处理异步调用时在 test() 中使用 async 箭头函数,这样您就不会依赖回调地狱。

除此之外,我会尝试使用 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 语句会更好,例如:

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

因为您不关心包含该文本内容的 HTML 元素