JSDOM is a JavaScript based headless browser that can be used to create a realistic testing environment.
Since enzyme's mount
API requires a DOM, JSDOM is required in order to use mount
if you are not already in a browser environment (ie, a Node environment).
For the best experience with enzyme, it is recommended that you load a document into the global scope before requiring React for the first time. It is very important that the below script gets run before React's code is run.
As a result, a standalone script like the one below is generally a good approach:
jsdom v10~
:
/* setup.js */ const { JSDOM } = require('jsdom'); const jsdom = new JSDOM('<!doctype html><html><body></body></html>'); const { window } = jsdom; function copyProps(src, target) { Object.defineProperties(target, { ...Object.getOwnPropertyDescriptors(src), ...Object.getOwnPropertyDescriptors(target), }); } global.window = window; global.document = window.document; global.navigator = { userAgent: 'node.js', }; global.requestAnimationFrame = function (callback) { return setTimeout(callback, 0); }; global.cancelAnimationFrame = function (id) { clearTimeout(id); }; copyProps(window, global);
Here is the sample of jsdom old API as well.
jsdom ~<v10
:
/* setup.js */ const { jsdom } = require('jsdom'); global.document = jsdom(''); global.window = document.defaultView; global.navigator = { userAgent: 'node.js', }; function copyProps(src, target) { const props = Object.getOwnPropertyNames(src) .filter(prop => typeof target[prop] === 'undefined') .reduce((result, prop) => ({ ...result, [prop]: Object.getOwnPropertyDescriptor(src, prop), }), {}); Object.defineProperties(target, props); } copyProps(document.defaultView, global);
describeWithDOM
API and clearing the document after every testIn 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.
It is important, however, to make sure that your tests using the global DOM APIs do not have leaky side-effects which could change the results of other tests. Until there is a better option, this is left to you to ensure.
When testing with JSDOM, the setup.js
file above needs to be run before the test suite runs. If you are using mocha, this can be done from the command line using the --require
option:
mocha --require setup.js --recursive path/to/test/dir
Jsdom requires node 4 or above. As a result, if you want to use it with mount
, you will need to make sure node 4 or iojs is on your machine. If you are stuck using an older version of Node, you may want to try using a browser-based test runner such as Karma.
Some times you may need to switch between different versions of node, you can use a CLI tool called nvm
to quickly switch between node versions.
To install nvm
, use the curl script from http://nvm.sh, and then:
nvm install 4
Now your machine will be running Node 4. You can use the nvm use
command to switch between the two environments:
nvm use 0.12
nvm use 4
© 2015 Airbnb, Inc.
Licensed under the MIT License.
https://airbnb.io/enzyme/docs/guides/jsdom.html