Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

babel-jest doesn't handle ES6 within modules

I am trying to set up Jest on a React based project which uses ES6 modules. However I seem to be having issues with ES6 modules, I am using babel-jest and believe I have this set up properly (Jest detects it automatically).

Jest doesn't seem to have a problem using ES6 imports however as soon as it hits on an import statement within one of the imported modules it chokes. It's as if it is only transpiling the initial test script and not any of the imported modules. I have tried various configurations and tried searching Google with no luck. Running tests without any imports works fine.

Here is the error:

({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Predications from './predications';
                                                                                         ^^^^^^
SyntaxError: Unexpected token import

Here are the relevant bits of config:

jest.conf.json

{
  "testRegex": "\/test\/spec\/.*\\.js$",
}

.babelrc

{
  "presets": ["es2015", "stage-0", "react"]
}

Test script

import React from 'react';
import { mount, shallow } from 'enzyme';
import Slider from 'react-slick';
import Carousel from '../../client/components/carousel/carousel.js'; // test chokes on when I include this module

describe('carousel component', () => {
  it('is a test test case', () => {
    expect(1 + 2).toEqual(3);
  });
});

Update:

As suggested, I have tried running the test without jest.conf.js, however the testRegex is needed in order for Jest to find my tests, I tried moving tests to the default test directory and they still fail.

I would like to clarify that tests themselves are running fine, the issue seems to be where one of my imported modules uses ES6, in my example above, if I don't import my carousel component the test runs fine, as soon as I import that the test chokes on the import statement within that file. It seems as though the imported modules are not getting transpiled.

Update #2

After some investigation it appears the issue is that babel is not transpiling ES6 within node_modules. I have created an example repo to demonstrate this here: https://github.com/jamiedust/babel-jest-example

I understand that third party modules should be handling their own transpiling, however we have a number of modules which are hosted on our own npm registry and are re-used between projects, in these cases Webpack handles transpiling, for the Jest tests we need these node_modules to be transpiled by Babel, or a way of leveraging our webpack set up to do this for us.

Solution

Add the following config in package.json (or Jest config file).

"jest": {
  "transformIgnorePatterns": [
    "/node_modules/(?!test-component).+\\.js$"
  ]
}
like image 330
jamiedust Avatar asked Feb 14 '17 12:02

jamiedust


People also ask

How do I enable Ecmascript modules in jest?

To access this object in ESM, you need to import it from the @jest/globals module or use import. meta . import {jest} from '@jest/globals'; jest.

What does Babel jest do?

Jest ships with one transformer out of the box – babel-jest . It will load your project's Babel configuration and transform any file matching the /\. [jt]sx?$/ RegExp (in other words, any .

Is Babel required for jest?

Node. js has supported async functions by default since version 7.6. 0, so (as you suspected) Babel is not needed for Jest to run tests using async functions. I just confirmed this by installing only Jest v24.


Video Answer


3 Answers

By default any code in node_modules is ignored by babel-jest, see the Jest config option transformIgnorePatterns. I've also created a PR on your example repo, so you can see it working.

While this works, I've found it to be extremely slow in real applications that have a lot of dependencies containing ES modules. The Jest codebase has a slightly different approach to this as you can find in babel-jest transforming dependencies. This can also take much longer on Windows, see Taking 10 seconds on an empty repo.

If doing "unit" testing, mocking is probably the better way to go.

like image 119
Samuel Sharpe Avatar answered Oct 24 '22 07:10

Samuel Sharpe


You could try adding the transform-es2015-modules-commonjs plugin to your babel config file for testing only. Here is an example config file which tells babel to transpile modules only when in a testing environment. You can put it underneath your presets:

{
  "presets": [
    "react",
    ["es2015", {"modules": false, "loose": true}]
  ],
  "env": {
    "test": {
      "plugins": ["transform-es2015-modules-commonjs"]
    }
  }
}

You can read about the plugin here:

https://www.npmjs.com/package/babel-plugin-transform-es2015-modules-commonjs

Then, when running your Jest tests on the command line specify NODE_ENV=test (you may need to add the --no-cache flag to the command the first time after making the change to the babel config because Jest caches babel output, but after that you can leave it off:

NODE_ENV=test jest --no-cache

I learned about this issue in a React seminar by Brian Holt at Frontend Masters. https://frontendmasters.com/courses/

like image 3
A. Cookro Avatar answered Oct 24 '22 07:10

A. Cookro


faced the same issue, followed the steps to resolve,

  1. install babel-jest
  2. in jest config add this configuration
       transform: {
           '^.+\\.js?$': require.resolve('babel-jest')
       }
  1. make sure you have babel.config.js present (your config might be different than provided below)
    module.exports = {
      "env": {
        "test": {
          presets: [
            [
              '@babel/preset-env',
              {
                targets: {
                  node: 'current',
                },
              },
            ],
          ]
        }
      }
    };
like image 3
Dip686 Avatar answered Oct 24 '22 06:10

Dip686