esbuild-jest icon indicating copy to clipboard operation
esbuild-jest copied to clipboard

ReferenceError: React is not defined

Open vertic4l opened this issue 4 years ago • 18 comments

hey there,

i've just installed esbuild-jest and figured most of the issues out myself, but as you can see here:

Bildschirmfoto 2021-11-30 um 16 20 06

20 tests / 4 test files are failing with error message:

ReferenceError: React is not defined

All of them are tsx files and have the same import of import React from "react";

Has someone an idea ?

All tests are passing with ts-jest

vertic4l avatar Nov 30 '21 15:11 vertic4l

And why is something like "@babel/preset-typescript" needed for this to work ? Thought that esbuild removes the need for Babel.

I can build the whole project with esbuild-loader without having to use Babel ?!

vertic4l avatar Nov 30 '21 15:11 vertic4l

I've ran into the same problem just today. I've tried out various different solutions, which have included:

  1. Using TSX instead of JSX
  2. Upgrading all testing framework libraries (enzyme + adapter)
  3. Upgrading React (v16.14.0)

I've seemed to have tracked it down to this error

ReferenceError: React is not defined
        at Object.<anonymous> (/Users/alexvernacchia/deliveroo/app-template-react/app/client/components/DataLoaderExample/index.test.jsx:12:31)
        at Object.asyncJestTest (/Users/alexvernacchia/deliveroo/app-template-react/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:100:37)
        at /Users/alexvernacchia/deliveroo/app-template-react/node_modules/jest-jasmine2/build/queueRunner.js:47:12
        at new Promise (<anonymous>)
        at mapper (/Users/alexvernacchia/deliveroo/app-template-react/node_modules/jest-jasmine2/build/queueRunner.js:30:19)
        at /Users/alexvernacchia/deliveroo/app-template-react/node_modules/jest-jasmine2/build/queueRunner.js:77:41
        at processTicksAndRejections (internal/process/task_queues.js:97:5)

All of my test files have import React from 'react' as an import statement. I've logged out React in both the test file and the component itself, with both logs returning the data about React.

The error seems to come when the shallow render takes place inside the test...

ReferenceError: React is not defined

       9 |   it('should render initial button correctly', () => {
      10 |     // console.log('TEST', React);
    > 11 |     const wrapper = shallow(<DataLoaderExample />);

The interesting part is that I've been running multiple tests and there's no difference between the tests or components. So Test A will always pass and Test B will always fail with this error. I've removed Test A from even running (commented out), but this doesn't seem to help.

My config is as follows:

{
  "rootDir": "../",
  "setupFilesAfterEnv": ["./jest/setup.js"],
  "moduleNameMapper": {
    "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)$": "identity-obj-proxy",
    "\\.(css|scss)$": "identity-obj-proxy"
  },
  "coverageDirectory": "coverage",
  "snapshotSerializers": ["enzyme-to-json/serializer"],
  "cacheDirectory": "./jest/cache",
  "testEnvironment": "jsdom",
  "transform": {
    "\\.(js|jsx|ts|tsx)$": "./jest/transformer.js"
  },
  "watchPlugins": ["jest-watch-typeahead/filename", "jest-watch-typeahead/testname"]
}

with the transformer setup as

const esbuildJest = require('esbuild-jest');

module.exports = esbuildJest.createTransformer({
  sourcemap: true,
  loaders: {
    '.js': 'jsx',
  },
});

Any help would be greatly appreciated!

Versions

vernak2539 avatar Nov 30 '21 17:11 vernak2539

@vernak2539 hey, the error occurs regardless of the used method (shallow(), mount() from enzyme or render() from testing-library). All other tests are using the same methods and are passing.

The issue seem to occur when using something like this in the test:

jest.mock("react-router-dom", () => ({
    /* eslint-disable @typescript-eslint/ban-ts-comment */
    // @ts-ignore
    ...jest.requireActual("react-router-dom"),
    useHistory: () => ({
        replace: mockHistoryReplace,
        push: mockHistoryPush,
    }),
}));

vertic4l avatar Dec 01 '21 09:12 vertic4l

Ahh yeah, interesting. My test looks like this:

import React from 'react';
import { shallow } from 'enzyme';
import fetch from '@custom/fetch';
import DataLoaderExample from './index';

jest.mock('@custom/fetch', () => jest.fn());

describe('DataLoaderExample', () => {
  it('should render initial button correctly', () => {
    const wrapper = shallow(<DataLoaderExample />);

    expect(wrapper.find('withLayout(withSpacing(Button))').html()).toContain(
      'Load Sample API Data',
    );
  });
});

When removing the line jest.mock('@custom/fetch', () => jest.fn());, the test passes. Even if the line is commented out (but still present in the file) the test fails. For it to pass, it has to be fully removed

vernak2539 avatar Dec 01 '21 09:12 vernak2539

This looks like the same issue maybe?

vernak2539 avatar Dec 01 '21 09:12 vernak2539

@vernak2539 yes, and furthermore the linked issue https://github.com/evanw/esbuild/issues/412

But how can this be fixed ?

vertic4l avatar Dec 01 '21 10:12 vertic4l

I found that changing the import statement to import * as React from 'react' resolved the issue. This suggests it has something to do with the way that ESbuild treats importing namespaces.

strake7 avatar Dec 09 '21 16:12 strake7

I've run into this same issue. If I include jest.mock("...") in my tests then I will get ReferenceError: React is not defined:

This passes:

import React from "react";
import { shallow } from "enzyme";

it("should pass", () => {
  const wr = shallow(<div></div>);
});

This fails:

import React from "react";
import { shallow } from "enzyme";

jest.mock("lodash"); // <<--------- added this line

it("should pass", () => {
  const wr = shallow(<div></div>);
});

If I then amend import React from "react"; to be import * as React from "react"; the test passes:

import * as React from "react"; // <<--------- amended this line
import { shallow } from "enzyme";

jest.mock("lodash");

it("should pass", () => {
  const wr = shallow(<div></div>);
});

josh08h avatar Jan 20 '22 11:01 josh08h

Same here, changing import React from "react" to import * as React from "react" patched the issue

albertodeago avatar Feb 25 '22 13:02 albertodeago

Im facing the same error as I relate here https://twitter.com/daniloab_/status/1497258702662823936.

My test has a simple react component to be used as a root because the function being tested needs some hooks.

The test breaks because we do not import the react since react 17 does not need anymore to do it.

Does anyone know how to fix it?

  • related https://github.com/aelbore/esbuild-jest/issues/70

daniloab avatar Feb 25 '22 17:02 daniloab

This also seems related to #65.

Adding the following to a file referenced in setupFielsAfterEnv fixes it for me:

import React from "react";
// whatever else you need in here

global.React = React;

llwt avatar Mar 07 '22 18:03 llwt

@llwt wow that's a lot better, at least it's just in one file... thanks man

albertodeago avatar Mar 08 '22 09:03 albertodeago

@albertodeago Np.

Not sure if you specifically need to use esbuild, but if not @swc/jest is just as fast (if not faster) than esbuild-jest and doesn't have any of these problems. I ran into issues with source maps with this lib as well which prompted me to checkout swc/jest.

I normally wouldn't recommend a different package in the issues of another, but this one seems unmaintained 🤷🏻

llwt avatar Mar 08 '22 18:03 llwt

Yeah I know it, I was just giving esbuild a shot for a side-project, thx for the suggestion anyway

albertodeago avatar Mar 09 '22 07:03 albertodeago

For those still coming across this issue, I fixed it by adding {runtime: 'automatic'} with my @babel/preset-react preset.

My babel.config.js file now looks like this:

module.exports = {
  presets: ['@babel/preset-env', ['@babel/preset-react', { runtime: 'automatic' }], '@babel/preset-typescript'],
};

See https://github.com/facebook/jest/issues/11045

stevedeighton avatar Sep 01 '22 09:09 stevedeighton

For those still coming across this issue, I fixed it by adding {runtime: 'automatic'} with my @babel/preset-react preset.

My babel.config.js file now looks like this:

module.exports = {
  presets: ['@babel/preset-env', ['@babel/preset-react', { runtime: 'automatic' }], '@babel/preset-typescript'],
};

See facebook/jest#11045

I use CRA without babel config

AuthorProxy avatar Nov 22 '22 22:11 AuthorProxy