A JavaScript implementation of many web standards
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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