Hi there,
We use an approach similar to the one described here in order to expose document and window globals to the Node global object.
Unfortunately, we just had an issue where we upgraded jsdom to 9.4.0, and several DOM globals stopped being exposed (FormData, Event). They changed these properties to be non-enumerable. We were able to fix it in our app by just referencing window.FormData, window.Event, etc.
jsdom's official approach about setting browser globals in a Node environment is "this is wrong and you shouldn't do it": https://github.com/tmpvar/jsdom/wiki/Don't-stuff-jsdom-globals-onto-the-Node-global
They suggest a couple of workarounds. Using window explicitly is the approach we took. Another approach is wrapping your entire test bundle and executing it inside a JSDom function. _(aside: I'm still not sure how to stitch this together with webpack, babel, etc. Their example mixes require and filesystem reads, which doesn't feel right vs. import statements.)_
jsdom's reasoning for avoiding exposing these globals is:
"[it] causes all these properties to be shared not only across all your tests, but across your entire Node.js process."
But to make things interesting, there's also this bit from Enzyme's docs, which says React doesn't play nicely when you start switching out document in between tests:
In previous versions of enzyme, there was a public describeWithDOM API which loaded in a new JSDOM document into the global namespace before every test, ensuring that tests were deterministic and did not have side-effects.
This approach is no longer recommended. React's source code makes several assumptions about the environment it is running in, and one of them is that the global.document that is found at "require time" is going to be the one and only document it ever needs to worry about. As a result, this type of "reloading" ends up causing more pain than it prevents.
We're kind of stuck between a rock and a hard place here, with enzyme saying "don't do this" and jsdom saying "don't do that".
Any feedback from other enzyme users in the same position, or clarity from the maintainers, would be much appreciated.
References:
https://github.com/tmpvar/jsdom/issues/1551
https://github.com/rstacruz/jsdom-global/issues/6
https://github.com/rstacruz/jsdom-global/pull/7#issuecomment-230321646
https://github.com/tmpvar/jsdom/issues/1549#issue-163608781
This is related: https://github.com/airbnb/enzyme/issues/483
I think this documentation on setting up JSDOM to use mount() on Node is still wrong. I'm getting the following error when I try running the setup script:
/Users/avrameisner/Development/admin_api/compiled/test/client/setupJSDOM.js:8
Object.keys(document.defaultView).forEach(function (property) {
^
TypeError: Cannot convert undefined or null to object
at Function.keys (<anonymous>)
at Object.<anonymous> (/Users/avrameisner/Development/admin_api/compiled/test/client/setupJSDOM.js:8:8)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.require (module.js:498:17)
at require (internal/module.js:20:19)
at /Users/avrameisner/Development/admin_api/node_modules/mocha/bin/_mocha:345:3
at Array.forEach (native)
at Object.<anonymous> (/Users/avrameisner/Development/admin_api/node_modules/mocha/bin/_mocha:344:10)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:425:7)
at startup (bootstrap_node.js:146:9)
at bootstrap_node.js:540:3
error Command failed with exit code 1.
Instead of Object.keys, you should be using Object.getOwnPropertyDescriptors and applying all of those - which would catch all non-enumerables too.
Not only are the Enzyme docs advocating a JSDOM anti-pattern, but they now seem to be using an old API as well. Since this config seems so fundamental to running Enzyme, an update would be much appreciated.
Most helpful comment
Not only are the Enzyme docs advocating a JSDOM anti-pattern, but they now seem to be using an old API as well. Since this config seems so fundamental to running Enzyme, an update would be much appreciated.