The Window object created by jsdom provides access to 180+ web standard interfaces, creating a complete browser-like environment for JavaScript execution and DOM manipulation.
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
// Access window
const window = dom.window;
// Or use destructuring
const { document } = dom.window;
const { Document, Element, Node, Event } = dom.window;jsdom implements a comprehensive set of web standards. All interfaces are accessible as properties of the window object.
Core DOM manipulation interfaces for working with nodes, elements, and documents.
// Core node types
interface Node {
// Node properties and methods per DOM specification
nodeType: number;
nodeName: string;
nodeValue: string | null;
parentNode: Node | null;
childNodes: NodeList;
firstChild: Node | null;
lastChild: Node | null;
previousSibling: Node | null;
nextSibling: Node | null;
ownerDocument: Document | null;
appendChild(node: Node): Node;
removeChild(node: Node): Node;
replaceChild(newChild: Node, oldChild: Node): Node;
insertBefore(newChild: Node, refChild: Node | null): Node;
cloneNode(deep: boolean): Node;
// ... and more
}
interface Element extends Node {
// Element properties and methods
tagName: string;
id: string;
className: string;
classList: DOMTokenList;
attributes: NamedNodeMap;
innerHTML: string;
outerHTML: string;
textContent: string;
getAttribute(name: string): string | null;
setAttribute(name: string, value: string): void;
removeAttribute(name: string): void;
hasAttribute(name: string): boolean;
querySelector(selectors: string): Element | null;
querySelectorAll(selectors: string): NodeList;
getElementsByTagName(name: string): HTMLCollection;
getElementsByClassName(names: string): HTMLCollection;
// ... and more
}
interface Document extends Node {
documentElement: Element;
head: HTMLHeadElement;
body: HTMLBodyElement;
title: string;
URL: string;
documentURI: string;
referrer: string;
cookie: string;
readyState: string;
contentType: string;
createElement(tagName: string): Element;
createTextNode(data: string): Text;
createDocumentFragment(): DocumentFragment;
createComment(data: string): Comment;
getElementById(id: string): Element | null;
getElementsByTagName(name: string): HTMLCollection;
getElementsByClassName(names: string): HTMLCollection;
querySelector(selectors: string): Element | null;
querySelectorAll(selectors: string): NodeList;
// ... and more
}Available Interfaces:
Node - Base node interfaceElement - Element interfaceDocument - Document interfaceXMLDocument - XML documentDocumentFragment - Document fragmentDocumentType - Doctype nodeAttr - Attribute nodeCharacterData - Base for text nodesText - Text nodeCDATASection - CDATA sectionComment - Comment nodeProcessingInstruction - Processing instructionDOMImplementation - DOM implementation factoryCollections:
NodeList - List of nodesHTMLCollection - Live collection of elementsNamedNodeMap - Named node map for attributesDOMStringMap - String map (dataset)DOMTokenList - Token list (classList)RadioNodeList - Radio button groupHTMLOptionsCollection - Options collectionHTMLFormControlsCollection - Form controlsStyleSheetList - Stylesheets collectionUsage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html>
<html>
<head><title>Test</title></head>
<body>
<div id="main" class="container">
<p>Hello</p>
<p>World</p>
</div>
</body>
</html>
`);
const { document } = dom.window;
// DOM manipulation
const main = document.getElementById("main");
console.log(main.tagName); // "DIV"
console.log(main.className); // "container"
// Create and append elements
const newP = document.createElement("p");
newP.textContent = "New paragraph";
main.appendChild(newP);
// Query selectors
const paragraphs = document.querySelectorAll("p");
console.log(paragraphs.length); // 3
// Modify content
document.title = "Updated Title";
document.body.innerHTML = "<h1>New Content</h1>";jsdom implements 76 HTML element interfaces, each with element-specific properties and methods.
Common HTML Elements:
interface HTMLElement extends Element {
// Common to all HTML elements
title: string;
lang: string;
dir: string;
hidden: boolean;
tabIndex: number;
dataset: DOMStringMap;
style: CSSStyleDeclaration;
click(): void;
focus(): void;
blur(): void;
// ... and more
}
interface HTMLAnchorElement extends HTMLElement {
href: string;
target: string;
rel: string;
// ... and more
}
interface HTMLInputElement extends HTMLElement {
type: string;
value: string;
checked: boolean;
disabled: boolean;
name: string;
placeholder: string;
form: HTMLFormElement | null;
// ... and more
}
interface HTMLFormElement extends HTMLElement {
action: string;
method: string;
elements: HTMLFormControlsCollection;
submit(): void;
reset(): void;
// ... and more
}All HTML Element Types:
HTMLElement, HTMLAnchorElement, HTMLAreaElement, HTMLAudioElement, HTMLBaseElement, HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDataElement, HTMLDataListElement, HTMLDetailsElement, HTMLDialogElement, HTMLDirectoryElement, HTMLDivElement, HTMLDListElement, HTMLEmbedElement, HTMLFieldSetElement, HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, HTMLHeadElement, HTMLHeadingElement, HTMLHtmlElement, HTMLHRElement, HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLLabelElement, HTMLLegendElement, HTMLLIElement, HTMLLinkElement, HTMLMapElement, HTMLMarqueeElement, HTMLMediaElement, HTMLMenuElement, HTMLMetaElement, HTMLMeterElement, HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement, HTMLOptionElement, HTMLOutputElement, HTMLParagraphElement, HTMLParamElement, HTMLPictureElement, HTMLPreElement, HTMLProgressElement, HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLSlotElement, HTMLSourceElement, HTMLSpanElement, HTMLStyleElement, HTMLTableElement, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, HTMLTableRowElement, HTMLTableSectionElement, HTMLTemplateElement, HTMLTextAreaElement, HTMLTimeElement, HTMLTitleElement, HTMLTrackElement, HTMLUListElement, HTMLUnknownElement, HTMLVideoElement
Usage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html>
<body>
<form id="myForm" action="/submit" method="post">
<input type="text" name="username" value="john">
<input type="password" name="password">
<button type="submit">Submit</button>
</form>
</body>
`);
const { document } = dom.window;
// Access form
const form = document.getElementById("myForm");
console.log(form.action); // "/submit"
console.log(form.method); // "post"
// Access form controls
const username = form.elements.namedItem("username");
console.log(username.value); // "john"
username.value = "jane";
// Form manipulation
form.reset();
console.log(username.value); // "" (reset clears value)Comprehensive event system supporting all standard web events.
interface EventTarget {
addEventListener(type: string, listener: EventListener, options?: AddEventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: EventListenerOptions): void;
dispatchEvent(event: Event): boolean;
}
interface Event {
type: string;
target: EventTarget | null;
currentTarget: EventTarget | null;
eventPhase: number;
bubbles: boolean;
cancelable: boolean;
defaultPrevented: boolean;
timeStamp: number;
preventDefault(): void;
stopPropagation(): void;
stopImmediatePropagation(): void;
// ... and more
}Event Types Available:
Event - Base eventUIEvent - UI events baseMouseEvent - Mouse eventsPointerEvent - Pointer eventsKeyboardEvent - Keyboard eventsTouchEvent - Touch eventsWheelEvent - Mouse wheelFocusEvent - Focus eventsInputEvent - Input eventsCompositionEvent - Text compositionCustomEvent - Custom eventsMessageEvent - Message passingErrorEvent - Error eventsProgressEvent - Progress eventsCloseEvent - WebSocket closeHashChangeEvent - URL hash changesPopStateEvent - History navigationStorageEvent - Storage changesPageTransitionEvent - Page transitionsBeforeUnloadEvent - Before unloadSubmitEvent - Form submissionTransitionEvent - CSS transitionsPromiseRejectionEvent - Promise rejectionsDeviceOrientationEvent - Device orientationDeviceMotionEvent - Device motionBlobEvent - Blob eventsUsage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html>
<body>
<button id="myButton">Click me</button>
</body>
`);
const { document, MouseEvent } = dom.window;
// Add event listener
const button = document.getElementById("myButton");
button.addEventListener("click", (event) => {
console.log("Button clicked!");
console.log("Event type:", event.type);
console.log("Target:", event.target.id);
});
// Dispatch event programmatically
const clickEvent = new MouseEvent("click", {
bubbles: true,
cancelable: true,
view: dom.window
});
button.dispatchEvent(clickEvent);
// Custom events
const customEvent = new CustomEvent("myCustomEvent", {
detail: { message: "Hello" }
});
document.addEventListener("myCustomEvent", (event) => {
console.log(event.detail.message); // "Hello"
});
document.dispatchEvent(customEvent);localStorage and sessionStorage interfaces.
interface Storage {
length: number;
getItem(key: string): string | null;
setItem(key: string, value: string): void;
removeItem(key: string): void;
clear(): void;
key(index: number): string | null;
}
// Access via window
window.localStorage: Storage;
window.sessionStorage: Storage;Usage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html><html></html>`, {
url: "https://example.org/"
});
const { window } = dom;
// Use localStorage
window.localStorage.setItem("username", "john");
window.localStorage.setItem("theme", "dark");
console.log(window.localStorage.getItem("username")); // "john"
console.log(window.localStorage.length); // 2
// Use sessionStorage
window.sessionStorage.setItem("tempData", "value");
// Storage quota
// Default: 5,000,000 code units per storage area
// Configurable via storageQuota optionXMLHttpRequest, WebSocket, and Headers interfaces.
interface XMLHttpRequest extends XMLHttpRequestEventTarget {
readyState: number;
response: any;
responseText: string;
responseType: string;
status: number;
statusText: string;
open(method: string, url: string, async?: boolean, username?: string, password?: string): void;
send(body?: Document | XMLHttpRequestBodyInit | null): void;
abort(): void;
setRequestHeader(name: string, value: string): void;
getResponseHeader(name: string): string | null;
getAllResponseHeaders(): string;
// ... and more
}
interface WebSocket extends EventTarget {
readonly url: string;
readonly readyState: number;
readonly bufferedAmount: number;
readonly protocol: string;
send(data: string | ArrayBuffer | Blob): void;
close(code?: number, reason?: string): void;
onopen: ((event: Event) => void) | null;
onmessage: ((event: MessageEvent) => void) | null;
onerror: ((event: Event) => void) | null;
onclose: ((event: CloseEvent) => void) | null;
}
interface Headers {
append(name: string, value: string): void;
delete(name: string): void;
get(name: string): string | null;
has(name: string): boolean;
set(name: string, value: string): void;
forEach(callback: (value: string, name: string) => void): void;
}Usage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM(``, {
url: "https://example.org/",
resources: "usable"
});
const { XMLHttpRequest, Headers } = dom.window;
// Use XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data");
xhr.onload = () => {
console.log(xhr.responseText);
};
xhr.send();
// Use Headers
const headers = new Headers();
headers.append("Content-Type", "application/json");
headers.append("Authorization", "Bearer token123");
console.log(headers.get("Content-Type")); // "application/json"Blob, File, FileList, and FileReader interfaces.
interface Blob {
readonly size: number;
readonly type: string;
slice(start?: number, end?: number, contentType?: string): Blob;
text(): Promise<string>;
arrayBuffer(): Promise<ArrayBuffer>;
}
interface File extends Blob {
readonly name: string;
readonly lastModified: number;
}
interface FileReader extends EventTarget {
readonly readyState: number;
readonly result: string | ArrayBuffer | null;
readonly error: DOMException | null;
readAsText(blob: Blob, encoding?: string): void;
readAsDataURL(blob: Blob): void;
readAsArrayBuffer(blob: Blob): void;
abort(): void;
}DOMParser and XMLSerializer for parsing and serializing documents.
interface DOMParser {
parseFromString(source: string, type: DOMParserSupportedType): Document;
}
type DOMParserSupportedType = "text/html" | "text/xml" | "application/xml" |
"application/xhtml+xml" | "image/svg+xml";
interface XMLSerializer {
serializeToString(root: Node): string;
}Usage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM();
const { DOMParser, XMLSerializer } = dom.window;
// Parse HTML
const parser = new DOMParser();
const doc = parser.parseFromString("<p>Hello</p>", "text/html");
console.log(doc.body.textContent); // "Hello"
// Parse XML
const xmlDoc = parser.parseFromString("<root><item/></root>", "text/xml");
console.log(xmlDoc.documentElement.tagName); // "root"
// Serialize
const serializer = new XMLSerializer();
const xmlString = serializer.serializeToString(xmlDoc);
console.log(xmlString); // "<root><item/></root>"Range and Selection for text selection and manipulation.
interface Range {
readonly startContainer: Node;
readonly startOffset: number;
readonly endContainer: Node;
readonly endOffset: number;
readonly collapsed: boolean;
readonly commonAncestorContainer: Node;
setStart(node: Node, offset: number): void;
setEnd(node: Node, offset: number): void;
selectNode(node: Node): void;
selectNodeContents(node: Node): void;
collapse(toStart?: boolean): void;
cloneContents(): DocumentFragment;
extractContents(): DocumentFragment;
deleteContents(): void;
insertNode(node: Node): void;
// ... and more
}
interface Selection {
readonly anchorNode: Node | null;
readonly anchorOffset: number;
readonly focusNode: Node | null;
readonly focusOffset: number;
readonly isCollapsed: boolean;
readonly rangeCount: number;
getRangeAt(index: number): Range;
addRange(range: Range): void;
removeRange(range: Range): void;
removeAllRanges(): void;
collapse(node: Node | null, offset?: number): void;
selectAllChildren(node: Node): void;
// ... and more
}NodeIterator and TreeWalker for DOM traversal.
interface NodeIterator {
readonly root: Node;
readonly whatToShow: number;
readonly filter: NodeFilter | null;
nextNode(): Node | null;
previousNode(): Node | null;
detach(): void;
}
interface TreeWalker {
readonly root: Node;
readonly whatToShow: number;
readonly filter: NodeFilter | null;
currentNode: Node;
parentNode(): Node | null;
firstChild(): Node | null;
lastChild(): Node | null;
previousSibling(): Node | null;
nextSibling(): Node | null;
previousNode(): Node | null;
nextNode(): Node | null;
}MutationObserver for watching DOM changes.
interface MutationObserver {
observe(target: Node, options?: MutationObserverInit): void;
disconnect(): void;
takeRecords(): MutationRecord[];
}
interface MutationRecord {
readonly type: string;
readonly target: Node;
readonly addedNodes: NodeList;
readonly removedNodes: NodeList;
readonly previousSibling: Node | null;
readonly nextSibling: Node | null;
readonly attributeName: string | null;
readonly attributeNamespace: string | null;
readonly oldValue: string | null;
}Usage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html><body><div id="target"></div></body>`);
const { document, MutationObserver } = dom.window;
const target = document.getElementById("target");
// Create observer
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
console.log("Mutation type:", mutation.type);
console.log("Added nodes:", mutation.addedNodes.length);
console.log("Removed nodes:", mutation.removedNodes.length);
});
});
// Start observing
observer.observe(target, {
childList: true,
attributes: true,
subtree: true
});
// Make changes
target.appendChild(document.createElement("p"));
target.setAttribute("class", "active");
// Stop observing
observer.disconnect();Custom element registry and shadow DOM support.
interface CustomElementRegistry {
define(name: string, constructor: CustomElementConstructor, options?: ElementDefinitionOptions): void;
get(name: string): CustomElementConstructor | undefined;
whenDefined(name: string): Promise<CustomElementConstructor>;
upgrade(root: Node): void;
}
interface ShadowRoot extends DocumentFragment {
readonly mode: string;
readonly host: Element;
// ... Element methods
}AbortController and AbortSignal for cancellation.
interface AbortController {
readonly signal: AbortSignal;
abort(reason?: any): void;
}
interface AbortSignal extends EventTarget {
readonly aborted: boolean;
readonly reason: any;
onabort: ((event: Event) => void) | null;
}Additional window-specific properties and interfaces.
window.location: Location; // URL and navigation
window.history: History; // Session history
window.navigator: Navigator; // Browser info
window.screen: Screen; // Screen info
window.performance: Performance; // Performance timing
window.crypto: Crypto; // Cryptography
window.console: Console; // Console (virtual)
// Timers
window.setTimeout(callback: Function, delay: number, ...args: any[]): number;
window.clearTimeout(id: number): void;
window.setInterval(callback: Function, delay: number, ...args: any[]): number;
window.clearInterval(id: number): void;
// Animation (with pretendToBeVisual: true)
window.requestAnimationFrame(callback: FrameRequestCallback): number;
window.cancelAnimationFrame(id: number): void;
// Form Data
window.FormData: FormData;
// URL and URLSearchParams
window.URL: typeof URL;
window.URLSearchParams: typeof URLSearchParams;
// Text Encoding
window.TextEncoder: typeof TextEncoder;
window.TextDecoder: typeof TextDecoder;
// Geometry
window.DOMRect: typeof DOMRect;
window.DOMRectReadOnly: typeof DOMRectReadOnly;Basic SVG element interfaces.
Available SVG Interfaces:
SVGElement, SVGGraphicsElement, SVGSVGElement, SVGGElement, SVGDefsElement, SVGDescElement, SVGMetadataElement, SVGTitleElement, SVGSymbolElement, SVGSwitchElement, and SVG data types (SVGAnimatedString, SVGNumber, SVGRect, etc.)
CSS Object Model (CSSOM) support via integrated libraries.
interface CSSStyleDeclaration {
[index: number]: string;
readonly length: number;
cssText: string;
getPropertyValue(property: string): string;
setProperty(property: string, value: string, priority?: string): void;
removeProperty(property: string): string;
item(index: number): string;
// CSS properties accessible as properties
color: string;
backgroundColor: string;
fontSize: string;
// ... and 100+ more CSS properties
}Usage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html>
<body>
<div id="box" style="color: red; font-size: 16px;"></div>
</body>
`);
const { document } = dom.window;
const box = document.getElementById("box");
// Access computed style
console.log(box.style.color); // "red"
console.log(box.style.fontSize); // "16px"
// Modify style
box.style.color = "blue";
box.style.backgroundColor = "yellow";
console.log(box.style.cssText);
// "color: blue; font-size: 16px; background-color: yellow;"XPath evaluation for querying DOM.
document.evaluate(
xpathExpression: string,
contextNode: Node,
namespaceResolver: XPathNSResolver | null,
resultType: number,
result: XPathResult | null
): XPathResult;Usage Example:
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html>
<body>
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</body>
`);
const { document, XPathResult } = dom.window;
// Evaluate XPath
const result = document.evaluate(
"//div[@class='item']",
document,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
console.log(result.snapshotLength); // 3
for (let i = 0; i < result.snapshotLength; i++) {
const node = result.snapshotItem(i);
console.log(node.textContent); // "Item 1", "Item 2", "Item 3"
}getBoundingClientRect() and properties like offsetTop return zeroslocation.hrefpretendToBeVisual option to simulate// GOOD: Access window directly
const { window } = dom;
const div = window.document.createElement("div");
// AVOID: Don't merge with Node.js global
// global.window = dom.window; // Don't do this!
// GOOD: Run code inside jsdom context
dom.window.eval('console.log(document.title);');
// GOOD: Use window constructors for type checks
console.log(div instanceof window.HTMLDivElement); // true
console.log(div instanceof HTMLDivElement); // false (different global)// Clean up when done
dom.window.close(); // Terminates timers, removes event listeners