The jsdom

27
THE JSDOM

Transcript of The jsdom

THE JSDOM

WHAT IS JSDOM?

A JavaScript implementation of the DOM*, for use with Node.js**

* Actually much more than just the DOM

** Actually it runs in more places than just Node.js

2 YEARS AGO…

jsdom in action

what jsdom implements

the future of jsdom

JSDOM IN ACTION

jsdom.env({

url: "http://www.dotjs.eu/",

scripts: ["https://code.jquery.com/jquery-2.1.1.js"],

loaded(errors, window) {

console.log("Number of speakers:");

console.log(window.$(".section-speakers .thumbnail").length);

}

});

var testPage = fs.readFileSync("index.html", "utf8");

var desiredOutput = fs.readFileSync("out.txt", "utf8");

browserifyFile("entry.js").then(bundledJS => {

var window = jsdom(testPage).parentWindow;

var scriptEl = window.document.createElement("script");

scriptEl.textContent = bundledJS;

window.document.head.appendChild(scriptEl);

assert.equal(window.document.body.innerHTML, desiredOutput);

});

http.createServer((req, res) => {

var pageUrl = url.parse(req.url, true)["proxy-me"];

jsdom.env(pageUrl, (err, window) => {

var images = window.document.querySelectorAll("img");

Promise.all(Array.prototype.map.call(images, imgEl => {

return getImageContents(url, imgEl.src)

.then(rotateImage)

.then(rotatedCanvas => imgEl.src = rotatedCanvas.toDataURL());

})

.then(() => res.end(jsdom.serializeDocument(window.document)));

});

}).listen(5002);

ZOMBIE.JS

var browser = Browser.create();

browser.visit("/signup")

.then(() => {

browser.fill("email", "[email protected]");

browser.fill("password", "eat-the-living");

return browser.pressButton("Sign Me Up!");

})

.then(() => {

browser.assert.success();

browser.assert.text("title", "Welcome To Brains Depot");

});

FACEBOOK’S JEST

WHAT JSDOM IMPLEMENTS

JUST THE DOM?

NOPE.

• DOM

• HTML

• DOM Parsing & Serialization

• XHR

• URL

• CSS Selectors

• CSSOM

• (more crazy CSS specs…)

ACTUALLY, IT’S WORSE

(WE’RE FIXING THAT…)

WEB-PLATFORM-TESTS

https://github.com/w3c/web-platform-tests

FORTUNATELY, WE HAVE HELP

jsdom

parse5

cssom

csstyle

nwmatcher

xmlhttprequest

canvas

contextify

THE FUTURE OF JSDOM

TMPVAR/JSDOM#950

“In the browser, you can do:

window.document.querySelectorAll([

'link[type="text/xml"]',

'link[type="application/rss+xml"]',

'link[type="application/atom+xml"]'

]);

This doesn't work in jsdom.”

interface ParentNode {

...

[NewObject] NodeList querySelectorAll(DOMString selectors);

};

Document implements ParentNode;

https://dom.spec.whatwg.org/#parentnode

String(['a', 'b', 'c']) === 'a,b,c'

window.document.querySelectorAll([

'link[type="text/xml"]',

'link[type="application/rss+xml"]',

'link[type="application/atom+xml"]'

])

===

window.document.querySelectorAll(

'link[type="text/xml"],link[type="application/rss+xml"],\link[type="application/atom+xml"]'

)

WEBIDL

interface Attr {

readonly attribute DOMString? namespaceURI;

readonly attribute DOMString? prefix;

readonly attribute DOMString localName;

readonly attribute DOMString name;

attribute DOMString value;

attribute DOMString textContent; // alias of .value

readonly attribute Element? ownerElement;

readonly attribute boolean specified; // useless; always returns true

};

HTMLHRELEMENT.IDL

interface HTMLHRElement : HTMLElement {

[Reflect] attribute DOMString align;

[Reflect] attribute DOMString color;

[Reflect] attribute boolean noShade;

[Reflect] attribute DOMString size;

[Reflect] attribute DOMString width;

};

⇒ HTMLHRELEMENT.JS

class HTMLHRElement extends HTMLElement {

get align() { return String(this.getAttribute("align")); }

set align(v) { this.setAttribute("align", String(v)); }

get noShade() { return Boolean(this.getAttribute("noshade")); }

set noShade(v) {

if (v) { this.setAttribute("noshade", ""); }

else { this.removeAttribute("noshade"); }

}

https://github.com/domenic/webidl-class-generator

https://github.com/domenic/webidl-html-reflector

https://github.com/domenic/webidl-conversions

https://github.com/tmpvar/jsdom