最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to make a test that will wait 5 seconds before check element appearance (React testing lib) - Stack Overflow

programmeradmin2浏览0评论

In my react ponent, I have an element that is appearing after 5 seconds.

I want to make a test that will check does element appear after 5 sec with jest fake timers, but can not make it work...

What I am doing wrong here?

One of the examples is not working:

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();
    });
  });

Second example:

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();
  });

In my react ponent, I have an element that is appearing after 5 seconds.

I want to make a test that will check does element appear after 5 sec with jest fake timers, but can not make it work...

What I am doing wrong here?

One of the examples is not working:

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();
    });
  });

Second example:

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();
  });

Share Improve this question edited Jan 27, 2022 at 9:36 Mark James asked Jan 27, 2022 at 9:23 Mark JamesMark James 5686 gold badges19 silver badges51 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 9

The general rule of thumb of using await findBy query and await waitFor is that you should use

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.

The same is mentioned in the official documentation of the dom-testing-library.


Now ing to your concern, you need to use jest.useFakeTimer() to enable fake timers that will help in mocking the setTimeout and other timer functions.

The same is mentioned here in official docs.

useFakeTimer works with the async methods, however, if we want to work with sync methods like getBy queries then we have to use jest.advanceTimersByTime(5000) to move your test 5 (any specified time) seconds ahead of it. (example given below)

In the following example, I reproduce the concern that you have raised. I think this might help.

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();
   
  });
});

Test Result

 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.
发布评论

评论列表(0)

  1. 暂无评论