mirror of
https://github.com/samsonjs/blog.git
synced 2026-04-10 11:45:57 +00:00
278 lines
No EOL
9.2 KiB
Markdown
278 lines
No EOL
9.2 KiB
Markdown
# jsdom
|
|
|
|
A javascript implementation of the W3C DOM.
|
|
|
|
## Install
|
|
|
|
npm install jsdom
|
|
|
|
or
|
|
|
|
git clone http://github.com/tmpvar/jsdom.git
|
|
cd jsdom
|
|
npm link
|
|
|
|
## Human contact
|
|
|
|
see: [mailing list][]
|
|
|
|
[mailing list]: http://groups.google.com/group/jsdom
|
|
|
|
|
|
|
|
|
|
## Easymode
|
|
|
|
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.
|
|
|
|
with URL
|
|
|
|
// Count all of the links from the nodejs build page
|
|
var jsdom = require("jsdom");
|
|
|
|
jsdom.env("http://nodejs.org/dist/", [
|
|
'http://code.jquery.com/jquery-1.5.min.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="http://jsdom.org>JSDOM\'s Homepage</a></p>', [
|
|
'http://code.jquery.com/jquery-1.5.min.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({
|
|
html: 'http://news.ycombinator.com/',
|
|
scripts: [
|
|
'http://code.jquery.com/jquery-1.5.min.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-1.6.2.min.js").toString();
|
|
|
|
jsdom.env({
|
|
html: '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());
|
|
});
|
|
}
|
|
});
|
|
|
|
### How it works
|
|
`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(html, [scripts], [config], callback)
|
|
|
|
- `html` (**required**)
|
|
May be a url, html fragment, or file
|
|
|
|
- `scripts` (**optional**)
|
|
May contain files or urls
|
|
|
|
- `callback` (**required**)
|
|
Takes 2 arguments:
|
|
- `errors` : array of errors
|
|
- `window` : a brand new window
|
|
|
|
_example:_ jsdom.env(html, function(`errors`, `window`) {})
|
|
|
|
|
|
If you would like to specify a configuration object
|
|
|
|
jsdom.env({ /* config */ })
|
|
|
|
- config.html : see `html` above
|
|
- 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 referer
|
|
- cookie : manually set a cookie value i.e. `'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.
|
|
|
|
## For the hardcore
|
|
|
|
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,
|
|
doc = jsdom(markup, level, options),
|
|
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 (eg. 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'),
|
|
doc = jsdom.jsdom('<html><body></body></html>', jsdom.dom.level1.core)
|
|
|
|
- `options` see the **Flexibility** section below
|
|
|
|
### Flexibility
|
|
|
|
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:
|
|
|
|
1. When you create a new `Document` using the jsdom builder (`require('jsdom').jsdom()`)
|
|
|
|
var jsdom = require('jsdom').jsdom,
|
|
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)
|
|
|
|
2. Previous to creating any documents you can modify the defaults for all future documents
|
|
|
|
require('jsdom').defaultDocumentFeatures = {
|
|
FetchExternalResources : ['script'],
|
|
ProcessExternalResources : false,
|
|
MutationEvents : false,
|
|
QuerySelector : false
|
|
}
|
|
|
|
|
|
|
|
#### Default Features
|
|
|
|
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`
|
|
_Default_: ['script']
|
|
_Allowed_: ['script', 'img', 'css', 'frame', 'link'] or false
|
|
|
|
Enables/Disables fetching files over the filesystem/http
|
|
|
|
`ProcessExternalResources`
|
|
_default_: ['script']
|
|
_allowed_: ['script'] or false
|
|
|
|
Disabling this will disable script execution (currently only javascript).
|
|
|
|
`MutationEvents`
|
|
_default_: '2.0'
|
|
_allowed_ : '2.0' or false
|
|
|
|
Initially enabled to be up to spec. Disable this if you do not need mutation events and want jsdom to be a bit more efficient.
|
|
|
|
**Note**: `ProcessExternalResources` requires this to be enabled
|
|
|
|
`QuerySelector`
|
|
_default_ : false
|
|
_allowed_ : true
|
|
|
|
This feature is backed by [sizzle][] but currently causes problems with some libraries. Enable this if you want `document.querySelector` and friends, but be aware that many libraries feature detect for this, and it may cause you a bit of trouble.
|
|
|
|
[sizzle]:http://sizzlejs.com/
|
|
|
|
# More Examples
|
|
|
|
## Creating a document-less window
|
|
|
|
var jsdom = require("jsdom"),
|
|
window = jsdom.createWindow();
|
|
|
|
console.log(window.document);
|
|
// output: undefined
|
|
|
|
## Creating a document
|
|
var jsdom = require("jsdom"),
|
|
doc = new (jsdom.dom.level1.core.Document)();
|
|
console.log(doc.nodeName);
|
|
// outputs: #document
|
|
|
|
## Creating a browser-like BOM/DOM/Window
|
|
|
|
var jsdom = require("./lib/jsdom").jsdom,
|
|
document = jsdom("<html><head></head><body>hello world</body></html>"),
|
|
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
|
|
|
|
|
|
## jQueryify
|
|
|
|
var jsdom = require("jsdom"),
|
|
window = jsdom.jsdom().createWindow();
|
|
|
|
jsdom.jQueryify(window, 'http://code.jquery.com/jquery-1.4.2.min.js' , function() {
|
|
window.$('body').append('<div class="testing">Hello World, It works</div>');
|
|
console.log(window.$('.testing').text());
|
|
});
|
|
|
|
# Test Compliance:
|
|
|
|
level1/core 531/531 100%
|
|
level1/html 238/238 100%
|
|
level1/svg 527/527 100%
|
|
level2/core 283/283 100%
|
|
level2/html 687/687 100%
|
|
level2/style 4/4 100%
|
|
level2/extra 4/4 100%
|
|
level3/xpath 93/93 100%
|
|
window/index 5/5 100%
|
|
window/script 8/8 100%
|
|
window/frame 14/14 100%
|
|
sizzle/index 12/15 80%
|
|
jsdom/index 63/63 100%
|
|
--------------------------------------
|
|
TOTALS: 3/2472 failed; 99% success
|
|
TIME: 16730ms
|
|
|
|
## Running the tests
|
|
|
|
First you'll want to `npm install -g nodeunit` then `npm install --dev`
|
|
|
|
Using `test/runner` 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 |