`userEvent.click` fails due to timeout when used with `jest.useFakeTimers`
See original GitHub issue@testing-library/user-eventversion:14.0.0-beta.7
- Testing Framework and version:
jestversion:27.4.7,@testing-library/jest-domversion5.15.1,@testing-library/reactversion12.1.2 - DOM Environment:
jsdomversion19.0.0
Relevant code or config
// Dummy.js
import React from "react";
const Dummy = (props) => {
const clickHandler = () => {
setTimeout(() => {
props.onClick();
}, 500);
};
return <button onClick={clickHandler}>Click me</button>;
};
export default Dummy;
// Dummy.test.js
import React from "react";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import userEvent from "@testing-library/user-event";
import Dummy from "./Dummy";
// Fails
test("onClick prop is called on button (userEvent, fakeTimer)", async () => {
jest.useFakeTimers();
const user = userEvent.setup();
const onClick = jest.fn();
render(<Dummy onClick={onClick} />);
const button = screen.getByRole("button");
await user.click(button);
jest.runOnlyPendingTimers();
expect(onClick).toHaveBeenCalledTimes(1);
jest.useRealTimers();
});
What you did:
Dummy component calls onClick prop after a delay when its button is clicked. I tried testing it using userEvent.click alongside jest.fakeTimers to avoid waiting for the delay.
What happened:
The test onClick prop is called on button (userEvent, fakeTimer) fails due to timeout.
npx jest output
FAIL client/src/dummy/Dummy.test.js (11.923 s)
✕ onClick prop is called on button (userEvent, fakeTimer) (5014 ms)
● onClick prop is called on button (userEvent, fakeTimer)
thrown: "Exceeded timeout of 5000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
19 |
20 | // Fails
> 21 | test.only("onClick prop is called on button (userEvent, fakeTimer)", async () => {
| ^
22 | jest.useFakeTimers();
23 | const user = userEvent.setup();
24 | const onClick = jest.fn();
at Object.<anonymous> (client/src/dummy/Dummy.test.js:21:6)
Reproduction repository: https://codesandbox.io/s/user-event-fake-timers-lwb65 (Source files are provided but I couldn’t get the tests to run on codesandbox)
Problem description:
The test fails due to timeout. The problem arises when using jest.useFakeTimers. The line await user.click(button) never completes.
Suggested solution:
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:10 (4 by maintainers)
Top Results From Across the Web
No results found
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

I wound up here looking for an answer to this problem. It seems to me that a better solution than described above is to make use of
userEvent.setup({ advanceTimers: jest.advanceTimersByTime }): instead of disabling the delay entirely, use the provided mechanism to advance the fake timers when needed.The implementation waits for delay seconds per
setTimeoutbetween actions. When fake timers are activated,new Promise(r => setTimeout(r, delay))only resolves when the timer is advanced.As delaying to the next macrotask is default behavior in
v14, maybe #585 is more pressing now. Maybe we should add a paragraph about fake timers in a more prominent place in the documentation - maybe in the introduction or in an extra FAQ section.For now you can disable delaying the next action per
userEvent.setup({delay: null}).Edit: fixed link