I have the following line that executes correctly in browser
eval(Babel.transform(template, { presets: ['react'] }).code);
but when I run jest tests I am getting ReferenceError: React is not defined
What am I missing?
More info: in the test file I have the following:
const wrapper = shallow(<MyComponent/>);
const instance = wrapper.instance();
instance.componentFunction(...)
and then the componentFunction has the eval(Babel.transform(template, { presets: ['react'] }).code);
line where template
is something it gets from the test file and can be something like <span>...</span>
Please let me know if more details are needed
@babel/preset
already has support for what you need. According to the react 17 documentation I only had to set the runtime
to automatic
in my babel.config.json
.
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}
If you are using @babel/plugin-transform-react-jsx
the config should be
{
"plugins": [
["@babel/plugin-transform-react-jsx", {
"runtime": "automatic"
}]
]
}
The latter is usually not needed since @babel/preset-react
includes @babel/plugin-transform-react-jsx
.
Why you shouldn't use import React from 'react';
The documentation states:
React.createElement
does not allow.There is also a technical RFC that explains how the new transformation works.
If you want to upgrade. React also provides an automated script that removes unnecessarry imports from your code.
If you are using JSX in your jest test files, you will need to add the following import line to the top of the file:
import React from 'react';
The reason for this is that Babel transforms the JSX syntax into a series of React.createElement()
calls, and if you fail to import React, those will fail.
The best solution for Next.js (where jsx: 'preserve'
specifically is:
Configuring your babel config in the way that next already does: (no need to install another babel plugin):
babel.config.js:
module.exports = {
presets: ['next/babel']
};
Alternatively, if anyone experienced this bug had the problem wherein import React from 'react'
is not necessary, because it is already included globally and doesn't need to be included in every file, then this solution may work for you.
I simply configured React to be globally defined in jest.
My jest.config.js
:
module.exports = {
moduleDirectories: ['./node_modules', 'src'],
// other important stuff
setupFilesAfterEnv: ['<rootDir>/src/jest-setup.ts']
}
import '@testing-library/jest-dom';
import React from 'react';
global.React = React; // this also works for other globally available libraries
Now I don't need to worry about each file importing React (even though eslint knows that's unnecessary with Next.js)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With