javascript - 如何进行一个在检查元素外观之前等待 5 秒的测试(React 测试库)

标签 javascript reactjs unit-testing jestjs react-testing-library

在我的 react 组件中,我有一个元素在 5 秒后出现。

我想做一个测试,用 jest fake timers 检查元素是否在 5 秒后出现,但无法使其工作...

我在这里做错了什么?

其中一个示例不起作用:

it('check step 2 labels text, status "Submitted"', async () => {
    render(<ProgressIndicator appStatus="submitted" />);

    jest.advanceTimersByTime(5005);
    await waitFor(() => {
      expect(
        screen.getByText('Beep. Boop. Still doing our thing here.'),
      ).toBeInTheDocument();
    });

    await waitFor(() => {
      expect(screen.getByText('Verifying identity...')).toBeInTheDocument();
    });
  });

第二个例子:

it('check step 2 labels text, status "Submitted"', async () => {
    render(<ProgressIndicator appStatus="submitted" />);

    act(() => {
      jest.advanceTimersByTime(5005);
    });

    expect(
      screen.getByText('Beep. Boop. Still doing our thing here.'),
    ).toBeInTheDocument();
    expect(screen.getByText('Verifying identity...')).toBeInTheDocument();
  });

最佳答案

使用 await findBy 查询和 await waitFor 的一般经验法则是您应该使用

await findBy when you expect an element to appear but the change to the DOM might not happen immediately.

and await waitFor when you have a unit test that mocks API calls and you need to wait for your mock promises to resolve.

dom-testing-library的官方文档中也提到了同样的事情.


现在,您需要使用 jest.useFakeTimer() 来启用假计时器,这将有助于模拟 setTimeout 和其他计时器函数。

official docs 中也提到了同样的情况.

useFakeTimer 与 async methods 配合使用但是,如果我们想要使用像 getBy 查询这样的同步方法,那么我们必须使用 jest.advanceTimersByTime(5000) 将测试移动 5(任何指定时间)秒在它前面。 (下面给出的示例)

在下面的示例中,我重现了您提出的问题。我认为这可能会有所帮助。

import { useState } from 'react';
import { act, render, screen, waitForElementToBeRemoved } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

const data = {
  name: 'subrato',
  age: 24,
};


function App() {
  const [myData, setState] = useState({});
  const [loading, setLoading] = useState(false);

  function clickHandler() {
    setLoading(true);
    setTimeout(() => {
      setState(data);
      setLoading(false);
    }, 5000);
  }

  return (
    <div className='App'>
      {loading && <div aria-label='loading'>loading....</div>}
      <p>{myData?.name}</p>
      <p>{myData?.age}</p>
      <button onClick={clickHandler}>Click me</button>
    </div>
  );
}
describe('Test my app', () => {
  beforeEach(() => {
    jest.useFakeTimers();
  });

  afterEach(() => {
    jest.useRealTimers();
  });

  it('display data', async () => {
    render(<App />);

    userEvent.click(screen.getByText('Click me'));

    expect(screen.getByLabelText(/loading/i)).toBeInTheDocument();

    expect(await screen.findByText('subrato')).toBeInTheDocument();
    expect(screen.getByText('24')).toBeInTheDocument();
   
  });

  it('display data second time', async () => {
    render(<App />);

    userEvent.click(screen.getByText('Click me'));

    expect(screen.getByLabelText(/loading/i)).toBeInTheDocument();

    act(() => jest.advanceTimersByTime(5000));

    expect(screen.getByText('subrato')).toBeInTheDocument();
    expect(screen.getByText('24')).toBeInTheDocument();
   
  });
});

测试结果

 PASS  src/TimerExample.spec.tsx (9.001 s)
  Test my app
    √ display data (487 ms)
    √ display data second time (35 ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        14.997 s
Ran all test suites matching /TimerExample.spec.tsx/i.

关于javascript - 如何进行一个在检查元素外观之前等待 5 秒的测试(React 测试库),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70876086/

相关文章:

android - 当对函数进行单元测试时,当您模拟它使用的函数时,最佳实践是什么

javascript - 为什么我的自动完成功能不起作用?

javascript - 带计数器的 CryptoJS 解密

javascript - 在 React 中使用 props 或 deconstruction 定义用户

unit-testing - 如何在我的 wicket 单元测试中控制浏览器代理

javascript - 单元测试: Having trouble mocking a promise return to test my emit

PHP 还是 JS 模板引擎? (对于同一 html 的多个 block )

javascript - jQuery 选择器 - extjs - 转义括号

javascript - React Redux 为什么使用dispatch = useDispatch()?

css - react 应用程序 : How To Create A Black Overlay For A Picture?