-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
Proposal: Sandbox setImmediate() in jsdom environment #11204
Comments
I think this is a good idea 👍 I think ideally we'd throw errors on any work after test teardown (we currently throw on Making EDIT: Most of ny reply here applies more to #11202, so I guess ignore the above! 😀 I 100% agree they should behave consistently, regardless of whether we want to throw, warn or do nothing. Since the "OG timers" ignore, we should replicate that behavior in We probably shouldn't have
|
Yeah. I think of it as kind of a "Stage 2" to come after this. Maybe a config option / new default? It would be pretty disruptive to enforce this in the existing codebase. Note that even in this mode, it may not always possible to cancel stuff (e.g. third party code may schedule it). But maybe Jest could enforce that you
I think with manual control it's not as much of an issue because at least they won't run in a dead environment on their own. Which is a problem with
So this is a bit thorny. It exists in Node and IE. It's unlikely more browsers would add it, but it probably doesn't hurt to have it? We're actually considering relying on it in React (when available) because it maps the closest to the semantics we need in the browser. Even though in practice we use a |
Yep, I touched on that in #11202. I agree it probably needs to be configurable (and deffo not something we should do now).
Makes sense 👍
I don't think we should remove it now (mostly as v27 is already packed with breaking changes), but I do think we should in a future version. Nothing would stop React from choosing to extend the default JSDOM environment in the same way Jest does today (by just assigning the one. from Node into the global of the test), but I think out of the box Jest's DOM environment should be as realistic as possible so code that runs in a test does not explode at runtime in a real browser. |
React itself doesn't have a particular test-specific setup (e.g. even CRA is just one of many and is also losing relevance), so I don't know where we'd do that. I'm actually not sure what we'd use in this case. |
I meant in a custom test environment: https://github.com/facebook/react/blob/1d1e49cfa453b58769e87c3c8d321024d58c948f/scripts/jest/config.base.js#L27-L28 |
Ah. So my comment is about React projects, not React itself. |
I think another long-term option is if jsdom implements MessageChannel but in a way that auto-closes all ports on window close. |
We've discussed this more with the team. Step 1: Sandbox I think this would satisfy our requirements and matches what you've been saying. Does this sound good? What timeline can we think of for releasing Step 1? Or would you jump to Step 2 right away? |
I don't think it's necessarily worth it to spend time on sandboxing something we're gonna remove? We're currently in a pre-release for a new major, so we could just remove it right away, but I don't feel strongly about it. If you're up for sending a PR sandboxing it and it would be helpful for React in their tests I'm fine with that and just mark it for removal later. If you don't want to use it we can just remove it now. As for |
To be clear, the concern here is not with React internal tests, but with tests of everyone using React with Jest today. We want to do a bugfix in React but it would effectively break a bunch of tests for people using jest+jsdom. So our fix is dependent on the jest+jsdom fix. This is why I was hoping we could do the less aggressive fix in a patch (isolation) and then the more aggressive one in a major (removal). So that as many people get the update as possible. |
So that when we release React with a fix, we can say "just bump your jsdom environment" to get rid of the crashing tests. |
Aha! Gotcha. I'm happy to land a patch making it work better - regardless of whether we remove it later or not, the behavior you've suggested (clearing on teardown) makes sense to me. Note that the change will only be part of Jest 27, but I do think people can use |
Hm. If we're going to do a major anyway, then it seems like it makes sense to just remove it. |
We're currently on But yes, I'd rather not attempt to do some git magic to get Lerna to not be confused by going back and making a new 26 release. React could release a custom env if you want to help users out that extra mile? Overriding |
I think we can do this as an intermediate step later if the update to 27 is too hard for people. |
Sounds good 👍 Do you wanna send a PR removing it? If not I'll get to it this weekend or next week |
If you can do it I'd appreciate it. |
I opened a PR at #11222. Our example using /cc @kentcdodds @eps1lon |
@gaearon do you need a release of this (it'd be a pre-release, but still)? |
Yes, that would be helpful. |
Cool, |
FWIW, I hope to release it stable during or right after Easter. Gonna be stuck at home regardless, so should be able to find the time to wrap it up |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
🚀 Feature Proposal
Currently,
setTimeout
andsetInterval
are sandboxed in the Jest jsdom environment.Concretely, the Jest jsdom environment calls
window.close()
which will clear all timers:However,
setImmediate
is not sandboxed like this.The proposal is to sandbox
setImmediate
in the jsdom environment. Concretely, let’s clear all the pending immediates right after thewindow.close()
call for consistency. This prevents running them at the time that DOM is already torn down, and we're in an invalid state.To implement this, we would expose a wrapper that tracks the immediate IDs, removes IDs from the set when the immediate runs, and calls the underlying
clearImmediate
on the whole set when jsdom shuts down.Motivation and Example
Jest source code explicitly calls this out as "for now it's OK" which signals to me that this was anticipated as a possible problem.
The motivation is that we want to start using
setImmediate
in more places, but Jest makes it difficult because by the time immediates run, the jsdom environment is already torn down.This works (
setTimeout
is effectively ignored after jsdom shutdown):but this doesn't (
setImmediate
still runs after jsdom shutdown):The proposal is to remove this inconsistency.
The proposal only concerns the Jest jsdom environment because it already sandboxes timers, and jsdom environment is useless after teardown. I don't think this is needed in a plain Node environment.
The text was updated successfully, but these errors were encountered: