Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

10.4.4 causing timeout issue with useEffect+jest.useFakeTimers #523

Closed
awesomeunleashed opened this issue Jul 8, 2020 · 10 comments · Fixed by #528
Closed

10.4.4 causing timeout issue with useEffect+jest.useFakeTimers #523

awesomeunleashed opened this issue Jul 8, 2020 · 10 comments · Fixed by #528

Comments

@awesomeunleashed
Copy link

  • @testing-library/react version: 10.4.4
  • Testing Framework and version: Jest 24.9.0 (Create React App)
  • DOM Environment: jsdom 14.1.0 (Create React App)

Relevant code or config:

// In a component
useEffect(() => {
  // any effect
}, [])

// In the tests
beforeEach(jest.useFakeTimers)
afterEach(jest.useRealTimers)

What you did:

I have a component that has a useEffect in it and its tests use jest.useFakeTimers. My tests for the component passed until I updated to @testing-library/react 10.4.4.

What happened:

The test now fails with this message:

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Error: Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

      at mapper (node_modules/jest-jasmine2/build/queueRunner.js:25:45)

Reproduction:

See https://github.com/awesomeunleashed/rtl-10-4-4-repro

Problem description:

I believe these tests should still be passing.

Suggested solution:

I imagine this has something to do with the scheduler changes in testing-library/react-testing-library#732, as useEffect and jest.useFakeTimers sound like scheduling-related things, but I don't see anything obviously related without knowing the code.

@awesomeunleashed awesomeunleashed changed the title 10.4.4 causing issue with useEffect+jest.useFakeTimers 10.4.4 causing timeout issue with useEffect+jest.useFakeTimers Jul 8, 2020
@kentcdodds
Copy link
Member

This should be resolved with testing-library/react-testing-library#739 which will be published in a moment. If it's not fixed in the next version, please comment here.

@awesomeunleashed
Copy link
Author

I updated my repro project to use 10.4.5, and I'm still seeing the same error.

@kentcdodds kentcdodds reopened this Jul 8, 2020
@kentcdodds
Copy link
Member

Rats. If anyone would like to dig a little bit to find what the issue is that would be welcome :-)

@marcosvega91
Copy link
Member

marcosvega91 commented Jul 8, 2020

As I can see from the code, the problem could be that cleanup is executed after jest.useRealTimers.

So when microtasks are flushed it will try to flush with realTimers instead of fakeTimers.

If this is the case a possible solution, that i really don't like but it is my first thought, is to override afterEach function putting at the beginning the cleanup. In this way we are sure that cleanup is run before everything

@MatanBobi
Copy link
Member

MatanBobi commented Jul 9, 2020

As I can see from the code, the problem could be that cleanup is executed after jest.useRealTimers.

So when microtasks are flushed it will try to flush with realTimers instead of fakeTimers.

If this is the case a possible solution, that i really don't like but it is my first thought, is to override afterEach function putting at the beginning the cleanup. In this way we are sure that cleanup is run before everything

Yeah it looks like that's the issue. I'll look into it today.
Doing something like this as @marcosvega91 suggested works:

afterEach(async () => {
  await cleanup()
  jest.useRealTimers()
})

@awesomeunleashed thanks for the reproduction, this is really helpful.

@kentcdodds
Copy link
Member

I think we may be able to make the cleanup work whether fake timers are enabled or not. I'll be thinking about this

@MatanBobi
Copy link
Member

MatanBobi commented Jul 9, 2020

It looks like what's happening here is that React used fakeTimers inside the scheduler package since it was used within the component,
that's why flushWork for the last work isn't being called and our scheduleCallback is never called (since the last work wasn't flushed).
This also works since it triggers the host callback react are waiting for:

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

@MatanBobi
Copy link
Member

MatanBobi commented Jul 14, 2020

This should be resolved with testing-library/react-testing-library#744 which was published a few hours ago.
Though, this touches a point we would like to explain deeper regarding the work with fake timers inside the tests.
@kentcdodds do you think we should keep this one open to track the documentation efforts you raised in testing-library/react-testing-library#743 (comment) ?
If so, maybe we can move it to the docs repo and if not, we can close it and open a new one in the docs repo.

@kentcdodds kentcdodds transferred this issue from testing-library/react-testing-library Jul 14, 2020
@kentcdodds
Copy link
Member

Transferred

@awesomeunleashed
Copy link
Author

Our tests pass with 10.4.6. Thanks, guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants