I added nanoid to a package in my monorepo, and a jest test in a downstream package is failing with this error message:
Details:
/Users/mikehogan/repos/personal/docsndata-monorepo/node_modules/.pnpm/nanoid@4.0.0/node_modules/nanoid/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { randomFillSync } from 'crypto'
^^^^^^
SyntaxError: Cannot use import statement outside a module
9 | const model_types_2 = require("@docsndata/model-types");
10 | const model_types_3 = require("@docsndata/model-types");
> 11 | const nanoid_1 = require("nanoid");
| ^
12 | const uuid_1 = require("uuid");
13 | function emptyStringMatchesRegexCondition() {
14 | return { _type: 'string.matches.regex', regex: "" };
at Runtime.createScriptFromCode (../../node_modules/.pnpm/jest-runtime@28.1.3/node_modules/jest-runtime/build/index.js:1796:14)
at Object.<anonymous> (../../model/core2/dist/cjs/property_types.js:11:18)
I tried the suggestions in this answer: How to use Jest to test functions using crypto or window.msCrypto
Specifically, when I paste this suggested snippet into my test case:
import crypto from 'crypto'
Object.defineProperty(global, 'crypto', {
value: {
getRandomValues: (arr:any) => crypto.randomBytes(arr.length)
}
});
My IDE tells me I need to install the crypto package, but that is deprecated according to its npm registry, in favour of a built in module. My ide also tells me that "global" is undefined. I am using node 16 and Typescript with the following tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist/esm",
"declaration": true,
"moduleResolution": "node"
},
"include": [
"./src"
]
}
and the following jest.config.js:
module.exports = {
globals: {
'ts-jest': {
packageJson: 'package.json',
},
},
"roots": [
"<rootDir>/src",
"<rootDir>/test",
],
"testMatch": [
"**/__tests__/**/*.+(ts)",
"**/?(*.)+(spec|test).+(ts)"
],
"transform": {
"^.+\\.(ts)$": "ts-jest"
},
};
So if crypto is now in-build, I added "@types/node": "^18.7.14"
to my package.json
. THAT has no crypto export, so I took a guess and did this:
import {webcrypto} from "crypto";
Object.defineProperty(global.self, "crypto", {
value: {
subtle: webcrypto.subtle,
},
});
Test fails with the same error. So confused and out of my depth here. Can someone please explain:
- Why jest is effected by what my production code imports?
- Is jest effected in this way by the crypto package specifically, or is it a more general issue?
- How do I fix it in a centralised way, for 1000s of jest tests in a large monorepo?
Edit #1: Reading up some more, it seems the version of nanoid I am using (4.0.0) removed support for CJS modules, as per https://github.com/ai/nanoid/blob/main/CHANGELOG.md#40 . Switching to nanoid 3.3.4 works, so at least I can move forward for now, but I still need to solve this.