'How to import ".mjs" modules in Jest's xyz.test.js?

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?



Solution 1:[1]

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",

Solution 2:[2]

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

Solution 3:[3]

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"}
      }
    ]
  ]
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tmhao2005
Solution 2 OZZIE
Solution 3 Nick S