The tl;dr is:
1) How can I have Jest use the native require
function to load all modules in my tests anywhere.
2) Where / how would I go about modifying (ie replacing with the esm loader) https://github.com/standard-things/esm the require function in one place, before any tests run, so all tests will use the modified require.
I'd like to use the esm-loader with my Jest test files. In order to do so, I need to patch the require function globally, before any test code runs, with something like
require = require("@std/esm")(module, { esm: "js", cjs: true });
How do I tell Jest to execute that code before anything else is touched or requested?
I tried pointing both setupTestFrameworkScriptFile
and an setupFiles
array entry to a file with that in it, but neither worked (though I did confirm that both ran).
Alternatively, I'm firing off these tests with an npm script
"scripts": {
"test": "jest"
}
Is there some CLI magic whereby I can just load a module and then run jest
?
Edit - the testEnvironment
and resolver
options make me wonder if this is ever even using the actual Node require
function to load modules, or instead using its own module loader. If so I wonder if this is even possible.
So this one was a bit tough to get working. The solution is quite simple but it took me a while to get it working. The problem is that whenever you use any module in jest
They are all loaded in below way
If you have a look at
node_modules/jest-runtime/build/index.js:495:510
this._createRequireImplementation(filename, options);
gives every module a custom require object. So you as such don't get the native require function at all, anywhere. Once jest has started every module loaded from then on will have jest's customrequire
function.When we load a module, the
requireModule
methods from thejest-runtime
gets called. Below is an excerpt from the sameAs you can see if the extension of the file is
.node
it loads the module directly, else it calls the_execModule
. This function is the same code that I posted earlier which does the code transformationNow when we want to modify
require
function for our test, we need_execModule
to export our code directly. So the code should be similar to loading of a.node
modulesBut doing that would mean patching the code, which we want to avoid. So what we do instead is avoid using the jest command directly, and create our own
jestload.js
and running that. The code for loading jest is simpleNow we want to modify the
_execModule
before the cli loads. So we add below codeNow time for a test
And a
sum.mjs
fileNow we run the test
The solution is available on below repo
https://github.com/tarunlalwani/jest-overriding-require-function-stackoverflow
You can clone and test the solution by running
npm test
.setupFiles
worked for me. Add this in package.json:https://jestjs.io/docs/en/configuration.html#setupfiles-array
I tried using
node -r @std/esm run.js
where run.js is just a script that calls jest, but it does not work and crashes here : https://github.com/facebook/jest/blob/master/packages/jest-runtime/src/script_transformer.js#L305.From what I understand from this line means that it is not possible because jest compiles the module using the native
vm
module. The above lines (290):is the code called when you are specifying transforms in your jest config.
Conclusion : until esm are supported ( and they will be under the
.mjs
extension ) you cannot import es modules in jest without specifying a transform. You could try to monkey patchvm
but I would really advise against this option.Specifying a jest transform is really not that hard, and for es modules it's really as simple as using
babel-jest
with the right babel config :Below a package.json with minimal settings