"ReferenceError: structuredClone is not defined" using jest with nodejs & typescript

44k Views Asked by At

I'm running tests with jest in a simple NodeJS app that uses typescript. My test is throwing an error: ReferenceError: structuredClone is not defined.

I'm not getting any linter errors and the code compiles fine normally.

  const variableForValidation = structuredClone(variableForValidationUncloned);

package.json:

  "dependencies": {
    ...
  },
  "devDependencies": {
    "@types/jest": "^29.0.0",
    "@types/node": "^18.7.15",
    "@typescript-eslint/eslint-plugin": "^5.36.1",
    "@typescript-eslint/parser": "^5.36.1",
    "eslint": "^8.23.0",
    "jest": "^28.0.1",
    "nodemon": "^2.0.19",
    "serverless-plugin-typescript": "^2.1.2",
    "ts-jest": "^28.0.8",
    "ts-node": "^10.9.1",
    "typescript": "^4.8.2"
  }

This github issue suggests to me that the issue has been resolved: https://github.com/facebook/jest/issues/12628 - or perhaps I'm misunderstanding?

I've seen a similar Stack question but using Mocha: mocha not recognizing structuredClone is not defined

8

There are 8 best solutions below

4
marcelocra On BEST ANSWER

structuredClone was added in Node 17.

If you can't update, the JSON hack (stringify then parse) works, but has some shortcomings that might be relevant to you:

  • Recursive data structures: JSON.stringify() will throw when you give it a recursive data structure. This can happen quite easily when working with linked lists or trees.
  • Built-in types: JSON.stringify() will throw if the value contains other JS built-ins like Map, Set, Date, RegExp or ArrayBuffer.
  • Functions: JSON.stringify() will quietly discard functions.

Edit:

I recently learned about the json-stringify-safe, that helps with the circular issue.

4
JimmyTheCode On

I couldn't figure it out, so I set my own global:

// globals.ts
if(!global.structuredClone){
    global.structuredClone = function structuredClone(objectToClone: any) {
          const stringified = JSON.stringify(objectToClone);
          const parsed = JSON.parse(stringified);
          return parsed;
        }
}
// entry point of app, eg index.ts:
import './globals.ts'
// ...

I think it might be because the target in my tsconfig is converting my typescript files to a javascript/node version before structuredClone was added?

5
gbengaoyetade On

For the same error, having the code below in the test file fixed the issue for me.

global.structuredClone = (val) => JSON.parse(JSON.stringify(val))

Reference

0
Steve Chambers On

I had the same issue with testEnvironment set to jest-environment-jsdom in my Jest config file.

@fservantdev has linked to this issue (currently open at the time of writing) regarding this: https://github.com/jsdom/jsdom/issues/3363

There are several possible workarounds suggested in that thread - the following worked for me:

  1. npm install @ungap/structured-clone
  2. npm i --save-dev @types/ungap__structured-clone
  3. Add the following line at the top of all the files where structuredClone is being used: import structuredClone from "@ungap/structured-clone";.

UPDATE: This suggestion from tkrotoff might be a better one. In short, this is a hot topic at the time of writing so worth reading the thread to stay up to date...

1
backslashN On

A polyfill of structuredClone is available in core-js. Add it to your jest.config.js.

import 'core-js' or require('core-js')

Note: Don't forget to add core-js to your babel exclude pattern.

0
Sam Spade On

For anyone who has already updated Jest and Node and still can't get structuredClone to work, try running:

console.log(`Node Version: ${process.version}`);

And verify that the logged version number supports structuredClone.

IDE misconfigurations can cause Jest to be run using a different version of Node. When I ran my project it used Node v17, but when I ran tests my IDE decided to use Node v16. Took hours to figure out what was happening.


After running into this problem again, jest 27 combined with ts-jest 27 seems to not be able to use structuredClone even if you are on Node v17. I solved this by updating to jest 29 and ts-jest 29.

0
dhilt On

Had the same issue with jsdom. They have no structuredClone global in current ([email protected]) version, and the issue seems stale: https://github.com/jsdom/jsdom/issues/3363.

In addition to the workarounds discussed, I would provide my approach based on setupFiles jest setting:

// global.mock.js
global.structuredClone = v => JSON.parse(JSON.stringify(v));
// jest.config.js
module.exports = {
  testEnvironment: "jsdom",
  ...
  roots: ["./__tests__"],
  setupFiles: ["<rootDir>/global.mock.js"]
};

0
Humed-Essie On

Update the version of your node to the most recent one.