Security News
Supply Chain Attack Detected in Solana's web3.js Library
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
The jsdom npm package is a pure-JavaScript implementation of many web standards, notably the WHATWG DOM and HTML Standards, for use with Node.js. It is designed to create a web browsing environment similar to what you would find in a web browser, allowing for the parsing and manipulation of HTML and XML documents. It can be used for testing web pages and JavaScript libraries in a Node.js environment.
DOM Manipulation
This feature allows you to manipulate the DOM of a document. The code sample demonstrates how to append a new list item to an unordered list.
const { JSDOM } = require('jsdom');
const dom = new JSDOM(`<ul><li>Item 1</li></ul>`);
const ul = dom.window.document.querySelector('ul');
ul.appendChild(dom.window.document.createElement('li')).textContent = 'Item 2';
console.log(dom.window.document.body.innerHTML);
Event Handling
This feature enables you to simulate and handle events. The code sample shows how to simulate a click event on a button and handle it by logging a message.
const { JSDOM } = require('jsdom');
const dom = new JSDOM(`<button id='myButton'>Click me</button>`);
const button = dom.window.document.querySelector('#myButton');
button.addEventListener('click', () => console.log('Button clicked!'));
button.click();
Fetching Remote Content
This feature allows you to fetch remote content and create a JSDOM instance from it. The code sample demonstrates fetching and logging the HTML content of a webpage.
const { JSDOM } = require('jsdom');
JSDOM.fromURL('https://example.com/').then(dom => {
console.log(dom.serialize());
});
Running Scripts
This feature allows you to run scripts within the context of the JSDOM instance. The code sample shows how to execute a script that changes the text content of the document body.
const { JSDOM } = require('jsdom');
const dom = new JSDOM(`<script>document.body.textContent = 'Hello, world!';</script>`);
console.log(dom.window.document.body.textContent);
Cheerio is a fast, flexible, and lean implementation of core jQuery designed specifically for the server. It does not implement a full web browser API as jsdom does, but it is often used for simpler DOM manipulation tasks and is faster due to its focus on a subset of use cases.
Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. It is more powerful for tasks like web scraping, automated testing, and rendering since it operates over a real browser, but it is heavier and more resource-intensive compared to jsdom.
PhantomJS is a headless WebKit scriptable with a JavaScript API. It has similar capabilities to Puppeteer but uses WebKit as the rendering engine instead of Chromium. It is no longer actively maintained, but it was once a popular choice for headless website testing.
A JavaScript implementation of the W3C DOM.
$ npm install jsdom
If this gives you trouble with errors about installing Contextify, especially on Windows, see below.
see: mailing list
Bootstrapping a DOM is generally a difficult process involving many error prone steps. We didn't want jsdom to fall into the same trap and that is why a new method, jsdom.env()
, has been added in jsdom 0.2.0 which should make everyone's lives easier.
You can use it with a URL
// Count all of the links from the Node.js build page
var jsdom = require("jsdom");
jsdom.env(
"http://nodejs.org/dist/",
["http://code.jquery.com/jquery.js"],
function (errors, window) {
console.log("there have been", window.$("a").length, "nodejs releases!");
}
);
or with raw HTML
// Run some jQuery on a html fragment
var jsdom = require("jsdom");
jsdom.env(
'<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom\'s Homepage</a></p>',
["http://code.jquery.com/jquery.js"],
function (errors, window) {
console.log("contents of a.the-link:", window.$("a.the-link").text());
}
);
or with a configuration object
// Print all of the news items on hackernews
var jsdom = require("jsdom");
jsdom.env({
url: "http://news.ycombinator.com/",
scripts: ["http://code.jquery.com/jquery.js"],
done: function (errors, window) {
var $ = window.$;
console.log("HN Links");
$("td.title:not(:last) a").each(function() {
console.log(" -", $(this).text());
});
}
});
or with raw JavaScript source
// Print all of the news items on hackernews
var jsdom = require("jsdom");
var fs = require("fs");
var jquery = fs.readFileSync("./jquery.js", "utf-8");
jsdom.env({
url: "http://news.ycombinator.com/",
src: [jquery],
done: function (errors, window) {
var $ = window.$;
console.log("HN Links");
$("td.title:not(:last) a").each(function () {
console.log(" -", $(this).text());
});
}
});
jsdom.env
is built for ease of use, which is rare in the world of the DOM! Since the web has some absolutely horrible JavaScript on it, as of jsdom 0.2.0 jsdom.env
will not process external resources (scripts, images, etc). If you want to process the JavaScript use one of the methods below (jsdom.jsdom
or jsdom.jQueryify
)
jsdom.env(string, [scripts], [config], callback);
The arguments are:
string
: may be a URL, file name, or HTML fragmentscripts
: a string or array of strings, containing file names or URLs that will be inserted as <script>
tagsconfig
: see belowcallback
: takes two arguments
error
: either an Error
object if something failed initializing the window, or an array of error messages from the DOM if there were script errorswindow
: a brand new window
Example:
jsdom.env(html, function (errors, window) {
// free memory associated with the window
window.close();
});
If you would like to specify a configuration object only:
jsdom.env(config);
config.html
: a HTML fragmentconfig.file
: a file which jsdom will load HTML from; the resulting window's location.href
will be a file://
URL.config.url
: sets the resulting window's location.href
; if config.html
and config.file
are not provided, jsdom will load HTML from this URL.config.scripts
: see scripts
above.config.src
: an array of JavaScript strings that will be evaluated against the resulting document. Similar to scripts
, but it accepts JavaScript instead of paths/URLs.config.done
: see callback
above.config.document
:
referer
: the new document will have this referercookie
: manually set a cookie value, e.g. 'key=value; expires=Wed, Sep 21 2011 12:00:00 GMT; path=/'
config.features
: see Flexibility
section below. Note: the default feature set for jsdom.env does not include fetching remote JavaScript and executing it. This is something that you will need to carefully enable yourself.Note that config.done
is required, as is one of config.html
, config.file
, or config.url
.
If you want to spawn a document/window and specify all sorts of options this is the section for you. This section covers the jsdom.jsdom
method:
var jsdom = require("jsdom").jsdom;
var doc = jsdom(markup, level, options);
var window = doc.createWindow();
markup
is an HTML/XML document to be parsed. You can also pass null
or an undefined value to get a basic document with empty <head>
and <body>
tags. Document fragments are also supported (including ""
), and will behave as sanely as possible (e.g. the resulting document will lack the head
, body
and documentElement
properties if the corresponding elements aren't included).
level
is null
(which means level3) by default, but you can pass another level if you'd like.
var jsdom = require("jsdom");
var doc = jsdom.jsdom("<html><body></body></html>", jsdom.level(1, "core"));
options
see the Flexibility section below.
One of the goals of jsdom is to be as minimal and light as possible. This section details how someone can change the behavior of Document
s on the fly. These features are baked into the DOMImplementation
that every Document
has, and may be tweaked in two ways:
Document
using the jsdom builder (require("jsdom").jsdom()
)var jsdom = require("jsdom").jsdom;
var doc = jsdom("<html><body></body></html>", null, {
features: {
FetchExternalResources : ["img"]
}
});
Do note, that this will only affect the document that is currently being created. All other documents will use the defaults specified below (see: Default Features).
require("jsdom").defaultDocumentFeatures = {
FetchExternalResources: ["script"],
ProcessExternalResources: false
};
Default features are extremely important for jsdom as they lower the configuration requirement and present developers a set of consistent default behaviors. The following sections detail the available features, their defaults, and the values that jsdom uses.
FetchExternalResources
["script"]
["script", "img", "css", "frame", "iframe", "link"]
or false
Enables/disables fetching files over the file system/HTTP.
ProcessExternalResources
["script"]
["script"]
or false
Disabling this will disable script execution (currently only JavaScript).
SkipExternalResources
false
/url to be skipped/
or false
/http:\/\/example.org/js/bad\.js/
Do not download and process resources with url matching a regular expression.
jsdom includes support for using the canvas package to extend any <canvas>
elements with the canvas API. To make this work, you need to include canvas as a dependency in your project, as a peer of jsdom. If jsdom can find the canvas package, it will use it, but if it's not present, then <canvas>
elements will behave like <div>
s.
var jsdom = require("jsdom");
var window = jsdom.createWindow();
console.log(window.document); // output: undefined
var jsdom = require("jsdom");
var doc = new (jsdom.level(1, "core").Document)();
console.log(doc.nodeName); // outputs: #document
var jsdom = require("jsdom").jsdom;
var document = jsdom("<html><head></head><body>hello world</body></html>");
var window = document.createWindow();
console.log(window.document.innerHTML);
// output: "<html><head></head><body>hello world</body></html>"
console.log(window.innerWidth);
// output: 1024
console.log(typeof window.document.getElementsByClassName);
// outputs: function
var jsdom = require("jsdom");
var window = jsdom.jsdom().createWindow();
jsdom.jQueryify(window, "http://code.jquery.com/jquery.js", function () {
window.$("body").append('<div class="testing">Hello World, It works</div>');
console.log(window.$(".testing").text());
});
var jsdom = require("jsdom").jsdom;
var window = jsdom().createWindow();
window.__myObject = { foo: "bar" };
var scriptEl = window.document.createElement("script");
scriptEl.src = "anotherScript.js";
window.document.body.appendChild(scriptEl);
// anotherScript.js will have the ability to read `window.__myObject`, even
// though it originated in Node!
level1/core 535/535 100%
level1/html 238/238 100%
level1/svg 527/527 100%
level2/core 283/283 100%
level2/html 706/706 100%
level2/style 15/15 100%
level2/extra 4/4 100%
level2/events 24/24 100%
level3/xpath 93/93 100%
window/index 7/7 100%
window/script 10/10 100%
window/frame 16/16 100%
sizzle/index 14/14 100%
jsdom/index 87/87 100%
jsdom/parsing 8/8 100%
jsdom/env 13/13 100%
jsonp/jsonp 1/1 100%
browser/contextifyReplacement 4/4 100%
browser/index 34/34 100%
------------------------------------------------------
TOTALS: 0/2619 failed; 100% success
First you'll want to npm install
. To run all the tests, use npm test
, which just calls node test/runner
.
Using test/runner
directly, you can slice and dice which tests your want to run from different levels. Usage is as follows:
test/runner --help
Run the jsdom test suite
Options:
-s, --suites suites that you want to run. ie: -s level1/core,1/html,html [string]
-f, --fail-fast stop on the first failed test
-h, --help show the help
-t, --tests choose the test cases to run. ie: -t jquery
Contextify is a dependency of jsdom, used for running <script>
tags within the
page. In other words, it allows jsdom, which is run in Node.js, to run strings of JavaScript in an isolated environment
that pretends to be a browser environment instead of a server. You can see how this is an important feature.
Unfortunately, doing this kind of magic requires C++. And in Node.js, using C++ from JavaScript means using "native modules." Native modules are compiled at installation time so that they work precisely for your machine; that is, you don't download a contextify binary from npm, but instead build one locally after downloading the source from npm.
For Mac and Linux users, this is usually fine. Their systems come preinstalled with the necessaries for compiling C++. For Windows users, however, things can be tricky. Thus, one of the most common problems with jsdom is trying to use it on Windows without the proper compilation tools installed. Here's what you need to compile Contextify, and thus to install jsdom, on Windows:
C:\Python27
.There are some slight modifications to this that can work; for example full versions of Visual Studio usually work, and sometimes you can even get an x64 version of Node.js working too. But it's tricky, so start with the basics!
FAQs
A JavaScript implementation of many web standards
The npm package jsdom receives a total of 26,154,798 weekly downloads. As such, jsdom popularity was classified as popular.
We found that jsdom demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.