Skip to content

Instantly share code, notes, and snippets.

@termi
Last active March 7, 2025 08:17
Show Gist options
  • Save termi/f0313118f2814802c48bb4d8ce12d82f to your computer and use it in GitHub Desktop.
Save termi/f0313118f2814802c48bb4d8ce12d82f to your computer and use it in GitHub Desktop.
Patch jest/runner/testWorker.js to fix compatibility issues and more

Fix env in jest tests

How to use

  • Run patch_node_modules_jest_runner_testWorker.js on postistall
  • or use patch-package to write a similar solution (you need to inject require('../<relative_path>/../jestProcess_onCreate.js') to jest-runner/build/testWorker.js).

Limitation

Script patch_node_modules_jest_runner_testWorker.js was tested only for [email protected]. To support other versions you may needed to update it.

'use strict';
// This file will be hack-patched to `jest-runner/build/testWorker.js` in `patch_node_modules_jest_runner_testWorker.js`
// Polyfills if you need it
require('./polyfills/jscore');
const vm = require('node:vm');
const { createContext } = vm;
const nodejsSetTimeout = globalThis.setTimeout;
const nodejsClearTimeout = globalThis.clearTimeout;
const nodejsSetInterval = globalThis.setInterval;
const nodejsClearInterval = globalThis.clearInterval;
const nodejsSetImmediate = globalThis.setImmediate;
const nodejsClearImmediate = globalThis.clearImmediate;
const nodejsQueueMicrotask = globalThis.queueMicrotask;
const nodejsRequire = require;
const nodejsConsole = console;
const nodejsBuffer = Buffer;
const nodejs_structuredClone = typeof structuredClone === 'function'
? structuredClone
: void 0
;
const { URL: nodeWebURL } = require('node:url');
const { Blob: nodeWebBlob } = require('node:buffer');
vm.createContext = function(context) {
if (!context) {
context = {};
}
/**
* Temporary solution for issue [jsdom / ReferenceError: AggregateError is not defined]{@link https://github.com/jsdom/jsdom/issues/3205}
*/
if (!context.AggregateError) {
// this could be from polyfill or from native nodejs support
if (typeof AggregateError === 'function') {
// eslint-disable-next-line no-undef
context.AggregateError = AggregateError;
}
else {
context.AggregateError = Error;
}
}
/*
Use it like this to create native require function:
```
const nativeNode_require = nodejsRequire('node:module').createRequire(__filename);
```
*/
// link to real nodejs require, to use it in tests.
context.nodejsRequire = nodejsRequire;
context.nodejsConsole = nodejsConsole;
context.nodejsSetTimeout = nodejsSetTimeout;
context.nodejsClearTimeout = nodejsClearTimeout;
context.nodejsSetInterval = nodejsSetInterval;
context.nodejsClearInterval = nodejsClearInterval;
context.nodejsSetImmediate = nodejsSetImmediate;
context.nodejsClearImmediate = nodejsClearImmediate;
context.nodejsQueueMicrotask = nodejsQueueMicrotask;
context.nodeWebURL = nodeWebURL;
context.nodeWebBlob = nodeWebBlob;
context.nodejsBuffer = nodejsBuffer;
if (!context.structuredClone && nodejs_structuredClone) {
context.structuredClone = nodejs_structuredClone;
}
if (globalThis["IS_REACT_ACT_ENVIRONMENT"] && context["IS_REACT_ACT_ENVIRONMENT"] == null) {
/**
* * [How to Upgrade to React 18 / Configuring Your Testing Environment](https://react.dev/blog/2022/03/08/react-18-upgrade-guide#configuring-your-testing-environment)
* * [React / Test Utilities / act()](https://legacy.reactjs.org/docs/test-utils.html#act)
* * [testing-library / issues / The current testing environment is not configured to support act(...) with vitest and React 18](https://github.com/testing-library/react-testing-library/issues/1061)
*/
context["IS_REACT_ACT_ENVIRONMENT"] = true;
}
return createContext(context);
};
'use strict';
const path = require("node:path");
const fs = require("node:fs");
// link to injected file
const jestProcess_onCreate_path = require.resolve('./jestProcess_onCreate.js');
// Use this fir debugging: `node patch_node_modules_jest_runner_testWorker.js`
if (require.main.filename === __filename) {
patch_node_modules_jest_runner_testWorker();
}
/**
* Patch jest: jest-runner/build/testWorker.js.
*
* For example: `[email protected]`. To support other versions you __may__ needed to update `require.resolve()` bellow.
*/
function patch_node_modules_jest_runner_testWorker() {
try {
/**
* Path of file: '/node_modules/jest/build/jest.js'
*/
const jest_path = require.resolve('jest');
/** Path of file: '/node_modules/@jest/core/build/jest.js' */
const jest_core_path = require.resolve('@jest/core', { paths: [ jest_path ] });
/**
* Path of file: '/node_modules/jest-runner/build/index.js'
*/
const jest_runner_path = require.resolve('jest-runner', { paths: [ jest_path, jest_core_path ] });
/**
* Path of file: '/node_modules/jest-runner/build/testWorker.js'
*/
const jest_runner_testWorker_path = path.join(path.dirname(jest_runner_path), 'testWorker.js');
/**
* Normalize '\\' to '/' for Windows.
*/
const jestProcess_onCreate_relative_path = path.relative(path.dirname(jest_runner_path), jestProcess_onCreate_path);
{
const content = String(fs.readFileSync(jest_runner_testWorker_path));
const old_value = 'async function worker({config, globalConfig, path, context}) {';
const new_value_start = `async function worker({config, globalConfig, path, context}) {// -INJECTION_START-`;
const new_value_content = `\nrequire('${jestProcess_onCreate_relative_path.replace(/\\/g, '/')}')`;
const new_value_end = `\n// -INJECTION_START-\n`;
const new_value = new_value_start + new_value_content + new_value_end;
if (!content.includes(old_value)) {
// noinspection ExceptionCaughtLocallyJS
throw new Error(`Can't PATH "jest-runner" testWorker.js: original script changed. Can't find "${old_value}".`);
}
/** @type {string | undefined} */
let newContent;
// never was
if (!content.includes(new_value_start)) {
newContent = content.replace(old_value, new_value);
}
else {
// Path to jestProcess_onCreate_relative_path may be changed
if (!content.includes(new_value)) {
const startIndex = content.indexOf(new_value_start);
const endIndex = content.indexOf(new_value_end);
if (startIndex === -1 || endIndex === -1) {
// noinspection ExceptionCaughtLocallyJS
throw new Error(`Can't PATH "jest-runner" testWorker.js! Something wrong with patched script ${JSON.stringify({ startIndex, endIndex })}`);
}
newContent = content.substring(0, startIndex) + new_value + content.substring(endIndex + new_value_end.length);
}
}
if (newContent) {
fs.writeFileSync(jest_runner_testWorker_path, newContent);
}
}
}
catch (err) {
console.warn(`"${patch_node_modules_jest_runner_testWorker.name}": done with error:`, err);
}
}
module.exports = {
patch_node_modules_jest_runner_testWorker,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment