ChatGPT解决这个技术问题 Extra ChatGPT

Does Jest support ES6 import/export?

If I use import/export from ES6 then all my Jest tests fail with error:

Unexpected reserved word

I convert my object under test to use old school IIFE syntax and suddenly my tests pass. Or, take an even simpler test case:

   var Validation = require('../src/components/validation/validation'); // PASS
   //import * as Validation from '../src/components/validation/validation' // FAIL

Same error. Obviously there's a problem with import/export here. It's not practical for me to rewrite my code using ES5 syntax just to make my test framework happy.

I have babel-jest. I tried various suggestions from GitHub issues. It is no go so far.

File package.json

 "scripts": {
    "start": "webpack-dev-server",
    "test": "jest"
  },
      "jest": {
        "testPathDirs": [
          "__tests__"
        ],
        "testPathIgnorePatterns": [
          "/node_modules/"
        ],
        "testFileExtensions": ["es6", "js"],
        "moduleFileExtensions": ["js", "json", "es6"]
      },

File babelrc

{
  "presets": ["es2015", "react"],
  "plugins": ["transform-decorators-legacy"]
}

Is there a fix for this?

does this help at all?
@GeorgePompidou - Possibly. I'm not sure if/how the solution applies to babel-jest
it's a matter of specifying something like "presets": ["es2015"] in a package.json or a .babelrc. you are using babel, after all.
@GeorgePompidou - In that case the solution does not work. I already have a babelrc containing es2015, react presets. Standard transpilation works, inside of gulp. It's just the Jest framework that can't handle it.
This question is from 5 years ago and yet jest's support for ES modules is experimental.

P
Peter Mortensen

From my answer to another question, this can be simpler:

The only requirement is to configure your test environment to Babel, and add the ECMAScript 6 transform plugin:

Step 1:

Add your test environment to .babelrc in the root of your project:

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

Step 2:

Install the ECMAScript 6 transform plugin:

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

And that's it. Jest will enable compilation from ECMAScript modules to CommonJS automatically, without having to inform additional options to your jest property inside package.json.


If you don't want to pollute your project with .babelrc, you can add the env key above under a babel key in package.json.
I believe the more recent @babel/plugin-transform-modules-commonjs replaces transform-es2015-modules-commonjs
Man this was taking me forever! Thanks!
This should be the correct answer, so dead simple.
@P.Brian.Mackey sure! If you already tested the new approach, and Babel isn't needed anymore, this is good news and it's important to update the community about the updated approach. :)
E
Eric

UPDATE 2020 - native support of ECMAScript modules (ESM)

According to this issue, there is native support of ESM from jest@25.4.0. So you won't have to use babel anymore. At the time of writing this answer (05/2020), to activate that you need to do three simple things:

Make sure you don't transform away import statements by setting transform: {} in config file

Run node@^12.16.0 || >=13.2.0 with --experimental-vm-modules flag

Run your test with jest-environment-node or jest-environment-jsdom-sixteen.

So your Jest configuration file should contain at least this:

export default {
    testEnvironment: 'jest-environment-node',
    transform: {}
    ...
};

And to set --experimental-vm-modules flag, you will have to run Jest as follows:

node --experimental-vm-modules node_modules/jest/bin/jest.js

Also note in the Github issue that this approach does not yet support the jest object. So you may need to import it manually:

import {jest} from '@jest/globals'

(I hope this will change in the future)


What is the 'jest-environment-node' and how does it differ from an environment 'node'?
it's a test environment that will be used for testing. It's jsdom by default. You can find more information here jestjs.io/docs/en/configuration#testenvironment-string
NODE_OPTIONS='--experimental-vm-modules' jest is a bit cleaner to run jest
As an important note, native support does not support mocking as of yet
4th thing to do to make this work: package.json should contain "type": "module" for Node to detect files as ESM, see nodejs.org/api/packages.html#packages_determining_module_system
P
Peter Mortensen

For an updated configuration, I'm using https://babeljs.io/setup#installation

Select JEST and be happy:

As a reference, the current configuration:

npm install --save-dev babel-jest

In your package.json file, make the following changes:

{
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "transform": {
      "^.+\\.jsx?$": "babel-jest"
    }
  }
}

Install babel preset:

npm install @babel/preset-env --save-dev

Create a .babelrc file:

{
  "presets": ["@babel/preset-env"]
}

Run your tests:

npm run test

Worked for me! The babel docs have been updated to specify .ts files too in the regex. Didn't need any other dependency for typescript like ts-jest. I did need @babel/preset-typescript. Added it to the list of presets in the .babelrc file.
This is basically the correct answer. Here is another good reference page from jest's own docs jestjs.io/docs/getting-started#using-babel
thanks this worked for me. As of now, you do not need to add the transform to your package.json. It is now default.
C
CodeFinity

In package.json, kindly set like this one: "test": "node --experimental-vm-modules node_modules/.bin/jest"

Should be good!


Nope! won't do it! Mocks will not work.
Sorry to hear that. There are some nuances to getting jest to work and even on Windows vs Mac sometimes issues. NS what you are trying to do exactly, but here is a template repo that I use for Node stuff that has a fully working jest (using nodemon). It includes other stuff that you may or may not want, but you can at least use as a guide?
I followed this answer instead. stackoverflow.com/a/52224329/985942 basically use babel to transform everything back to commonjs
Right. That's what that repo ends up doing. 🆒
P
Peter Mortensen

It's a matter of adding stage-0 to your .babelrc file. Here is an example:

{
  "presets": ["es2015", "react", "stage-0"],
  "plugins": ["transform-decorators-legacy"]
}

PS: don't forget to install the stage-0 preset through npm
Don’t ever use stage-0 or any stage-* in production. This answer is bad practice. Use preset-env
Y
YOSEPH NOH

I encountered the same issue.

These are what I did:

yarn add --dev babel-jest @babel/core @babel/preset-env

Make file jest.config.js in rootDir.

module.exports = {
    moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "json"],
    transform: {
        '^.+\\.(js|jsx)?$': 'babel-jest'
    },
    testEnvironment: 'node',
    moduleNameMapper: {
        '^@/(.*)$': '<rootDir>/$1'
    },
    testMatch: [
        '<rootDir>/**/*.test.(js|jsx|ts|tsx)', '<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
    ],
    transformIgnorePatterns: ['<rootDir>/node_modules/']
};

Then make file babal.config.js in rootDir.

Go like this:

module.exports = {
    "presets": ["@babel/preset-env"]
}

G
Gilbert

Below is how I setup jest, typescript and ES Modules for my project.

jest.config.js

/**
 * @type {import('ts-jest/dist/types').InitialOptionsTsJest} 
 * To configure ESM support, see: https://kulshekhar.github.io/ts-jest/docs/guides/esm-support
 * 
 **/
export default {
    preset: 'ts-jest/presets/default-esm',
    testEnvironment: 'node',
    extensionsToTreatAsEsm: ['.ts'],
    globals: {
        'ts-jest': {
            useESM: true
        }
    },
    setupFiles: ['<rootDir>/__tests__/setup.ts'],
};

tsconfig.json

{
    "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "outDir": "./dist",
        "moduleResolution": "node",
       // "strict": true,
        "esModuleInterop": true,
        "inlineSourceMap": true,
    }
}

package.json scripts and devDependencies

"scripts": {
    "start": "node ./dist/server.js",
    "dev": "tsc-watch --onSuccess \"node ./dist/server.js\"",
    "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
  },
"devDependencies": {
    "@jest/globals": "^27.4.4",
    "@types/express": "^4.17.13",
    "@types/jest": "^27.4.0",
    "@types/supertest": "^2.0.11",
    "cross-env": "^7.0.3",
    "supertest": "^6.2.1",
    "ts-jest": "^27.1.3"
  }

__tests__/setup.ts

import dotenv from 'dotenv';


dotenv.config({
    path: './.env.test'
});

P
Peter Mortensen

In addition to installing babel-jest (which comes with Jest by default now) be sure to install regenerator-runtime.


If I configured jest with a babel config like this {presets: [['@babel/preset-env', {targets: {node: 'current'}}]]}; then regenerator runtime was not needed (without the node:'current' part it did warn about this). See jestjs.io/docs/getting-started#using-babel
b
bFunc

To add support for React and react-testing-library it may be useful to eject CreateReactApp and take all needed Jest configuration from the package.json. It is ready to use with another bundler, Rollup in my case.