'How to use ESM tests with jest?

My setup

  • Node v14.16.0
  • I have one test file that contains a simple test written with ESM modules (import).
  • In package.json I have a script (following Jest documentation adapted to Windows): "test": "set \"NODE_OPTIONS=--experimental-vm-modules\" && npx jest"
  • My tests are run w/ npm run test (the script above)

My goal: Run the ESM tests using jest.

My attempts:

(1) CommonJS App w/ .js test

  • package.json contains "type": "commonjs"
  • Test file named test.js
  • Error: SyntaxError: Cannot use import statement outside a module (This is expected because the test is being run as a commonjs file.)

(2) CommonJS App w/ .mjs test

  • package.json contains "type": "commonjs"
  • Test file named test.mjs
  • Error: No tests found (Jest isn't finding the file?)

(3) ESM App w/ .js or .mjs

  • package.json now has "type": "module"
  • Test file named test.mjs or test.js
  • Error: ReferenceError: module is not defined at ...jest.config.js:6:1

(4) CommonJS App and CommonJS test

  • package.json contains "type": "commonjs"
  • Test file named test.js but using the commonjs require syntax (and without the ESM modules I'd like to include); Note that this is not what I want, but included just to show there's nothing wrong with the test itself.
  • Test runs fine and passes


Solution 1:[1]

Here are the steps I took to run Jest with a test using ESM. The source files under test were also written using ESM.

  1. Set my node version to 14.16.0
  2. npm i jest -D installs Jest as a dev dependency
  3. Add "type": "module" to package.json
  4. Update scripts in package.json to include "test": "node --experimental-vm-modules ./node_modules/.bin/jest"
  5. Create a jest.config.js file with the following content: export default { transform: {} }
  6. Have at least one test that could be found using the default testMatch (mine was inside __tests__ dir)
  7. npm test

There is a more complete example in the webpack-strip-debug-loader repository on GitHub.

Solution 2:[2]

For me to work it was only necessarry to set script "test" as follows:

"test": "cross-env NODE_OPTIONS=--experimental-vm-modules npx jest"

and yeah, don't forget -> npm i cross-env jest

Solution 3:[3]

After a lot of fiddling, this is my successful setup (the parts that matter):

  • package.json has
  "type": "commonjs",
  "script": {
    "test": "NODE_OPTIONS=--experimental-vm-modules jest"
  }
  • jest.config.mjs (yes, esModule)
export default {
  moduleFileExtensions: [
    "mjs",
    // must include "js" to pass validation https://github.com/facebook/jest/issues/12116
    "js",
  ],
  testRegex: `test\.mjs$`,
};

That having to include "js" is a historic relic from the times modules where obviously .js files. Follow https://github.com/facebook/jest/issues/12116 for update.

Solution 4:[4]

Here's the minimum you need. Props to @Luke for the comment above with the testMatch answer I needed.

  1. package.json - Make sure "type": "module" is in there

  2. jest.config.js - Add this glob to your testMatch array: "**/?(*.)+(spec|test).(m)js"

  3. Make sure your test file(s) end in .spec.mjs or .test.mjs to match the glob

  4. Set your npm test script to node --experimental-vm-modules ./node_modules/.bin/jest

That's it. You do not need the transform setting in the jest config as the documentation suggests.

Solution 5:[5]

in my case, leaving

  • "type": "module" in package.json

and renaming

  • jest.config.js to jest.config.cjs
  • babel.config.js to babel.config.cjs

worked

Solution 6:[6]

I think your issue lies in this line and how you're retrieving the tag info from the CSV object from your foreach loop:

$scriptBlock = [scriptblock]::Create('@{$info.Tags}')

In the previous line in your script, to define the $tags variable, you retrieve the value of the name of the VM in the CSV object using ($info.psobject.properties.value[0]). I would attempt to use that same format in the next line, but modifying it to retrieve the tag part of the CSV object using the index of 1:

So instead of:

$scriptBlock = [scriptblock]::Create('@{$info.Tags}')

use:

$scriptBlock = [scriptblock]::Create('@{$info.psobject.properties.value[1]}')

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
Solution 2 Vladimir Trotsenko
Solution 3 joegomain
Solution 4 Brandon Aaskov
Solution 5 raquelhortab
Solution 6 JGoose