The require.main of modules that are required from within a test file is undefined, when:
createRequirecreateRequire was given another module than the current one (observe how parent2.js works as expected)Tested with Jest 26.4.2, Node v12.4.0
require.main.filename to get the name of the requiring file, as it would work in a node context.https://github.com/sguillia/jest-createRequire-repro
All files are in the demo repo
child.js
console.log(require.main && require.main.filename)
parent2.js
const Module = require('module')
require = Module.createRequire(__filename)
// Node: Prints path of parent2.js
// Jest: Prints path of parent2.js
require('./child')
parent3.js
const Module = require('module')
const path = require('path')
require = Module.createRequire(path.resolve('./subfolder/sub.js')) // sub.js is empty file
// Node: Prints path of parent3.js
// Jest: Prints null
require('./child')
$ node parent2.js
<path>
$ jest parent2.js
<path>
$ node parent3.js
<path>
$ jest parent3.js
<path>
$ node parent2.js
<path>
$ jest parent2.js
<path>
$ node parent3.js
<path>
$ jest parent3.js
null
System:
OS: Linux 4.15 Ubuntu 16.04.7 LTS (Xenial Xerus)
CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Binaries:
Node: 12.4.0 - ~/.nvm/versions/node/v12.4.0/bin/node
Yarn: 1.22.4 - ~/.nvm/versions/node/v12.4.0/bin/yarn
npm: 6.14.8 - ~/.nvm/versions/node/v12.4.0/bin/npm
Happy to take a PR fixing this! Might be just a matter of adding a parent in here?
hey @jeysal, Can I try to fill a PR for this ?
@mohamedsgap sure!
@jeysal I'd love to give it a shot! May I go ahead?
Yep!
I'm trying to add a parent key to the object you suggested here however I get this message saying parent is deprecated:
@deprecated — since 14.6.0 Please use require.main and module.children instead. Should I continue?
@flozender Is that a TypeScript warning? If so, that should be fine.
@jeysal Yes, it is a TypeScript error. My approach is to create a parent module, assign the keys manually, and attach it to the object since the only parameter available to me is modulePath inside of the createRequire function. Is this a viable approach? Thanks for your support.
Hmm, looking at it again, it doesn't seem so simple anymore. createRequire has absolutely no context at the moment, so I'm not sure where to derive either a parent or a main from ... I wonder how Node does this
@jeysal I will try to find out, but if you come across something please let me know. :)
It seems they are 'cheating' with an effectively global variable process.mainModule
How do you suggest I go about this? Should I try to emulate what they're doing?
So for us that would mean dropping the current main in logic jest-runtime that traverses parents, and instead somehow get the module of the test file currently being executed. I'm not yet sure how to figure that out ...
The currently executing test file is in the environment options, but the environment doesn't expose it.
It's in the cacheFS as the only initial entry, but that's "conincidence".
We could throw it on process in jest-runner like Node does.
We could pass it into the runtime in jest-runner.
None of those seem like great options. @SimenB ideas?
I'm down with passing it in in jest-runner when instantiating the runtime. Getting rid of the current recursion for parent would be nice as well.
require.main is the same regardless of being "normal" require or as the result of createRequire?
We should probably populate process.mainModule as well, fwiw
I'd like to help with this, what would be a good starting point?
Other than the jest-runtime index.ts you've already looked at, the place where jest-runner instantiates a new Runtime will be affected :) you can start from those places and should be able to see what changes need to be made :upside_down_face:
You wanna pass the path fo the test file (https://github.com/facebook/jest/blob/c808901f5ddfcbf8be924c850bd757d3ae720876/packages/jest-runner/src/runTest.ts#L79) into the runtime here: https://github.com/facebook/jest/blob/c808901f5ddfcbf8be924c850bd757d3ae720876/packages/jest-runner/src/runTest.ts#L154-L162
then store it on the instance of the runtime, and use that as main
Thanks!