CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jsdom

A JavaScript implementation of many web standards

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

common-patterns.mddocs/guides/

Common Patterns

Practical examples for everyday jsdom tasks.

Basic DOM Manipulation

const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html><body></body>`);
const { document } = dom.window;

// Create and manipulate elements
const div = document.createElement("div");
div.id = "main";
div.className = "container";
div.textContent = "Hello World";
document.body.appendChild(div);

// Query elements
const main = document.getElementById("main");
const allDivs = document.querySelectorAll("div");

Working with Events

const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html><body><button id="btn">Click</button></body>`);
const { document, MouseEvent } = dom.window;

const button = document.getElementById("btn");
button.addEventListener("click", (event) => {
  console.log("Button clicked!");
});

// Dispatch event programmatically
const clickEvent = new MouseEvent("click", {
  bubbles: true,
  cancelable: true,
  view: dom.window
});
button.dispatchEvent(clickEvent);

Loading from URL

const { JSDOM } = require("jsdom");

async function scrapePage() {
  const dom = await JSDOM.fromURL("https://example.com/", {
    resources: "usable",
    runScripts: "dangerously"
  });
  
  const title = dom.window.document.title;
  const paragraphs = Array.from(
    dom.window.document.querySelectorAll("p")
  ).map(p => p.textContent);
  
  return { title, paragraphs };
}

Custom Resource Loading

const { JSDOM, ResourceLoader } = require("jsdom");

class CustomResourceLoader extends ResourceLoader {
  fetch(url, options) {
    // Override specific URLs
    if (url === "https://example.com/config.js") {
      return Promise.resolve(Buffer.from(`window.CONFIG = { apiUrl: "test" };`));
    }
    // Block certain resources
    if (url.includes("analytics")) {
      return Promise.resolve(null);
    }
    // Use default for others
    return super.fetch(url, options);
  }
}

const dom = new JSDOM(html, {
  resources: new CustomResourceLoader(),
  runScripts: "dangerously"
});

Working with Forms

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)

Using Storage APIs

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");

Handling Cookies

const { JSDOM, CookieJar } = require("jsdom");

const cookieJar = new CookieJar();
cookieJar.setCookieSync("session=abc123", "https://example.org/");

const dom = new JSDOM(``, {
  url: "https://example.org/",
  cookieJar
});

// Access cookies from page
console.log(dom.window.document.cookie); // "session=abc123"

// Set cookies from the page
dom.window.document.cookie = "theme=dark";

Error Handling with Virtual Console

const { JSDOM, VirtualConsole } = require("jsdom");

const virtualConsole = new VirtualConsole();
virtualConsole.on("error", (err) => console.error("Page error:", err));
virtualConsole.on("jsdomError", (error) => {
  console.error("jsdom error:", error.type, error.message);
});

const dom = new JSDOM(html, { virtualConsole });

Serializing Documents

const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html>hello`);

// Serialize with doctype
const html = dom.serialize();
// Returns: "<!DOCTYPE html><html><head></head><body>hello</body></html>"

// Get outerHTML (no doctype)
const outerHTML = dom.window.document.documentElement.outerHTML;
// Returns: "<html><head></head><body>hello</body></html>"

Working with Custom Events

const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html><body></body>`);
const { document, CustomEvent } = dom.window;

// Create and dispatch custom event
const customEvent = new CustomEvent("myCustomEvent", {
  detail: { message: "Hello" }
});

document.addEventListener("myCustomEvent", (event) => {
  console.log(event.detail.message); // "Hello"
});

document.dispatchEvent(customEvent);

Using MutationObserver

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);
  });
});

// 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();

Working with XPath

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"
}

docs

index.md

tile.json