The jsdom

domenicdenicola 9,235 views 27 slides Jan 05, 2015
Slide 1
Slide 1 of 27
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27

About This Presentation

Two years ago I inherited jsdom, a project of breathtaking scope. In essence, it aims to simulate a browser in JavaScript, by implementing JavaScript versions of a wide variety of web standards (much more than just the DOM). While maintaining jsdom for the last two years, and eventually bringing it ...


Slide Content

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

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