React 测试库,如何测试 history.push?

3
在React应用中,我有一个按钮可以通过程序跳转到新的URL:
<ComposeButton
  onClick={() => {
    history.push('some-link'))
  }}
>

在我的测试中,我按照React Router的react-testing-library文档所述渲染了我的组件:

const renderComponent = (page: Pages) => {
  const history = createMemoryHistory()

  return renderWithState(
    <MockedProvider
      mocks={mocks}
      addTypename={false}
      defaultOptions={{
        watchQuery: { fetchPolicy: 'no-cache' },
        query: { fetchPolicy: 'no-cache' }
      }}
    >
      <Router history={history}>
        <ComponentToRender />
      </Router>
    </MockedProvider>
  )
}

我该如何在react-testing-library中等待页面变化?
it('sends invitations', async () => {
    const { getByTestId, queryByTestId, debug, getByText } = renderComponent(
      Pages.contacts
    )

    await new Promise((resolve) => setTimeout(resolve))

    const writeMessageBtn = getByTestId('write-message-btn')
    waitFor(() => fireEvent.click(writeMessageBtn))
    await new Promise((resolve) => setTimeout(resolve))

    waitFor(() => debug()) // <- expect to see new page

    getByText('EV_305_NEW_INVITATION_SEND') // <- this is in the second page, never get here
})

当使用 debug 时,我无法看到新页面的内容(在点击按钮后)


你是否在测试中使用了一个已定义了“some-link”路由的Router来渲染你的组件? - thedude
我将 Router 添加到测试中,但测试仍然不等待新页面内容。 - AlbertMunichMar
1个回答

2

我不确定这样做是否能使一切正常,但是你分享的代码样例存在一些问题,我可以指出:

  1. 你正在渲染一个Router但没有Routes。改用MemoryRouter,并提供与实际应用程序相同的路由 - 至少提供你要推入历史记录的路由。

  2. 你没有正确使用react-testing-library。请使用findByTestId而不是getByTestId。例如:const writeMessageBtn = await findByTestId('write-message-btn')。区别在于get*查询是同步的,而find*是异步的。你不需要等待任意超时时间,测试库将尝试寻找该元素几秒钟。在其他使用get*的地方也是如此。


你能解释一下为什么不使用get*吗? - Bastian Stein
@BastianStein 我稍微扩展了我的回答,如果需要更多细节,建议你阅读 react-testing-library 的文档。 - thedude
我明白get是同步的。在测试中,如果我无论如何都在等待结果,为什么要使用异步版本? - Bastian Stein
1
测试可能会导致您想要等待的 UI 发生变化。最好等待 UI 发生更改,而不是等待超时或承诺,因为这些可能会在 UI 有机会更新之前结束。 - thedude
我现在明白了,谢谢。我误解了get方法会阻塞一定时间直到找到元素或失败的概念,但实际情况并非如此。 - Bastian Stein

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