![Happy DOM Logo](https://github.com/capricorn86/happy-dom/raw/master/docs/happy-dom-logo.jpg) # About [Happy DOM](https://github.com/capricorn86/happy-dom) is a JavaScript implementation of a web browser without its graphical user interface. It includes many web standards from WHATWG [DOM](https://dom.spec.whatwg.org/) and [HTML](https://html.spec.whatwg.org/multipage/). The goal of [Happy DOM](https://github.com/capricorn86/happy-dom) is to emulate enough of a web browser to be useful for testing, scraping web sites and server-side rendering. [Happy DOM](https://github.com/capricorn86/happy-dom) focuses heavily on performance and can be used as an alternative to [JSDOM](https://github.com/jsdom/jsdom). ### DOM Features - Custom Elements (Web Components) - Shadow Root (Shadow DOM) - Declarative Shadow DOM - Mutation Observer - Tree Walker - Fetch And much more.. ### Works With - [Google LitHTML](https://lit-html.polymer-project.org) - [Google LitElement](https://lit-element.polymer-project.org) - [React](https://reactjs.org) - [Angular](https://angular.io/) - [Vue](https://vuejs.org/) # Installation ```bash npm install happy-dom ``` # Usage ## Basic Usage A simple example of how you can use Happy DOM. ```javascript import { Window } from 'happy-dom'; const window = new Window(); const document = window.document; document.body.innerHTML = '
'; const container = document.querySelector('.container'); const button = document.createElement('button'); container.appendChild(button); // Outputs "
" console.log(document.body.innerHTML); ``` ## VM Context The default Window class is a [VM context](https://nodejs.org/api/vm.html#vm_vm_createcontext_sandbox_options). A [VM context](https://nodejs.org/api/vm.html#vm_vm_createcontext_sandbox_options) will execute JavaScript code scoped within the context where the Window instance will be the global object. ```javascript import { Window } from 'happy-dom'; const window = new Window({ innerWidth: 1024, innerHeight: 768, url: 'http://localhost:8080' }); const document = window.document; document.write(` Test page
`); // Will output "Test" console.log(document.querySelector('.container div').innerHTML); ``` ## Global Context Happy DOM exports a class called GlobalWindow, which can be used to run Happy DOM in the global context instead of the default behaviour of running in a [VM context](https://nodejs.org/api/vm.html#vm_vm_createcontext_sandbox_options). ```javascript import { Window, GlobalWindow } from 'happy-dom'; const vmWindow = new Window(); const globalWindow = new GlobalWindow(); // Will output "false" console.log(vmWindow.Array === global.Array); // Will output "true" console.log(globalWindow.Array === global.Array); globalWindow.eval('global.test = 1'); // Will output "1" console.log(global.test); ``` ## Server-Side Rendering of Web Components The example below will show you how to setup a Node [VM context](https://nodejs.org/api/vm.html#vm_vm_createcontext_sandbox_options) to render a page with custom elements (web components) in Happy DOM. We can then use a new web feature called [Declarative Shadow DOM](https://chromestatus.com/feature/5191745052606464) to include the shadow roots in the HTML output. [Declarative Shadow DOM](https://chromestatus.com/feature/5191745052606464) is only supported by Chromium based browsers. Unsupported browsers should safely fallback to being rendered using Javascript. ```javascript import { Window } from 'happy-dom'; const window = new Window({ innerWidth: 1024, innerHeight: 768, url: 'http://localhost:8080' }); const document = window.document; document.write(` Test page
Slotted content
`); /* Will output: Slotted content */ console.log(document.body.querySelector('div').getInnerHTML({ includeShadowRoots: true })); ``` ## Additional Features **whenAsyncComplete()** Returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that is resolved when all async tasks has been completed. ```javascript window.happyDOM.whenAsyncComplete().then(() => { // Do something when all async tasks are completed. }); ``` **cancelAsync()** This method will cancel all running async tasks. ```javascript window.setTimeout(() => { // This timeout will be canceled }); window.happyDOM.cancelAsync(); ``` **setInnerWidth()** Sets the property `window.innerWidth` and dispatches a "resize" event. ```javascript window.happyDOM.setInnerWidth(1920); ``` **setInnerHeight()** Sets the property `window.innerHeight` and dispatches a "resize" event. ```javascript window.happyDOM.setInnerHeight(1080); ``` **setURL()** Sets the property `window.location.href`. ```javascript window.happyDOM.setURL('https://localhost:3000'); ``` ## Settings Settings can be sent to the constructor or by setting them on the "window.happyDOM.settings" property. Set by constructor: ```javascript const window = new Window({ innerWidth: 1920, innerHeight: 1080, url: 'https://localhost:8080', settings: { disableJavaScriptFileLoading: true, disableJavaScriptEvaluation: true, disableCSSFileLoading: true, disableIframePageLoading: true, enableFileSystemHttpRequests: true } }); ``` Set by property: ```javascript const window = new Window(); window.happyDOM.settings.disableJavaScriptFileLoading = true; window.happyDOM.settings.disableJavaScriptEvaluation = true; window.happyDOM.settings.disableCSSFileLoading = true; window.happyDOM.settings.disableIframePageLoading = true; window.happyDOM.settings.enableFileSystemHttpRequests = true; ``` **disableJavaScriptFileLoading** Set it to "true" to disable JavaScript file loading. Defaults to "false". **disableJavaScriptEvaluation** Set it to "true" to completely disable JavaScript evaluation. Defaults to "false". **disableCSSFileLoading** Set it to "true" to disable CSS file loading in HTMLLinkElement. Defaults to "false". **disableIframePageLoading** Set it to "true" to disable page loading in HTMLIFrameElement. Defaults to "false". **enableFileSystemHttpRequests** Set it to "true" to enable file system HTTP requests using XMLHttpRequest. Defaults to "false". # Performance | Operation | JSDOM | Happy DOM | | ------------------------------------ | ------- | --------- | | Import / Require | 333 ms | 45 ms | | Parse HTML | 256 ms | 26 ms | | Serialize HTML | 65 ms | 8 ms | | Render custom element | 214 ms | 19 ms | | querySelectorAll('tagname') | 4.9 ms | 0.7 ms | | querySelectorAll('.class') | 6.4 ms | 3.7 ms | | querySelectorAll('[attribute]') | 4.0 ms | 1.7 ms | | querySelectorAll('[class~="name"]') | 5.5 ms | 2.9 ms | | querySelectorAll(':nth-child(2n+1)') | 10.4 ms | 3.8 ms | [See how the test was done here](https://github.com/capricorn86/happy-dom-performance-test) # Jest Happy DOM provide with a package called [@happy-dom/jest-environment](https://github.com/capricorn86/happy-dom/tree/master/packages/jest-environment) that makes it possible to use Happy DOM with [Jest](https://jestjs.io/). # Global Registration Happy DOM provide with a package called [@happy-dom/global-registrator](https://github.com/capricorn86/happy-dom/tree/master/packages/global-registrator) that can register Happy DOM globally. It makes it possible to use Happy DOM for testing in a Node environment. # Sponsors [RTVision](https://rtvision.com)