npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jest-happy-dom-extended

v0.2.0

Published

A Happy DOM Jest environment with real 2D Canvas, dedicated Workers, and verified Web API compatibility fixes.

Readme

jest-happy-dom-extended

Run browser JavaScript tests in Node.js with a Happy DOM Jest environment, real 2D Canvas rendering and additional working Web APIs.

Installation

Requires Node.js >=22.18.0 and Jest 30. Choose your package manager below.

skia-canvas is a required dependency. Its installation script downloads the native binary for your platform. See the Skia installation guide for supported Linux, Windows and macOS builds and source-build requirements.

npm

npm install --save-dev jest@30 jest-happy-dom-extended

With npm 12, approve and run Skia's native installation script after installation:

npm approve-scripts skia-canvas
npm rebuild skia-canvas

pnpm

pnpm add -D jest@30 jest-happy-dom-extended
pnpm approve-builds

In the approval prompt, select skia-canvas and your project's other required native scripts. Jest 30 also lists @parcel/watcher and unrs-resolver. pnpm saves these approvals in pnpm-workspace.yaml.

For a non-interactive installation with pnpm 12, merge this into pnpm-workspace.yaml before running pnpm add:

allowBuilds:
  skia-canvas: true
  '@parcel/watcher': true
  unrs-resolver: true

Bun

bun add --dev jest@30 jest-happy-dom-extended
bun pm trust skia-canvas

bun pm trust runs Skia's installation script and saves the package in trustedDependencies. Use Bun to install dependencies; run Jest with Node.js as shown below.

Video support

Drawing video frames also requires ffmpeg and ffprobe on PATH. Ordinary Canvas drawing and image loading do not use these executables. Supported video formats depend on your FFmpeg build.

Configure Jest

Select the installed package as your Jest environment:

// jest.config.mjs
export default {
  testEnvironment: 'jest-happy-dom-extended',
  testEnvironmentOptions: { url: 'https://example.test/' },
}
npx jest

Use module.exports in jest.config.cjs for CommonJS. Extensions are installed synchronously before setupFiles and setupFilesAfterEnv; existing transforms and application fixtures remain normal Jest configuration.

Included behavior

Happy DOM provides the DOM, fetch and related browser object families. This package extends its official Jest environment and normalizes verified differences across Jest's VM boundary.

| API | Extension | | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | HTML Canvas / OffscreenCanvas | CPU Skia 2D drawing, paths, filters, compositing, PNG/JPEG/WebP output, dimension/state resets and call-time asynchronous snapshots | | ImageData | Window-compatible types, shared VM pixel arrays/subviews, sRGB/display-p3 byte conversion | | Images and createImageBitmap | Intrinsic dimensions, invocation-time readiness, Blob/ImageData/Canvas/video sources, crop/resize/flip and real Bitmap storage | | Canvas security | Image/video CORS, redirect/credential handling, taint propagation and protected readback/export | | Canvas transport / Worker | ImageBitmap cloning/transfer and context-free OffscreenCanvas transfer, HTML placeholder presentation and actual dedicated Worker execution | | structuredClone | Native graph cloning and ArrayBuffer transfer, extended for owned Canvas/Bitmap payloads | | Encoding / compression streams | Node-backed TextEncoderStream, TextDecoderStream, CompressionStream and DecompressionStream | | MessageChannel / MessagePort | Native entangled ports with matching constructor identity and owned-resource cleanup | | BroadcastChannel | Native delivery isolated to the test environment | | Blob / File | VM binary normalization, FileReader compatibility, bytes() and BOM-aware UTF-8 text() | | Animation.cancel() | Observable AbortError rejection without an internal unhandled rejection | | XMLHttpRequest / CompositionEvent | Instance ready-state constants and composed text with normal event flags |

Application-specific mocks remain in your tests. The Canvas contract documents supported behavior, resource limits and measured browser differences.

Real Canvas output

Save this as canvas.test.cjs; it runs with the configuration above without a TypeScript transform.

const { expect, test } = require('@jest/globals')

test('draws a red pixel and exports PNG', async () => {
  // Arrange
  const canvas = document.createElement('canvas')
  canvas.width = 1
  canvas.height = 1
  const context = canvas.getContext('2d')
  // Act
  context.fillStyle = 'red'
  context.fillRect(0, 0, 1, 1)
  const blob = await new Promise((resolve) => canvas.toBlob(resolve))
  // Assert
  expect([...context.getImageData(0, 0, 1, 1).data]).toEqual([255, 0, 0, 255])
  expect(blob?.type).toBe('image/png')
})

OffscreenCanvas provides the same drawing with await canvas.convertToBlob(). Reassigning a dimension, including the same value or a dimension attribute, clears pixels and drawing state while preserving an already obtained context's identity. Unsupported output MIME types fall back to real PNG bytes with the matching MIME type.

Asynchronous outputs copy pixels at invocation. Later redraws or resizes cannot change the pending image. Happy DOM's waitUntilComplete() includes these outputs, and teardown drains the environment's own outputs without waiting for unrelated application intervals. Encoding failures produce an asynchronous null HTML toBlob result or an Offscreen EncodingError rejection. Empty HTML canvases produce data:, or asynchronous null; empty Offscreen exports reject with IndexSizeError. Tainted readback/export fails with SecurityError. Cleanup still runs when a user callback throws.

Configuration and lifecycle

Image loading is enabled by default. Opt out explicitly when needed:

export default {
  testEnvironment: 'jest-happy-dom-extended',
  testEnvironmentOptions: {
    settings: { enableImageFileLoading: false },
  },
}

Standard Happy DOM environment options pass through. Jest serializes configuration for its workers, so construct custom Canvas adapter instances programmatically in a custom environment subclass before super(), or when constructing the environment directly. Custom adapters preserve their identity and remain their owner's cleanup responsibility. An explicit canvasAdapter: null keeps rendering disabled.

ESM imports and CommonJS require share one runtime, coordinating prototype restoration across simultaneous environments. The package owns the Canvas/media/Worker resources it creates. Close ports transferred out to other owners when those owners finish. Setup code that opens native resources must clean them up if it throws: Jest 30.5.1 can skip environment teardown after a failing setupFiles module.

Runtime boundaries

  • Runtime dependencies are pinned to Happy DOM 20.14.0 and CPU skia-canvas 3.0.8. CI covers Node 22.18.0, 24.20.0 and 26.8.1 on Linux/Windows, plus installed Jest 30.0.0 and 30.5.1 consumers in serial and two-process modes.
  • Canvas contexts use effective sRGB/unorm8 backing. Byte ImageData supports sRGB/display-p3 conversion; float16 ImageData is not supported. Font availability, edge rasterization and decoder rounding can differ from browsers.
  • 2D support does not include a Window Path2D constructor, WebGL, WebGPU or bitmaprenderer. Real layout and browser scheduling require a browser.
  • Dedicated Workers use actual node:worker_threads and the documented classic/module script loader. They are for trusted test code; their VM contexts are not a security sandbox. Node/file imports, service/shared workers and arbitrary browser-platform serialization are outside the supported contract.
  • Video selects the latest frame at or before the requested timestamp and samples playback at up to 20 fps. Audio playback and browser media scheduling are outside the contract.
  • Native structuredClone does not make every Happy DOM Blob, File, DOM node or platform object cloneable. BroadcastChannel names are isolated per test environment.
  • Animation support addresses cancellation promises; other upstream animation limitations remain.

Read the exact Canvas limits and evidence, verification guide and architecture for details. The former /canvas helper subpath is removed; use the environment setting above.

Contributing and releases

The monorepo contains source, regression/property tests and installed-consumer fixtures. pnpm check validates the implementation and its distribution. The private compatibility workspace is bundled; consumers install only this public package and its normal dependencies. Follow the contribution guide or manual release guide.

Independent Laststance project; not an official Happy DOM or Jest package. MIT licensed.