【问题标题】:React Testing Library - using 'await wait()' after fireEventReact 测试库 - 在 fireEvent 之后使用 'await wait()'
【发布时间】:2020-11-13 15:50:22
【问题描述】:

我正在尝试使用测试库在 fireEvent.click 之后检查 DOM 元素。我知道我需要在 fireEvent 之后等待,但不知道为什么简单地使用 await 不起作用?下面是用两种方式编写的相同测试——第一个失败,第二个通过。我不明白为什么第一个失败了......非常感谢任何见解!

附言-- 我知道 wait 已被弃用,而 waitFor 是首选,但是由于某些限制,我目前无法更新版本:(

测试失败

// This test fails with the following error and warning:
// Error: Unable to find an element by: [data-test="name_wrapper"]
// Warning: An update to OnlinePaymentModule inside a test was not wrapped in act(...).

  it('this is a failing test...why', async () => {
      const { getByText, getByTestId } = render(<Modal {...props} />);
      const button = getByText('open modal');

      fireEvent.click(button);

        const nameWrapper =  await getByTestId('name_wrapper');
        expect(
          nameWrapper.getElementsByTagName('output')[0].textContent
        ).toBe('Jon Doe');

        const numberWrapper = await getByTestId('number_wrapper');
        expect(
          numberWrapper.getElementsByTagName('output')[0].textContent
        ).toBe('123456');
        
    });
PASSING TEST - 为什么这个通过但第一个失败?

// This test passes with no warnings

  it('this is a passing test...why', async () => {
      const { getByText, getByTestId } = render(<Modal {...props} />);
      const button = getByText('open modal');

      fireEvent.click(button);
      
      await wait(() => {
        const nameWrapper = getByTestId('name_wrapper');
        expect(
          nameWrapper.getElementsByTagName('output')[0].textContent
        ).toBe('Jon Doe');

        const numberWrapper = getByTestId('number_wrapper');
        expect(
          numberWrapper.getElementsByTagName('output')[0].textContent
        ).toBe('123456');
      })  
    });

【问题讨论】:

  • 在第一个示例中,getByTestId 没有返回 Promise,因此这些等待毫无意义。
  • 在第二个例子中你可以做await wait() 然后继续。
  • 您可以在testing-library.com/docs/dom-testing-library/api-async 上阅读更多内容,这里有一些很好的例子。例如。 await waitFor(callback) 所做的是等待回调为真,然后继续。
  • 不,但你可以先await waitFor(() =&gt; getByTestId(...)); const el = getByTestId(...)
  • 另一个好的来源是jestjs.io/docs/en/asynchronous

标签: arrays reactjs async-await jestjs react-testing-library


【解决方案1】:

5 个月后我回来回答我的问题(自从发布这个问题以来我学到了很多哈哈)......

首先,由于已经过了 5 个月,我想强调的是,如果可能,最好使用 userEvent 库而不是 fireEvent

如果我没有指出代码中有很多反模式,那我也是失职了……你应该只在waitFor 中做出一个断言。您应该避免使用 getByTestId 以支持更易于访问的替代方案。

最后,第一个测试失败的原因是您不能将waitgetBy* 一起使用。 getBy 不是异步的,不会等待。这本来是更好的解决方案:

fireEvent.click(button);
const nameWrapper =  await findByTestId('name_wrapper');

那么测试将等待nameWrapper 元素可用。

第二个测试通过了,因为 getBy 被包装在 RTL 的异步实用程序 wait 中(wait 现在已弃用,取而代之的是 waitFor)。这本质上就是 findBy 在幕后所做的——findBygetBy 的异步版本。

当我发布这个问题时,我并没有完全理解 await 是一个 Javascript 关键字(并且只是让代码等待承诺解决的语法糖)。 wait(现在是 waitFor)是 RTL 的一个实用程序,它可以让测试的执行等到回调不抛出错误。

【讨论】:

  • 你不需要 await 和 findByTestId,是吗?
  • @wuarmin 你确实需要await。否则,下一行的代码将在 promise 解决之前执行。
猜你喜欢
  • 2021-01-08
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多