Solving "ReferenceError: structuredClone is not defined" in Jest Tests
Current Status
structuredClone()
was added in Node.js 17.0.0 (Sept 2021). If you're using older Node versions or Jest environments like jsdom, manual solutions are needed.
Problem Overview
When running Jest tests in Node.js/TypeScript environments, you might encounter:
ReferenceError: structuredClone is not defined
This occurs because:
structuredClone()
is unavailable in Node.js versions below 17- jsdom (used by Jest for browser-like environments) lacks its implementation
- Your production environment supports it, but testing environment doesn't
Recommended Solutions
1. Update Node.js Version (Ideal Solution)
Upgrade to Node.js v17+:
# Check current version
node --version
# Update using nvm (recommended)
nvm install 18
nvm use 18
# Or via package manager (e.g., macOS Homebrew)
brew update && brew upgrade node
Verify support:
console.log('Native structuredClone support:', typeof structuredClone !== 'undefined');
Minimum Version Note
Ensure all team members and CI/CD pipelines update simultaneously to prevent environment inconsistencies.
2. Global Polyfill in Jest Configuration
For older Node versions or jsdom environments:
module.exports = {
setupFiles: ['<rootDir>/jest.setup.ts'],
// Other configurations...
};
declare global {
function structuredClone<T>(obj: T): T;
}
// Add polyfill implementation
global.structuredClone = <T>(obj: T): T => {
if (typeof globalThis.structuredClone === 'function') {
return globalThis.structuredClone(obj);
}
return JSON.parse(JSON.stringify(obj)) as T;
};
3. Robust Polyfill Library
For complete feature support (Dates, Maps, custom classes, circular refs):
npm install @ungap/structured-clone
npm install -D @types/ungap__structured-clone
import structuredClone from '@ungap/structured-clone';
export const deepClone = <T>(obj: T): T => structuredClone(obj);
import { deepClone } from './utils/clone';
test('cloning test', () => {
const original = new Map([['key', { value: 123 }]]);
const cloned = deepClone(original);
// Assertions...
});
Polyfill Limitations
While libraries provide better coverage, they can't perfectly replicate native browser behavior. Profile performance for large objects.
Environment-Specific Fixes
Fixing jsdom Environments
When using jest-environment-jsdom
, add this to your setup file:
// Only define if missing in jsdom
if (!global.structuredClone) {
global.structuredClone = function (obj) {
return new Promise((resolve) => {
const { port1, port2 } = new MessageChannel();
port2.onmessage = (ev) => resolve(ev.data);
port1.postMessage(obj);
});
};
}
Jest Version Conflicts
If you've updated Node but still see errors:
- Upgrade Jest and related tools:
npm install --save-dev jest@29 ts-jest@29
- Verify actual Node version in tests:
test('debug env', () => {
console.log(`Test Node version: ${process.version}`);
});
Alternative: Switch to Vitest
For modern projects, consider Vitest (Jest-compatible API):
npm remove jest ts-jest @types/jest
npm install -D vitest happy-dom @vitest/coverage-v8
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'happy-dom',
setupFiles: './vitest.setup.ts',
coverage: { provider: 'v8' },
},
});
import { expect, test } from 'vitest';
test('structuredClone works', () => {
const original = { date: new Date() };
const cloned = structuredClone(original);
expect(cloned.date instanceof Date).toBe(true);
});
When to Use Which Solution?
Solution | Best For | Node Version Required | Complexity |
---|---|---|---|
Update Node.js | Greenfield projects, team alignment | v17+ | ★☆☆☆☆ |
Global Polyfill | Legacy projects, quick fixes | Any | ★★☆☆☆ |
Polyfill Library | Complex objects, circular references | Any | ★★★☆☆ |
Switch to Vitest | Performance-critical tests, modern stacks | v14+ | ★★★★☆ |
Historical Context
structuredClone()
entered browser specs in 2021 (MDN Docs)- Node.js implemented it in v17.0.0 (September 2021)
- jsdom support is still pending as of 2024 (GitHub Issue)
Always prioritize upgrading Node.js where possible. For constrained environments, choose polyfills based on your data complexity and testing needs. Remember to document your solution for team awareness!