Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReferenceError: React is not defined in jest tests

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

like image 461
chibis Avatar asked Nov 21 '19 17:11

chibis


3 Answers

@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:

  • There are some performance improvements and simplifications that 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.

like image 153
René Link Avatar answered Nov 09 '22 05:11

René Link


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.

like image 36
GregL Avatar answered Nov 09 '22 04:11

GregL


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)

like image 7
Zargold Avatar answered Nov 09 '22 06:11

Zargold