Victor Pudeyev
Victor Pudeyev

Reputation: 4539

How to setup jest with node_modules that use es6

I have a very simple test:

describe('sanity', () => {
  it('sanity', () => {
    expect(true).toBeTruthy()
  })
})

And I'm receiving the following error:

 FAIL  spec/javascript/sanity_test.js
  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /Users/piousbox/projects/ruby/<project>/node_modules/@atlaskit/tooltip/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export { default } from './components/Tooltip';
                                                                                             ^^^^^^

    SyntaxError: Unexpected token export

      3 | import update from "immutability-helper";
      4 | import {components} from "react-select-2";
    > 5 | import Tooltip from "@atlaskit/tooltip";
        | ^
      6 | const isEqual = require("react-fast-compare");
      7 | import _, {replace} from "lodash";
      8 | import { get } from "$shared/request";

      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
      at Object.<anonymous> (app/javascript/customer2/components/fob/fob_utils.js:5:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        1.593s

I have this .babelrc:

{
  "presets": ["@babel/react", "@babel/env"]
}

How do I make the trivial test pass?

Upvotes: 33

Views: 44167

Answers (4)

Michael Brenndoerfer
Michael Brenndoerfer

Reputation: 4066

In certain circumstances, custom modules that live in the node_modules folder are not ready for consumption by node directly, e.g. because they are generated as a separate build step.

By default jest ignores node_modules for transformation, as they are usually vanilla JS already. However, when that's not the case, you might get your error.

You can resolve the error by making sure your transform works, and you are including the specific module(s) in your transform.

In your jest.config.ts

{...
  testEnvironment: 'node',
  transform: {
    '^.+\\.[tj]s$': [
      'ts-jest',
      {
        tsconfig: '<rootDir>/tsconfig.json'
      }
    ]
  },
  transformIgnorePatterns: ['node_modules/(?!@prisma/client-data-model/zod)'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'node'],
..}

We define that all node_modules, but @prisma/client-data-model/zod) should be ignored. As defined above, @prisma/client-data- model/zod) will now be transformed by ts-jest, too.

Upvotes: 2

Mukesh  Kumar Bagaria
Mukesh Kumar Bagaria

Reputation: 99

STEP-1. Create a .babelrc file at root directory and include given below code into it

{
    "env": {
      "test": {
        "plugins": ["@babel/plugin-transform-modules-commonjs"]
      }
    }
  }

STEP-2 Run this command in the root folder of your project-

npm install --save-dev jest @babel/plugin-transform-modules-commonjs

Jest doesn't work properly with ES6 Modules. Currently they have mentioned this thing in their website also so you can resolve this issue by following above given two steps.

Upvotes: 9

Victor Pudeyev
Victor Pudeyev

Reputation: 4539

Matt's answer is accepted b/c it is insightful. The change that did it for me was adding in package.json:

  "jest": {
    ...
    "transformIgnorePatterns": [
      "node_modules/(?!@atlaskit)"
    ],

You can add support for multiple packages at once by separating them with a |

  "jest": {
    ...
    "transformIgnorePatterns": [
      "node_modules/(?!module1|module2|etc)"
    ],

Upvotes: 45

Matt Carlotta
Matt Carlotta

Reputation: 19762

Two ways you can pass this test:

Option 1.) Setup your babel configuration to handle ES6 imports by add a testing env option (the testing environment flag will be defined in your package.json scripts, for example: "test": "NODE_ENV=testing jest" or "test": "BABEL_ENV=testing jest")...

babel.config.js

module.exports = api => {
  api.cache(true);

  return {
    presets: ["@babel/preset-env", "@babel/preset-react"],
    plugins: [
      "@babel/plugin-transform-runtime",
      ["@babel/plugin-proposal-class-properties", { loose: true }],
    ],
    env: {
      testing: {
        presets: [
          [ "@babel/preset-env", { targets: { node: "current" }}],
        ],
      },
    },
  };
};

Option 2.) Transpile the ES6 module into ES5 syntax in your webpack.config.js configuration:

webpack.config.js

const { NODE_ENV } = process.env
const inDevelopment = NODE_ENV === "development";

module.exports = {
  ...
  module: {
    rules: [
      ...
      {
        test: /\.(js|jsx)$/,
        loader: "babel-loader",
        exclude: !inDevelopment ? /node_modules\/(?!(@atlaskit\/tooltip))/ : /(node_modules)/,
        options: {
          cacheDirectory: inDevelopment,
          cacheCompression: false,
        },
      },
      ...
    ],
  }
  ...
}

The major difference between the two options is that the first option will only work in a testing environment. If you try to use it in a development/production environment, it may impact other 3rd party packages and cause compilation errors. Therefore, if you plan on moving this into a production environment that supports IE11 and below, then the second option is recommended. HOWEVER, keep in mind that this will transpile the package every time a production build is created and/or a test suite is run. Therefore, if you're working on a very large project (or transpiling multiple ES6 packages), it can be quite resource heavy. Therefore, I'd recommend compiling the 3rd party package(s) from ES6 to ES5 and installing it/them locally or privately (via an NPM package).

Working example (this example includes the second option): https://github.com/mattcarlotta/transpile-es6-module

To install:

  1. cd ~/Desktop && git clone [email protected]:mattcarlotta/transpile-es6-module.git
  2. cd transpile-es6-module
  3. yarn install
  4. yarn dev to run the demo
  5. yarn test to run test suites

Upvotes: 8

Related Questions