16

I want to use Import/export feature of ES6 modules (since my entire project uses that) with Jest 26.1.0.

I have created a directory for my test cases called testCases/ which contains a math.mjs file. Now I am trying to import this file in math.test.js (for Jest). Whenever I run npm run test, it throws the following error.

>Details:

    /home/jatin/Downloads/Node.js/task-manager-app/TestCases/math.test.js:1
    import calc from "../src/math.mjs";
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime._execModule (node_modules/jest-runtime/build/index.js:1179:56)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        1.556 s
Ran all test suites.
npm ERR! Test failed.  See above for more details.

I even tried changing Jest configuration,as per the documentation and other GitHub issues but no success so far.

Below is my math.mjs testing file

  const calc = (total, tippercent) => {
    const tip = total * tippercent;
    return total + tip;
}

export default calc

And this is my math.test.js

import calc from "../src/math.mjs";

test("to calculate tipercent", () => {});

How can we configure Jest to parse .mjs modules?

Jatin Mehrotra
  • 9,286
  • 4
  • 28
  • 67
  • Are you using Babel jest? – evolutionxbox Jul 27 '20 at 11:29
  • No, like I said I dont know much about jest, so somewhere I read babel-jest could help with .mjs modules so just tried, but even it didn't help me. I want to work only with jest, also can you explain to me what is the difference between the two? – Jatin Mehrotra Jul 27 '20 at 11:47
  • 1
    Babel jest doesn’t replace jest. It’s used in conjunction with it. https://www.npmjs.com/package/babel-jest – evolutionxbox Jul 27 '20 at 11:51
  • Thank you for the input, so what could be the solution to my problem? can you guide me through the configuration? – Jatin Mehrotra Jul 27 '20 at 11:55
  • https://github.com/facebook/jest/issues/5204 – evolutionxbox Jul 27 '20 at 11:56
  • I tried adding this to my package.json -> "jest": { "transform": { "^.+\\.m?jsx?$": "babel-jest" }, "testMatch": [ "**/spec/**/*.js?(x)", "**/?(*.)(spec|test).js?(x)", "**/spec/**/*.mjs", "**/?(*.)(spec|test).mjs" ], "verbose": true } However, i am getting the same error. – Jatin Mehrotra Jul 27 '20 at 12:17
  • More over these are the same Github issues, which I have seen earlier but nothing helped me so far. – Jatin Mehrotra Jul 27 '20 at 12:19
  • Have you installed and set up Babel-jest? – evolutionxbox Jul 27 '20 at 12:20
  • Yes i have installed "@babel/core", "@babel/preset-env", "babel-jest" as dev-dependency, but i have no clue how to configure it. Can you send me babel-jest configuration ? – Jatin Mehrotra Jul 27 '20 at 12:26
  • I use the standard one in the readme https://github.com/facebook/jest#using-babel. I’m only commenting to try and help, I don’t have an exact solution. – evolutionxbox Jul 27 '20 at 12:29
  • Thank you for the inputs, will look into that and will share an update. – Jatin Mehrotra Jul 27 '20 at 12:39
  • When you say you "tried changing the configuration", can you post that configuration? Since you read the guides I assume you're config is `jest.config.mjs` and you're not using the JS version of bable config i.e. `babel.config.js` for example. – Dominic Jul 27 '20 at 13:00
  • I used this from the https://github.com/facebook/jest/issues/9430 { ... "type": "module", "scripts": { ... "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js", }, "jest": { "transform": {}, "testEnvironment": "jest-environment-node" }, Anyways, thanks for the help everyone, I got my solution thanks to @tmhao2005 – Jatin Mehrotra Jul 27 '20 at 15:43

4 Answers4

11

I think it would work with following setup:

At root level of your app, jest.config.js:

module.exports = {
  testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|js?|tsx?|ts?)$",
  transform: {
    "^.+\\.jsx?$": "babel-jest",
    "^.+\\.mjs$": "babel-jest",
  },
  testPathIgnorePatterns: ["<rootDir>/build/", "<rootDir>/node_modules/"],
  moduleFileExtensions: ["js", "jsx", "mjs"]
}

And babel config babel.config.js:

const presets = [
  [
    "@babel/preset-env",
  ]
];

module.exports = { presets };

And finally your script to run the test in package.json:

"test": "jest --config=jest.config.js",
tmhao2005
  • 14,776
  • 2
  • 37
  • 44
  • 1
    In my case, because I was using modules on the test files as well, I renamed the test also to `.mjs` and changed the `testRegex` pattern a little to make jest also check for .mjs files: ```testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(mjs?|jsx?|js?|tsx?|ts?)$'``` – Eduardo Russo Aug 12 '21 at 14:05
4

Just adding my solution, since the accepted answer didn't work for me.

Your project may require different settings, of course. For instance, my test files end in .tests.mjs but yours may not. Also, if you don't use Cypress you won't need "/cypress/" in your testPathIgnorePatterns.

Some key points are:

  1. Making sure "mjs" is included in the moduleFileExtensions (if you have test files that end in .mjs).
  2. Making sure my testMatch glob ends in .?js (not .m?js, since it's a glob, not a regex) (again, if your test files end in .mjs).
  3. Making sure to define transformIgnorePatterns without "/node_modules/", which is normally included by default. This ensures the dependencies my tests use are transpiled as well. For some reason this is rarely mentioned in the help I've seen. Does no one have dependencies that use ES Modules?

As for dependencies to install, I only had to add jest and @babel/preset-env. Just to be sure, you might want to also install babel-jest and @babel/core since a lot of the documentation says so, but it looks like they're actually dependencies of jest so they came along with it.

This Jest config is included in my package.json ("jest" is a top-level key):

  "jest": {
    "moduleFileExtensions": ["mjs", "js", "jsx", "ts", "tsx", "json", "node"],
    "testMatch": [
      "**/?(*.)tests.?js"
    ],
    "testPathIgnorePatterns": [
      "/node_modules/",
      "/cypress/"
    ],
    "transform": {
      "^.+\\.m?js$": "babel-jest"
    },
    "transformIgnorePatterns": [
      "\\.pnp\\.[^\\/]+$"
    ]
  }

And this is my babel.config.json. Note that this did not work when included (verbatim!) in my package.json. It had to be a separate file.

{
  "presets": [
    [
      "@babel/preset-env", {
        "targets": {"node": "current"}
      }
    ]
  ]
}
Nick S
  • 555
  • 4
  • 17
  • 1
    I got to work with ```.tests.mjs``` files but when using ```import``` for importing a controller or service file ( like user.service.mjs) I got this error: ```ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From __tests__/sample.tests.mjs. at async Promise.all (index 2)``` – Ali Shefaee Jul 07 '22 at 09:47
2

There are instructions how to do this in jest docs.

Simplest configuration:

  • disable transfrom in package.json:
    "jest": {
      "transform": {}
    }
    
  • modify test script in package.json:
    "test": "NODE_OPTIONS=--experimental-vm-modules jest",
    
  • create a function index.mjs:
    export const sum = (a, b) => a + b;
    
  • write a test in index.test.js:
    import { sum } from './index.mjs';
    
    it('sum() returns sum of two numbers', () => {
      expect(sum(1,2)).toBe(3);
    };
    
Oleh
  • 472
  • 6
  • 13
  • i get error 'NODE_OPTIONS' is not recognized as an internal or external command, operable program or batch file. – Tadas V. Mar 09 '23 at 08:22
  • NODE_OPTIONS is simply environment variable. @TadasV. I suppose you are running on windows have a look into this question https://stackoverflow.com/questions/53948521/node-options-is-not-recognized-as-an-internal-or-external-command – Oleh Mar 09 '23 at 16:53
  • 1
    yes its win issue. node --experimental-vm-modules node_modules/jest/bin/jest.js solved it – Tadas V. Mar 09 '23 at 18:09
1

It doesn't support ES modules :< https://github.com/facebook/jest/issues/4842

OZZIE
  • 6,609
  • 7
  • 55
  • 59