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
1 Answer
Reset to default 9The 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.