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

Pr/cleanup renderhooks #106

Closed

Conversation

apostolidhs
Copy link

@apostolidhs apostolidhs commented Jun 24, 2019

What:

Added global cleanup

Why:

We should unmount all the rendered hooks after each test so we can avoid memory leaks, flaky tests and fully test the hooks on the entire lifecycle.

How:

We keep the functions that unmount of the rendered hooks in a list and export a cleanup function that iterates the list and unmounts the hooks.

Checklist:

  • Documentation updated
  • Tests
  • Typescript definitions updated
  • Ready to be merged
  • Added myself to contributors table

I don't know if we should add a global option on the library that enables the cleanup feature. If a client runs the tests without calling the cleanup function, then we will collect a list of the unmount functions. This will may cause performance issues in a huge amount of tests.


Related issue #76

@codecov-io
Copy link

Codecov Report

Merging #106 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff          @@
##           master   #106   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files           1      1           
  Lines          39     43    +4     
  Branches        3      3           
=====================================
+ Hits           39     43    +4
Impacted Files Coverage Δ
src/index.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3701efb...df66140. Read the comment docs.

@@ -51,6 +53,11 @@ function resultContainer() {
}
}

function cleanup() {
unmounts.forEach((unmount) => unmount())
unmounts.length = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there significant difference between this and unmounts = []? That feels a bit clearer what it's doing to me, but I'm not sure if there are some other hidden benefits to this approach?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking to use either mutable or immutable approach. Personally, i prefer the immutable way as i suggested in the issue.

let unmounts = [];
unmounts = [...unmounts, unmount];
unmounts = [];

but i saw the way that you are using the resolvers

const resolvers = []; 
resolvers.push(resolver);

and i tried to follow the same pattern for consistency (mutable). I don't have a strong opinion on this, it's up to you.

@@ -73,6 +80,14 @@ function renderHook(callback, { initialProps, wrapper } = {}) {
})
const { unmount, update } = testRenderer

function unmountHook() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if someone calls this then then cleanup? does the second unmount fail? should unmountHook also remove the callback from unmounts (making this line no longer necessary at all)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see there is a test around this case. I personally feel that having unmountHook remove the callback from the unmounts array is bit clearer to what is happening rather than relying on the behaviour of unmount, but I don't care enough to block this for it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you, i will fix it.

@@ -0,0 +1 @@
afterEach(require('./src').cleanup)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be requireing ./lib so that it picks up the compiled version after publishing.

@mpeyper
Copy link
Member

mpeyper commented Jun 25, 2019

Hi @apostolidhs,

Thanks for taking the time to put this together. There was still some discussion in #76 about whether this should be called cleanup or unmountAll. I personally prefer cleanup, but I'll give others the opportunity to change my mind before we commit to this. @DaveStein feel free to weigh in on this one.

@mpeyper
Copy link
Member

mpeyper commented Jun 25, 2019

I just read the description properly and noticed your question about a global option.

Exploring that a bit, would it be enabled by default and they can disable globally if they have performance issues or is it disabled by default and they have to opt in to use it? We could enable it by default if they use the cleanup-after-each utility which would cover most use cases (in my opinion).

I also think it would take an awful lot of tests before someone actually saw an issue from not calling cleanup, so perhaps we don't worry until someone files an issue?

@mpeyper
Copy link
Member

mpeyper commented Jun 25, 2019

Just another thought, could we auto clear on a renderHook call? My test generally only have 1 to kick things off, then I use rerender and act calls for follow up renders.

Would this result in less cases where anyone actually needs to call cleanup or use the cleanup-after-each utility?

Would this result in more strange failures because something throwing on unmount would fail the next test?

@DaveStein
Copy link

My comment about unmountAll vs cleanup would just be a reference to how Jest has reset vs clear and the like. We might want cleanup to do all the things, and have unmountAll to do one form of cleanup. Otherwise, someone might mean to just unmountAll in tests today, then have something added to cleanup, and then have their tests break because it's doing something extra.

@apostolidhs
Copy link
Author

@mpeyper Can you take a look again? I committed the changes as a fixup.

  • Renames the cleanup -> unmountAll
  • Remove the unmounted hook from the unmounts

@mpeyper
Copy link
Member

mpeyper commented Jun 29, 2019

Sorry, I haven't had time to looks at this again yet (end of financial year is Oz and I work in financial services). I'm planning to look in the next few days.

@mpeyper
Copy link
Member

mpeyper commented Jun 30, 2019

@apostolidhs Those changes look good. I found them here, but they do not appear to be in this branch (I did notice the branch they are on is missing the pr/ prefix that this branch has). Can you add that commit to this PR?

The only bit I'm not sure on is where you've put the documentation (in the README). It would be great to get it into the docs site. Perhaps more or less what you have in the setup page and then some details on the unmountAll export in the API reference.

I can tidy all that up after we merge this if you prefer too. Just let me know.

@mpeyper
Copy link
Member

mpeyper commented Aug 8, 2019

I'm not sure where this is at right now, but react-testing-library has a PR open around auto cleanup, which might be something we want to explore instead of/in addition to this.

testing-library/react-testing-library#430

@mpeyper
Copy link
Member

mpeyper commented Oct 3, 2019

I'm going to close this as it appears to have gone stale (no updates in months and 4/6 changed files not have conflict.

I'm still very much in favour of this change, so if anyone wants to pick it up from here then I'm happy to continue. Alternatively, if you want to start fresh, that's cool too.

@mpeyper mpeyper closed this Oct 3, 2019
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 this pull request may close these issues.

None yet

4 participants