Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 311
Jatin Mehrotra Avatar asked Jul 27 '20 11:07

Jatin Mehrotra


People also ask

How do I enable ES modules in node JS?

To be able to load an ES module, we need to set “type”: “module” in this file or, as an alternative, we can use the . mjs file extension as against the usual . js file extension. Also, from Node version 12.7.

Does Nodejs support ES6 modules?

The syntax for importing modules in ES6 looks like this. The reason for this error is that Node js doesn't support ES6 import directly. If you try to use import for importing modules directly in node js it will throw out that error.

What is an MJS file?

A file with . mjs extension is a JavaScript source code file that is used as an ECMA Module (ECMAScript Module) in Node. js applications. Node. js's natvie module system is CommonJS that is used to split the code in different files to keep the JS code organized.


2 Answers

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",
like image 196
tmhao2005 Avatar answered Oct 19 '22 07:10

tmhao2005


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"}
      }
    ]
  ]
}
like image 2
Nick S Avatar answered Oct 19 '22 06:10

Nick S