-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
feat: Use act to flush instead of custom implementation #768
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 4b62cc3:
|
3a7f185
to
e8f48ae
Compare
Codecov Report
@@ Coverage Diff @@
## master #768 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 4 4
Lines 109 109
Branches 16 16
=========================================
Hits 109 109
Continue to review full report at Codecov.
|
This looks good IMO, mostly because the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a huge fan of this change.
To be clear, could you give an example of a typical kind of way some folks are writing their tests with fake timers that won't work with this change and what they'd have to do to migrate?
@kentcdodds I think this relates to this issue we had after we changed the
Without this, it will fail IMO:
|
Ok, so after this change, folks only need to do this, correct? beforeEach(() => jest.useFakeTimers())
afterEach(() => jest.useRealTimers()) Thanks to auto-cleanup being wrapped in |
I think so.. Maybe @eps1lon will be able to confirm this :) |
Yep, that's what I think is the correct pattern for using fake timers. Otherwise you're creating an environment for a test that leaks to possibly unrelated files. Though I think we should add a warning to our And to re-iterate: This change is backwards incompatible. I suspect most people don't clean up their timers so we should probably release this as a major. |
Yep, makes sense. In my own tests, I'm thinking that I'll do this in my setup file: afterEach(() => jest.useRealTimers()) And then just call afterEach(() => {
jest.runOnlyPendingTimers()
jest.useRealTimers()
}) So not a ton will change for the way I do things (though I'm sure it will for others). In any case, I'm super jazzed about this change. Thanks! |
Let's think about other breaking changes we could make at this point as well... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, I tried this on https://github.com/kentcdodds/bookshelf and it works unless I upgrade to 2.11.0 of react-query: TanStack/query#909 (comment)
Still need to do some investigation there. I'm guessing it's a problem with react-query (because even without these changes, I start getting act warnings with that version of react-query), but I thought I'd mention it here to keep everyone informed.
Found the problem was with react-query. This change makes things better with that as well as it turns out. Unless anyone can think of other breaking changes we should consider, I think this is ready to go. |
@kentcdodds Yeah I only had this as a draft because I was hoping for some more tests in other repos. With bookshelf tested this looks fine by me. We had some pretty bad timing issues with React 17 in Material-UI and and already use patch internally. Without this patch we'll probably see some very odd bug reports for React 17 depending on the test runner/timers used. I just hope we don't swallow some missing act warnings but since we're not inside the test this seems safe to do. |
Let's do a beta release with this. |
Another thing to consider is whether we want to make any breaking changes to DOM Testing Library which would impact this lib and we'd like to bundle up... |
🎉 This PR is included in version 11.0.0-beta.1 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
BREAKING CHANGE: cleanup is now synchronous and wraps the unmounting process in `act`.
Replaces #514 with wrapping
unmountComponentAtNode
inact
i.e. we no longer flush microtasks manually. We need to wrap it inact
for React 17 so that effect cleanup functions are flushed.I extracted the original description into a test (as I understood the description) and the test is still passing with this chamge
The current implementation is problematic since it relies on a specific implementation of the scheduler i.e. a specific config. Some aspects already changed over time and might change again (considering main thread scheduling proposal for chrome). So having the custom implementation is a liability that already caused problems in the past.
As far as I can tell the underlying problem is tests that do not properly reset their timers. You shouldn't use fake timers between tests if you're using third party libraries. As soon as they use any async APIs in beforeEach or afterEach (like we're doing) you can get into incredibly hard to debug situations. At least we shouldn't be solving this problems since jest's fake timers aren't the only fake timers.
We also currently didn't handle any macrotasks so I don't even think we solved that many issues.
PS: Not having any repros (does not have to be deterministic) is problematic for code that is supposed to stay. I'd release this in a major or alpha to see if this causes any problems. My guess is that we should add a warning in our automatic cleanup if fake timers are still on.