jsdom is a blend of old and new code. Some of its older and less-touched corners may look different from newer work. Here we'll describe the modern setup, but you might encounter parts of the codebase that don't fit this model, or that seem unnecessarily baroque (like the directory structure in
In general, a web platform class (like
CSSStyleSheet) is specified using a language called Web IDL. Web IDL abstracts away a lot of the boilerplate involved in creating such classes, like type conversions, argument validation, and attribute/property reflection.
As such, most web platform classes present in jsdom are implemented in two parts:
- An IDL file, such as
Attr.idl, drawn more or less straight from the spec
- An implementation file, such as
Attr-impl.js, containing the relevant implementation logic
Our build step (
npm run prepublish) then generates a public API file (e.g.
Attr.js) which takes care of all the Web IDL-derived boilerplate, delegating to the implementation file for the important stuff. We then wire it together with a line in
lib/jsdom/living/index.js that exposes the generated class on all jsdom windows.
When contributing, the first question you should ask is:
Can I exhibit how the browsers differ from what jsdom is doing?
If you can, then you've almost certainly found a bug in or missing feature of jsdom, and we'd love to have your contribution. In that case, move on to:
What spec covers this potential contribution?
Almost all of our relevant functionality is covered in either the DOM Living Standard or the HTML Living Standard. There are various obsolete W3C specs ("DOM Level 2" etc.) that were never really implemented in browsers, and there is also the "DOM Level 4" W3C fork of the WHATWG DOM Living Standard. But we try to stick to the two main WHATWG specs for jsdom these days.
Other specs might pop up from time to time, especially in regard to CSS stuff. In general Mozilla's Servo project provides good guidance on relevant places to look. platform.html5.org is also pretty comprehensive.
Running the tests
First you'll want to
npm install. Then, configure your system to run the web platform tests as described in their README. If you can't get that set up correctly, the test runner will make a best-faith effort to run the tests hosted on http://w3c-test.org/, but this is pretty slow and fragile.
To run all the tests:
Web platform feature tests
All tests for web platform features (as opposed to features of jsdom itself, such as the
jsdom.* APIs) should be in web-platform-tests format. We have some infrastructure for running these directly against jsdom documents. So ideally, when contributing a bugfix or new feature, you can browser the web-platform-tests repository and find the test covering your work, and then just enable it in the manifest file. These tests are HTML files which use a special library called testharness.js to report their results.
However, the web-platform-tests project is not fully comprehensive. If you need to write your own test for a web platform feature, place it in our to-upstream directory. (It's so named because, over time, we hope to upstream these tests back to the web-platform-tests repository, so all browsers can benefit from them.) Note that you may need to create new directory structure, paralleling that of the main web-platform-tests repository.
To run all web-platform-tests:
npm run test-wpt
To run the to-upstream web-platform-tests:
npm run test-tuwpt
(Note for future reference for the maintainers: to update the submodules used for the web-platform-tests use the command
git submodule update --recursive --remote.)
jsdom API tests
If you are testing something that can only be accomplished through the jsdom API, and not inside a normal web browser, you'll want to write a different kind of test.
Our own test suites are currently being transitioned from nodeunit to mocha and chai. Some of the test suites are run using nodeunit, while others are run using mocha. So if you would like to run a specific test, you will have to first figure out which kind it is. A test file containing
describe("foo", ...) and
specify("foo", ...) calls is for mocha. A test file containing
exports[foo] = ... definitions is for nodeunit. After the transition finishes, there will be no nodeunit tests remaining.
All new tests should be written in the mocha format. To do that, simply add a file in the appropriate place (usually
test/jsdom) following the surrounding conventions. Then, add it to the manifest at
To run all mocha tests:
npm run test-mocha-all
To run a specific mocha test:
npm run test-mocha -- test/jsdom/env.js
To run older tests (and also web-platform-tests): see
npm run test-old
(The older tests also include a lot of web platform feature tests that are stuck in nodeunit format for now. We'd like to eventually move them to web-platform-tests format.)
Testing against the browser
As noted above, our own test suites are currently being transitioned from nodeunit to mocha. The nodeunit test cases are executed in Chrome using Selenium. The mocha test cases are executed in Chrome using karma.
To run all browser tests:
npm run test-browser
To run the karma tests in an iframe:
npm run test-karma
To run the karma tests in a web worker:
npm run test-karma-worker
To run the older tests:
npm run test-browser-old (requires Java installed and in your PATH)
This project cares about performance. There are a number of benchmarks that you can run. If you suspect your contribution has an impact on the performance of existing functionality, make sure you run the benchmarks before and after your change so that you can compare.
You can also run the benchmarks using the native DOM implementation of Chrome. A comparison with jsdom will automatically be made for you. If your new feature is much slower than the alternative DOM implementation, there might be an unexpected bottleneck somewhere in your change.
To run benchmarks in Node.js:
npm run benchmark
To run benchmarks in the browser:
npm run benchmark-browser, then open
benchmark/browser-runner.html in Chrome (or Chromium) and use the developer console to execute the
If you've read this far, you should know everything there is to know about contributing to jsdom. We have an active and full issue tracker that we'd love you to help with. Go find something broken or missing, and fix it!