Do you want to request a _feature_ or report a _bug_?
bug
What is the current behavior?
FAIL ./my.test.js
● Test suite failed to run
ReferenceError: requirejsVars is not defined
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal repository on GitHub that we can npm install and npm test.
jest.config.json
{
"testEnvironment": "node"
}
my.test.js
var requirejs = require('requirejs')
test(() => {})
./node_modules/.bin/jest -c jest.config.json my.test.js
What is the expected behavior?
PASS
Run Jest again with --debug and provide the full configuration it prints. Please mention your node and npm version and operating system.
./node_modules/.bin/jest --debug -c jest.config.js my.test.js
jest version = 16.0.1
test framework = jasmine2
config = {
"testEnvironment": "/Users/jamuferguson/dev/paypal/p2pnodeweb/node_modules/jest-environment-node/build/index.js",
"rootDir": "/Users/jamuferguson/dev/paypal/p2pnodeweb",
"name": "-Users-jamuferguson-dev-paypal-p2pnodeweb",
"setupFiles": [
"/Users/jamuferguson/dev/paypal/p2pnodeweb/node_modules/babel-polyfill/lib/index.js"
],
"testRunner": "/Users/jamuferguson/dev/paypal/p2pnodeweb/node_modules/jest-jasmine2/build/index.js",
"scriptPreprocessor": "/Users/jamuferguson/dev/paypal/p2pnodeweb/node_modules/babel-jest/build/index.js",
"usesBabelJest": true,
"automock": false,
"bail": false,
"browser": false,
"cacheDirectory": "/var/folders/9d/p3qfw0g94yz7qh3z9dr4btwm391xgk/T/jest",
"clearMocks": false,
"coveragePathIgnorePatterns": [
"/node_modules/"
],
"coverageReporters": [
"json",
"text",
"lcov",
"clover"
],
"globals": {},
"haste": {
"providesModuleNodeModules": []
},
"mocksPattern": "__mocks__",
"moduleDirectories": [
"node_modules"
],
"moduleFileExtensions": [
"js",
"json",
"jsx",
"node"
],
"moduleNameMapper": {},
"modulePathIgnorePatterns": [],
"noStackTrace": false,
"notify": false,
"preset": null,
"preprocessorIgnorePatterns": [
"/node_modules/"
],
"resetModules": false,
"testPathDirs": [
"/Users/jamuferguson/dev/paypal/p2pnodeweb"
],
"testPathIgnorePatterns": [
"/node_modules/"
],
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.jsx?$",
"testURL": "about:blank",
"timers": "real",
"useStderr": false,
"verbose": null,
"watch": false,
"cache": true,
"watchman": true,
"testcheckOptions": {
"times": 100,
"maxSize": 200
}
}
Determining test suites to run...watchman warning: Recrawled this watch 1 times, most recently because:
/Users/jamuferguson/dev/paypal/p2pnodeweb: kFSEventStreamEventFlagUserDropped
To resolve, please review the information on
https://facebook.github.io/watchman/docs/troubleshooting.html#recrawl
To clear this warning, run:
`watchman watch-del /Users/jamuferguson/dev/paypal/p2pnodeweb ; watchman watch-project /Users/jamuferguson/dev/paypal/p2pnodeweb`
FAIL ./my.test.js
● Test suite failed to run
ReferenceError: requirejsVars is not defined
at <anonymous>:2:3
at Object.exports.runInThisContext (vm.js:54:17)
at exec (node_modules/requirejs/bin/r.js:80:23)
at setBaseUrl (node_modules/requirejs/bin/r.js:31952:13)
at node_modules/requirejs/bin/r.js:32042:9
at Object.<anonymous> (node_modules/requirejs/bin/r.js:32137:2)
at Object.<anonymous> (my.test.js:1:145)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 0.767s
Ran all test suites matching "my.test.js".
Also tried adding requirejsVars to globals and it still blew up.
Also important
~/dev/paypal/p2pnodeweb (jest-mocha) $ npm ls requirejs
[email protected] /Users/jamuferguson/dev/paypal/p2pnodeweb
└── [email protected]
FYI we don't use AMD/requirejs for our tests, but a lib we use in our testing also supports AMD style tests, so it relies on requirejs
The code in question very likely relies on this.requirejsVars and expects this to equal window, but instead of will be undefined. It probably does that because requirejs tries to guess your environment based on various globals that exist, but we patch some of those, so we're really in trouble here :)
While this is a real issue, our team at least has found a workaround to avoid the requirejs dep in our mock helper, so I will close.
@xjamundx
Can you please provide us the workaround step as we have same kind of issue?
I worked around this problem with the following hack:
Create a manual mock for vm and replace runInThisContext
// __mocks__/vm.js
const vm = jest.genMockFromModule('vm');
// r.js calls vm.runInThisContext during initialization
// but when running under jest it does not work as expected.
// This assumes nothing else calls this method during the tests...
vm.runInThisContext = function () {
return undefined
};
module.exports = vm;
Load the mock in any tests that transitively tries to load *r.js *
// my_spec.js
jest.mock('vm');
This only works because my code does not actually use require.js bundle loader in node.js
it only uses the .optimize method for bundling. So I don't mind potentially breaking require.js
by providing this no-op mock.
Also if any other package needs to use vm.runInThisContext during the test it will be broken as well.
@bd82 nice one. had the same problem, your hack worked for me...maybe this should be investigated by the jest core team
Glad it helped you @digitalkaoz.
I'm not really sure we can do anything here. PRs trying to fix it has been ignored for more than 2 years... Trying to support an unsupported library that does crazy stuff seems like it wouldn't be the way to best spend our time.
https://github.com/requirejs/r.js/pull/849
If someone else is able to fix it though, I'll be happy to help it get landed
Maybe just wait a while longer until nobody would use require.js anymore? 😄
Yeah, I'm leaning towards ~not fixing it~ not spending the time to attempt to fix it
Yeah, let's not spend time on this from our side. If somebody feels strongly and can find a clean fix, send a PR and tests, that is obviously always welcome.
Ok, so I know this is a hack. But I did figure out a way to make this work.
```globals.js
/*
THIS IS A HOOK where code is called before the Jest ENV is loaded.
Therefore we can pull in real node modules without JEST'S shenanigans. This is useful for us to load
things like Cesium which need requirejs and can not be loaded in Jests environment.
!!!!!!!!!!!!!!HACK!!!!!!!!!!!!!!!
So here we hack load Cesium which loads fine in pure node. Then inject it
into a global object which Jest exposes to the test environment to allow us to
utilize it and further inject it partially in mocks.
*/
module.exports = function setupGlobal() {
process.$Cesium = require('cesium');
};
```
Use your jest.config to point to the above file via https://jestjs.io/docs/en/configuration#globalsetup-string .
Apologies for the update/edits spam, fat fingered.. doh.
In your mock for cesium you can now
module.exports = process.$Cesium;
Note this only works for all tests if --runInBand is used as some test will get their own unique process without it.
I tried setupFiles hoping this would inject a preloaded requirejs module into the child process prior to Jests module / require environment being loaded. However this is not the case and requirejsVars will still be missing.
It would be nice if there was another step to hook into for each child_process prior to to setupFiles where you have access to manipulating the real node environment without anything jest loaded.
It would be nice if there was another step to hook into for each child_process prior to to setupFiles where you have access to manipulating the real node environment without anything jest loaded.
Actually it looks like globals will work fine.
globals: {
$Cesium: require('cesium')
},
Negative, works for a single test jest env is still preprocessed before globals is called.
@nmccready , I tried your solution for Cesium, which solved the requirejsVars error, but instead I got
TypeError: nodeRequire is not a function
Did this not happen to you?
Did this not happen to you?
Yeah so it works as long as the tests stay non-parallel. So you need to turn parallelization off on Jest. This sucks, but I resulted to making all Cesium tests being treated as Integration tests.
So when running our test suite it runs normal tests all in parallel and another process for sync/integration tests.
I think the confusion in here is Negative. So My thoughts were that globals: {... was going to work and it did not.
Sorry for the confusion.
This is what worked for me
```__jest__/globals.js
const debug = require('../_debug').spawn('jest:global');
/*
THIS IS A HOOK where code is called before the Jest ENV is loaded.
Therefore we can pull in real node modules without JEST'S BS. This is useful for us to load
things like Cesium which need requirejs and can not be loaded in Jests environment.
!!!!!!!!!!!!!!HACK!!!!!!!!!!!!!!!
So here we hack load Cesium which loads fine in pure node. Then inject it
into a global object which Jest exposes to the test environment to allow us to
utilize it and further inject it partially in mocks.
*/
module.exports = function globalSetup() {
process.$Cesium = require('cesium');
debug(() => process.$Cesium);
};
```jest.config.js
module.exports = {
globalSetup: '<rootDir>/__jest__/global.js',
....
}
Looks like I re-answered this... oh well. CHeers
Looks like I re-answered this... oh well. CHeers
Do you know of any way to add the --runInBand flag to jest when using create-react-app (which invokes jest indirectly somehow when you run npm test?
This is what worked for me
const debug = require('../_debug').spawn('jest:global'); /* THIS IS A HOOK where code is called before the Jest ENV is loaded. Therefore we can pull in real node modules without JEST'S BS. This is useful for us to load things like Cesium which need requirejs and can not be loaded in Jests environment. !!!!!!!!!!!!!!HACK!!!!!!!!!!!!!!! So here we hack load Cesium which loads fine in pure node. Then inject it into a global object which Jest exposes to the test environment to allow us to utilize it and further inject it partially in mocks. */ module.exports = function globalSetup() { process.$Cesium = require('cesium'); debug(() => process.$Cesium); };module.exports = { globalSetup: '<rootDir>/__jest__/global.js', .... }
@nmccready in your hack solution, you have two module.exports. One is to be saved as global.js. Where is the other one saved/saved as?
I am not doing something right here because this is not working for me.
I am using create react app with craco, and craco-cesium to load cesium into my project. I am trying to setup jest to start creating tests but the issue is Cesium is using requireJS.
I added the following to my package.json
// package.json
...
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts"
],
"globalSetup": "<rootDir>/setupTests.js"
}
...
I setup the setupTests.js with the following code:
// setupTests.js
module.exports = async () => {
var cesium = require('cesium');
process.$Cesium = cesium
};
and I have the first basic test for valid rendering:
// App.test.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
however I get the error in one of my view inside <App /> component with the following code:
import Cesium from "cesium";
...
TypeError: Cannot read property 'Ion' of undefined
...
Cesium.Ion.defaultAccessToken = '...';
reporting Cesium as undefined when calling it's functions. I tried to use jest.config.js for jest to pick up the configuration from there with the following code:
// jest.config.js
const { createJestConfig } = require("@craco/craco");
const cracoConfig = require("../craco.config.js");
const jestConfig = createJestConfig(cracoConfig);
module.exports = jestConfig;
but create react app doesn't pick up this file so I cannot try this to verify if this would work.
Most helpful comment
I worked around this problem with the following hack:
Create a manual mock for vm and replace runInThisContext
Load the mock in any tests that transitively tries to load *r.js *
This only works because my code does not actually use require.js bundle loader in node.js
it only uses the .optimize method for bundling. So I don't mind potentially breaking require.js
by providing this no-op mock.
Also if any other package needs to use vm.runInThisContext during the test it will be broken as well.