-
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(cleanup): automatically cleanup if afterEach is detected #430
Conversation
cc @threepointone, I'd love your input here. |
Here's the one issue that I think people will bump up against. If people write their tests like this: const {getByText} = render(<Counter />)
const counterButton = getByText(/^count/i)
test('the counter is initialized to the initialCount', () => {
expect(counterButton).toHaveTextContent('0')
})
test('when clicked, the counter increments the click', () => {
fireEvent.click(counterButton)
expect(counterButton).toHaveTextContent('1')
}) Or similar, then they'll be in trouble because we'll auto-cleanup for them and their tests will break in a way that's really confusing. They should definitely not be writing their tests like that, but I know a lot of people do put each assertion in its own |
FWIW, I have this blog post written already: https://kentcdodds.com/blog/test-isolation-with-react |
55aa167
to
65ff32b
Compare
Codecov Report
@@ Coverage Diff @@
## master #430 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 3 4 +1
Lines 91 95 +4
Branches 12 13 +1
=====================================
+ Hits 91 95 +4
Continue to review full report at Codecov.
|
Bit dead today because of the release, so I'll be a while before responding haha. But I don't think you should merge this any time soon, at least not without thinking about it for a day or so. Seems like too little to warrant a major version bump. |
65ff32b
to
a67a3fc
Compare
src/__tests__/act.js
Outdated
@@ -1,7 +1,5 @@ | |||
import React from 'react' | |||
import {render, cleanup, fireEvent} from '../' | |||
|
|||
afterEach(cleanup) |
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.
Several of the tests were manually wiring up cleanup
even though they didn't need to before (and they certainly don't need to now), so I fixed those.
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.
There a bunch of docs with afterEach(cleanup)
too
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 made these unrelated polish changes to master so this PR could be slimmer.
I suspect that most of these people don't have cleanup configured in most of their tests at all 😬, unless they manually do |
🤔 I think I'm a fan of this model as a major release. Weighing the tradeoffs personally, this seems like it will save a lot more bugs than it will create. I've seen people get burned multiple times by not importing and running cleanup properly. If the primary downside is that some test suites will have to be refactored during the upgrade to be better isolated, that seems reasonable. |
a67a3fc
to
31b8dfc
Compare
You can disable this with the RTL_SKIP_CLEANUP environment variable if you so choose, but it's recommended to have cleanup work this way. Closes #428
31b8dfc
to
6862dd1
Compare
After considering this a lot, I've determined that we should go forward with this change. The Testing Library family of tools has a primary goal: To enable people to write tests which give them more confidence and are easier to maintain. The kinds of tests that this change could break do not give people more confidence nor are they easy to maintain. And the current requirement to have to wire up cleanup makes using react testing library harder (which is contrary to the goals of the library). This is worth a breaking change IMO. The "churn" will be a minimum and will only negatively impact people who are not using the library as documented anyway. And for people who have been doing things correctly by wiring up the So in a few hours I will be merging this unless there's good reason to not do so. |
Looks like this would be an auto-solve for testing-library/react-hooks-testing-library#76. I was confused when I looked at your PR, but then saw that cleanup essentially ends up calling |
How will this work with concurrent mode (.createRoot()/.unmount())? or do you not factor that in right now? |
// this ensures that tests run in isolation from each other | ||
if (typeof afterEach === 'function' && !process.env.RTL_SKIP_CLEANUP) { | ||
afterEach(async () => { | ||
await asyncAct(async () => {}) |
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.
Consider - if ther are any hanging promises after a test is finished, that probably means the user hasn't asserted on the actual stable state of the UI. So this would hide a probable bug.
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.
Maybe this is a similar concern with the async act() in cleanup-after-each, ouch. at least there it's explicit tho.
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.
if there are any hanging promises after a test is finished, that probably means the user hasn't asserted on the actual stable state of the UI.
I'm not sure I understand how this change impacts that at all. This change is doing exactly the same thing that cleanup-after-each
is doing. It's just wiring it up automatically.
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.
Maybe this shouldn't be an act(), but it should flush promises anyway. So if there are any stray async updates, the warning will fire, and the dev will account for it in their test.
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 not sure I understand how this change impacts that at all. This change is doing exactly the same thing that cleanup-after-each is doing. It's just wiring it up automatically.
I'm suggesting it should be removed from that too.
I don't know. I guess we don't factor that in right now. Currently you can only |
To be clear: all this change does is make it so people don't have to wire up cleanup-after-each themselves (which they should be doing). If they're doing that already, then this change will make 0 impact on them. So the only people who will experience any bumps in this transition are the people who are using RTL incorrectly. |
If you're going all in on a major update, why do it just for this one feature, and so soon, is my major concern. I think you should think deeply on the implications, and at least bounce around some ideas. Alternate idea for this 'feature': Custom describe/test helpers? You'd have a lot more freedom there too. |
I definitely don't want custom |
Also, I'm not as concerned about publishing major version bumps to my libraries. It's just a number, people using the current version get a great library. People who upgrade have very little work to do to upgrade (less than if we batched a ton of changes for a major version change). I personally feel like most people wont need to make any changes for this major version change, so upgrading to this version will require very minimal work. And if they don't bother upgrading that's fine too. |
Sure, it was a suggestion. I'm trying to point out that you're set on a major, then you can rethink stuff beyond this one feature. If you're set on making this change, go for it, I'll keep my feedback to myself. |
That's a good point. I'm definitely open to suggestions and feedback. I just thought I had already explained my thoughts around your feedback about the custom describe/test helpers. |
There's one other breaking change that we could potentially include with this one: testing-library/dom-testing-library#314 I'm just worried that this will be a significant change and there's too much inertia behind the |
+1 for major version bumps for anything that might even be remotely breaking. (I'll go back to lurking now) |
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.
Really like this being implemented by default.
I'm not a big fan of having side-effects in modules though but I guess we don't have any other choice.
I would like to have a pure import though (e.g. @testing-library/react/pure
) instead of the environment variables. Those are pretty iffy if you want to incrementally adopt isolated tests.
src/index.js
Outdated
// if we're running in a test runner that supports afterEach | ||
// then we'll automatically run cleanup afterEach test | ||
// this ensures that tests run in isolation from each other | ||
if (typeof afterEach === 'function' && !process.env.RTL_SKIP_CLEANUP) { |
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.
We should guard against process and process.env not being defined for people running their tests in actual browsers.
Co-Authored-By: Adrià Fontcuberta <[email protected]>
I feel the same way. I'm fine with the |
Actually, I think we'll support both. Because lots of people who would need to make this migration would probably prefer the |
405f61a
to
e0deaf7
Compare
Ok, both mechanisms are supported. So people who don't want this behavior can either set But 99% of people wont even know this is a thing (or want it) and that's a huge win. |
Basically, we're changing the default for the more common case. Before, 99% of people had to wire up the cleanup and 1% didn't bother (and their tests were probably not very good). Now, 99% of people don't have to do anything, 0.9% of people will have to figure out a better way to write tests, and 0.1% of people will have to figure out how to skip out of the auto-cleanup stuff. Those numbers are made up. It's probably even more favorable to be honest. |
Ok, this is going to go in the next few minutes. |
You can disable this with the RTL_SKIP_CLEANUP environment variable if you so choose, but it's recommended to have cleanup work this way. Closes #428 BREAKING CHANGE: If your tests were not isolated before (and you referenced the same component between tests) then this change will break your tests. You should [keep your tests isolated](https://kentcdodds.com/blog/test-isolation-with-react), but if you're unable/unwilling to do that right away, then you can either run your tests with the environment variable `RTL_SKIP_AUTO_CLEANUP` set to `true` or import `@testing-library/react/pure` instead of `@testing-library/react`.
BREAKING CHANGE: If you were using `debugDOM` before, use `prettyDOM` instead. Note that `debugDOM` is different from `debug` which you get back from `render`. That is unchanged.
e0deaf7
to
c231511
Compare
I'm going to upgrade @testing-library/dom with this PR as well. So we'll get a single release for both breaking changes (because we re-export everything from @testing-library/dom). |
Here it goooooes! |
🎉 This PR is included in version 9.0.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
Wow this is great Kent, thank you so much! Totally in favor of this change. Just wanted to chime in to say that I think the affected users will be higher than 1% or 0.1%. I do contractor work so I see many different codebases from different teams and companies often and the style you described in #430 (comment) is far more common than one would think. I suspect it might be because of the micro-optimization tendencies and that low-performance phobia that some developers have that they think that re-using the container/wrapper element across several tests will make their test suites faster. Or maybe they don't feel comfortable rendering the components each time on each tests because it doesn't feel DRY ? Regardless, I will not make up any numbers or statistics, and like I said I totally agree with the change, just wanted to provide a different perspective and expectations based on my personal anecdotal experience, just because I can think of many repos that I've worked with this year alone that I know will have test failures. |
You're probably right @reyronald. Hopefully this change will help people rethink their testing practices. That said, I decided to make disabling this behavior as easy as enabling the original behavior was: #435 |
What:
automatically call
cleanup
(with async act) ifafterEach
is detected.Why:
Closes #428
This effectively means that 90% of users wont even have to know about
cleanup
at all. Which is a huge improvement.How:
You can disable this with the
RTL_SKIP_CLEANUP
environment variable if you so choose, but it's recommended to have cleanup work this way.Checklist:
docs site Let's get this reviewed/merged first, then we can start working on the docs.