jsdom: window.crypto is undefined

iโ€™m trying to run tests using jsdom and mocha but I got this error:

ReferenceError: crypto is not defined

Is crypto really defined in jsdom?

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 20
  • Comments: 28 (2 by maintainers)

Most upvoted comments

Please consider adding crypto.randomUUID(). ๐Ÿ™

I used @peculiar/webcrypto in jest setupFiles

// jest.setup.js
import { Crypto } from "@peculiar/webcrypto"

global.crypto = new Crypto()

Seems to be working fine.

If you only require random numbers to be polyfilled, then you can also do

var nodeCrypto = require('crypto');
global.crypto = {
    getRandomValues: function(buffer: T) { return nodeCrypto.randomFillSync(buffer);}
};

Note: Youโ€™ll need Node v10 if you want buffer to be able to be Uint32Array as in v8 only Uint8Array and Buffer are supported

Put these codes into jest.steup.js, then you can visit window.crypto:

import { webcrypto } from 'node:crypto';

Object.defineProperty(globalThis, 'crypto', {
  value: webcrypto,
});

I just added the following to my jest.setup.js

crypto = require('@trust/webcrypto')

PR for crypto.getRandomValues(array) (only that one) at #3352.

I used @peculiar/webcrypto in jest setupFiles

// jest.setup.js
import { Crypto } from "@peculiar/webcrypto"

global.crypto = new Crypto()

Seems to be working fine.

Thanks , it is working fine for me also . https://www.npmjs.com/package/@peculiar/webcrypto - It is also maintained. you save my day ๐Ÿ˜ƒ It was struggling from last one hour for this issue .

I just added the following to my jest.setup.js

crypto = require('@trust/webcrypto')

Note that @trust/webcrypto is no longer maintained. See anvil.io.

This solution worked for me: https://stackoverflow.com/a/66687075/4064775

import crypto from "crypto";

Object.defineProperty(global.self, "crypto", {
  value: {
    subtle: crypto.webcrypto.subtle,
  },
});

in your setup file (for jest). With node 15.

Just ran in to this with Jest 29 on Node18. Overcame with the following custom environment:

import type { Context } from 'vm';
import type { EnvironmentContext, JestEnvironmentConfig } from '@jest/environment';
import { Crypto } from '@peculiar/webcrypto';
import JsDomEnvironment from 'jest-environment-jsdom';

export class CryptoEnvironment extends JsDomEnvironment {
  constructor({ globalConfig, projectConfig }: JestEnvironmentConfig, context: EnvironmentContext) {
    const pcWithBuffer = {
      ...projectConfig,
      globals: {
        ...projectConfig.globals,
        // https://github.com/facebook/jest/issues/4422
        Uint8Array,
      },
    };

    super({ globalConfig, projectConfig: pcWithBuffer }, context);

    Object.defineProperty(this.global, 'crypto', {
      value: new Crypto(),
    });
  }

  async setup(): Promise<void> {
    await super.setup();
  }

  async teardown(): Promise<void> {
    await super.teardown();
  }

  getVmContext(): Context | null {
    return super.getVmContext();
  }
}

export default CryptoEnvironment;

Hope it helps others landing here ๐Ÿ˜ƒ

Put these codes into jest.steup.js, then you can visit window.crypto:

import { webcrypto } from 'node:crypto';

Object.defineProperty(globalThis, 'crypto', {
  value: webcrypto,
});

Thanks! ๐Ÿ‘๐Ÿป๐Ÿค

@theogravity Iโ€™m facing the same issue it would seem only getRandomValues and randomUUID are natively implemented in jsdom.

Using @peculiar/webcrypto worked for me.

Ref: #1612 (comment)

Overriding global.crypto wonโ€™t work in v20 as itโ€™s read-only now. Might be possible with --no-experimental-global-webcrypto, though. Also the lib only covers a subset of features. Def better than none for sure.

@theogravity Iโ€™m facing the same issue it would seem only getRandomValues and randomUUID are natively implemented in jsdom.

Using @peculiar/webcrypto worked for me.

Ref: https://github.com/jsdom/jsdom/issues/1612#issuecomment-783729297

Trying crypto.subtle.importKey on the latest version of jest-environment-jsdom (29.5.0) gives

TypeError: Cannot read properties of undefined (reading 'importKey') under node v20

I also forced jsdom to the latest 22.1.0 and it also gives that.

const crypto = require('crypto');

Object.defineProperty(global.self, "crypto", {
    value: Object.setPrototypeOf({ subtle: crypto.subtle }, crypto)
});

This is still not working for me, keep getting error:

For security reasons, `window.crypto` is required to run `auth0-spa-js`

I added the following config options in package.json:

"jest": {
    "moduleFileExtensions": [
      "js",
      "ts",
      "tsx"
    ],
    "rootDir": "src",
    "testRegex": "\\.test\\.tsx?$",
    "transform": {
      "^.+\\.tsx?$": "ts-jest"
    },
    "testEnvironment": "jsdom",
    "setupFiles": [
      "<rootDir>/lib/test/jest.setup.js"
    ],
  },

jest.setup.js

window.crypto = require('@trust/webcrypto')
  1. npm i @trust/webcrypto
  2. Put window.crypto = require('@trust/webcrypto'); at the top of jest.setup.js or setupTests.js (create-react-app)