`userEvent.click` fails due to timeout when used with `jest.useFakeTimers`

See original GitHub issue
  • @testing-library/user-event version: 14.0.0-beta.7
  • Testing Framework and version: jest version: 27.4.7, @testing-library/jest-dom version 5.15.1, @testing-library/react version 12.1.2
  • DOM Environment: jsdom version 19.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:closed
  • Created 2 years ago
  • Reactions:2
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

16reactions
anomiexcommented, Jun 30, 2022

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.

9reactions
ph-fritschecommented, Jan 16, 2022

The implementation waits for delay seconds per setTimeout between 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

Read more comments on GitHub >

github_iconTop Results From Across the Web

No results found

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found