24

I'm trying to test a file which needs to import an es6 module like this:

https://repl.it/HG9t/0

It seems I'm missing some configurations to make it work properly.

If you can achieve this with another unit testing framework easily, I'm interested too.

Thank you in advance for your help.

Alphapage
  • 901
  • 1
  • 6
  • 29

3 Answers3

11
  1. Install required dependencies:

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

or

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

  1. Create babel.config.js in your main folder and paste it there:
// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current',
        },
      },
    ],
  ],
};
  1. Make sure all your jest settings in package.json and jest.config.js are set to default.
Ilyich
  • 4,966
  • 3
  • 39
  • 27
  • 1
    I got "Error while loading config - You appear to be using a native ECMAScript module configuration file, which is only supported when running Babel asynchronously." – Raine Revere May 09 '21 at 16:14
10

As node does not support modules you have to compile your files using Babel. Have a look at the docs on how to configure Jest and Babel

apnerve
  • 4,740
  • 5
  • 29
  • 45
Andreas Köberle
  • 106,652
  • 57
  • 273
  • 297
  • 11
    Node has been supporting modules with the `--experimental-modules` flag since v8.5. – Dan Dascalescu Aug 16 '18 at 01:22
  • 1
    Even without the .mjs extension? – Biel Simon Aug 23 '18 at 18:40
  • 5
    @BielSimon Yes, without the mjs extension. You need `"type": "module"` in your package.json and the flag mentioned by Dan. – Chris Magnuson Jun 10 '19 at 17:54
  • 2
    `"type": "module"` will only work from node v12 onwards https://nodejs.org/docs/latest-v12.x/api/esm.html but you can use `node -r esm` – velop Sep 05 '19 at 11:45
  • You don't even need `"type":"module"` at all (unless you do things the official Node way). If you just use `-r esm` ... with a normal library (eg. Node itself, or Mocha) that supports it, ES6 modules "just work". – machineghost Sep 16 '19 at 23:52
  • I'm getting `ReferenceError: module is not defined` when I put "type": "module" in my package.json file – roadev Feb 26 '21 at 01:29
0

I had a similar problem with the npm packages 'rgb-hex' and 'hex-rgb' because their main export is done in ES6 format. I was using a Typescript project with Jest. I think the error comes from the Jest end and not Typescript, as Jest works on properly transpiled javascript (according to its own config). The underlying problem is these ES6 style main exports will cause problems with Jest (not tsc or Typescript chain) because you need to tell Jest to transpile.

I found a usable config using the package 'ts-jest' with the following configs, based on simple presets (the only thing to note is the ignore patterns):

tsconfig.json:

{
    "compilerOptions": {
      "esModuleInterop": true,
      "module": "es2020",
      "moduleResolution": "nodenext",
      "forceConsistentCasingInFileNames": true,
      "strict": true,
      "skipLibCheck": true,
      "rootDir": "./",
      "allowJs": true
    },
    "ts-node": {
        "esm": true
    },
    "include": ["./ts-src/**/*"]
  }

jest.config.cjs

module.exports = {
  verbose: true,
  preset: 'ts-jest/presets/js-with-babel-esm',
  testEnvironment: 'node',
  transformIgnorePatterns: ['/node_modules/(?!(hex\-rgb|rgb\-hex)/)']
};

NOTE: Above, the preset setting is important you want the babel with esm, according to docs of 'ts-jest'.

babel.config.cjs (totally vanilla but included and I think necessary)

module.exports = {
    presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
  };

Note the ignore patterns for the stuff from node_modules. You're using the negation in regex with a grouping to tell it "yes ignore node_modules for transpiling, aside from these specific package patterns". The reason this stuff comes up with Jest is packages in node_modules usually don't use ES6 exports from their main file, index.js file (or similar). And Jest doesn't usually transform them, because then it would have to scan all of node_modules. So you use those ignore patterns (with somewhat counter-intuitive regex) to transpile specific things in node_modules.

EDIT: the .cjs extensions are because my overall project was using "type": "module" in the package.json. If you leave these files as .js you'll get a very descriptive error. The .cjs extension tells Node to relax and just use the configs in the current canonical format their frameworks use (which is not ES6... lol JS never change)

bbuck
  • 129
  • 10