Do you want to request a feature or report a bug?
bug
What is the current behavior?
babel-jest is not able to transpile es6 module statements if in *.mjs files
If the current behavior is a bug, please provide the steps to reproduce and either a repl.it demo through https://repl.it/languages/jest or a minimal repository on GitHub that we can yarn install
and yarn test
.
What is the expected behavior?
Babel should transpile module import/export statements also with mjs files
Please provide your exact Jest configuration and mention your Jest, node, yarn/npm version and operating system.
jest.config.js
module.exports = {
verbose: true,
moduleDirectories: ['node_modules', 'imports'],
testMatch: ['/tests/**/*.js', '**/?(*.)test.js'],
transform: {
'^.+\\.m?js$': 'babel-jest',
},
}
.babelrc
{
"env": {
"test": {
"presets": [
["es2015", { "modules": false }]
],
"plugins": [
["transform-es2015-modules-commonjs", {
"spec": true
}]
]
}
}
}
Note: I've tried disabling the transform-es2015-modules-commonjs plugin, but then the syntax error is back in the test js file
Node: v8.6
babel-core: 6.26.0
babel-jest: 21.2.0
babel-plugin-transform-es2015-modules-commonjs: 6.24.1
babel-preset-es2015: 6.24.1
jest: 21.2.0
Example output error:
yarn run v1.1.0
$ jest
FAIL tests/integration/controller/data-provider/Credentials/CredentialsList.action.test.js
● Test suite failed to run
/app/tests/integration/controller/data-provider/Credentials/CredentialsList.action.test.js:2
import { Credentials, AdWordsCredentials } from '../../../../../imports/models/data-provider/Credentials.mjs';
^^^^^^
SyntaxError: Unexpected token import
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:305:17)
at Generator.next (<anonymous>)
at Promise (<anonymous>)
P.S.
If I call my test files ending with .test.mjs
and I edit the testMatch
accordingly, jest won't recognize them
Another way expect from transpiring with babel would be to use experimental ES6 module support, see https://nodejs.org/dist/latest-v8.x/docs/api/esm.html
I am currently trying to extend the testMatchers like this:
"jest": {
"verbose": true,
"testMatch": ["**/__tests__/**/*.?(m)js?(x)", "**/?(*.)(spec|test).?(m)js?(x)"]
}
but still my test named [test].test.mjs is still not found.
@mknet ,
I'm ashamed to say that I don't fully understand the Jest matching pattern. It does not make sense to me at all: at js?(x)
?
should be applied to s
meaning either jx
or jsx
would be a match which seems strange.
So not fully understating it, I used a plain stupid approach with:
"testMatch": [ "**/__tests__/**/*.js?(x)", "**/?(*.)(spec|test).js?(x)", "**/__tests__/**/*.mjs", "**/?(*.)(spec|test).mjs" ]
and that (probably not even surprisingly to me) worked.
We also need to specify --experimental-modules
node flag to make node recognize ESM modules.
But still, with all that it fails to me with the error similar to the one @elegos reports :-(. Wish there were better support of ESM in Jest. Because ESM's are great, I believe.
So to clarify, this still doesn't work from what I can tell.
@kirlat
Your matching pattern doesn't work for me.
@elegos You need to add moduleFileExtensions: ["js", "json", "jsx", "node", "mjs"]
. It will find mjs
files, but they are not supported by now, as I understood. It hardcoded in babel-core 6.
https://github.com/babel/babel/blob/v6.26.0/packages/babel-core/src/util.js#L15
And it is extended to mjs
in babel 7 beta
Came here because I added a transform to my package.json to transpile files with the .es6 label. It didn't work until also adding ".es6" to moduleFileExtensions
"transform": {
"^.+\\.jsx?$": "/Users/.../node_modules/babel-jest/build/index.js",
"^.+\\.es6$": "/Users/.../node_modules/babel-jest/build/index.js"
}
The get-around as of jest 22.4.3 and babel-core 6.26.3:
Therefore insert the following into package.json:
"jest": {
"testMatch": [
"**/__tests__/**/*.?(m)js?(x)",
"**/?(*.)(spec|test).?(m)js?(x)"
],
"moduleFileExtensions": [
"js",
"json",
"jsx",
"node",
"mjs"
],
"transform": {
"^.+\.m?js$": "babel-jest"
}
},
"babel": {
"env": {
"test": {
"presets": [["es2015",{"modules": false}]],
"plugins": [["transform-es2015-modules-commonjs", {"spec": true}]]
}
}
},
add preset:
yarn add --dev babel-preset-es2015 babel-plugin-transform-es2015-modules-commonjs babel-jest babel-core
yarn test now works with tests named .test.mjs and source files named .mjs
thank you @haraldrudell your solution saved me a lot of hairpulling. Your solution also works with Babel7 once plugin names are adjusted.
.babelrc
:
{
"env": {
"test": {
"presets": [["@babel/preset-env",{"modules": false}]],
"plugins": [["@babel/plugin-transform-modules-commonjs", {"spec": true}]]
}
}
}
yarn add --dev @babel/preset-env @babel/core @babel/plugin-transform-modules-commonjs babel-jest
Isn't this a dupe of #4842?
@haraldrudell: can you please format that package.json code as a code block, using three backticks? Also, I get a syntax error due to the \
in the key under transform
. An alternative that still matches a period is [.]
. Also, no need for [[
. Just [
is enough.
@kirlat: that glob pattern is confusing because you were expecting a regular expression, but testMatch
uses micromatch
and those are extended globbing patterns (or shell regular expressions). In your example, ?(expression)
means the expression may appear or not. In this case, x
may or may not be present, so Jest matches .js
and .jsx
.
In my case all I needed to do to get it working was add transform
and moduleFileExtensions
options in package.json:
"jest": {
"transform": {
...
"^.+\\.mjs$": "babel-jest"
},
...
"moduleFileExtensions": [
...
"mjs"
],
(Of course if you don't already have the babel-jest
package installed you will need to install it with npm install -D
or yarn add -D
.)
Comment above is correct 🙂
@mbrowne this solution was already mentioned in https://github.com/facebook/jest/issues/4637#issuecomment-385291263
@SimenB: the problem isn't entirely solved. I'm using the settings listed by @mbrowne, but get weird errors with imports from CommonJS modules. Here's a reproduction repo: https://github.com/dandv/jest-mjs-devx
Please re-open. .mjs
files have been around since Node v8.5.0 but the developer experience using them in Jest is pretty poor. If there is a clear solution for being able to use them, including my use case above, I would love to know about it. But right now, it's a shot in the dark and devs have to rummage through GitHub comments to figure out how to use them.
Using .mjs
files is something that should be cleanly documented.
PR most definitely for documenting mjs usage.
Thanks for the reproduction, I'll take a look later today!
@dandv this is a problem with graphql-tools - they have transpiled away their import
/export
, so it's not compatible with babel and actual ESModules at the same time.
This fixes your test, but makes npm start
fail.
diff --git i/basic.test.mjs w/basic.test.mjs
index 972110c..427162c 100644
--- i/basic.test.mjs
+++ w/basic.test.mjs
@@ -1,5 +1,5 @@
import { makeSchema } from './lib';
test('basic test', () => {
- expect(makeSchema).toNotBe(null);
+ expect(makeSchema).not.toBe(null);
});
diff --git i/lib.mjs w/lib.mjs
index 5717d51..81e22e0 100644
--- i/lib.mjs
+++ w/lib.mjs
@@ -1,5 +1,6 @@
-import graphQLTools from 'graphql-tools';
-export const makeSchema = graphQLTools.makeExecutableSchema({
+import { makeExecutableSchema } from 'graphql-tools';
+
+export const makeSchema = makeExecutableSchema({
typeDefs: 'type Foo { bar: Int! }',
resolvers: {},
});
The way of importing I changed to is the way it's documented here: https://github.com/apollographql/graphql-tools. The fact that doesn't work with Node's esm mode is not Jest's fault
Also note that the current implementation in node might be pulled and redone, so asking the ecosystem to change so you can use experimental flags with their current behavior might not be the best way forward: https://github.com/nodejs/modules/pull/180
Something like @std/esm
on your side is probably a better solution than --experimental-modules
re: nodejs/modules#180
it isn't getting pulled, but we are removing some of the features. .mjs
is currently not going anywhere. We are also in the process of getting this standardized with the ietf
Edit: to be clear I meant not going anywhere as in it is not going to disappear, we believe it will stick around for all future implementations
@SimenB: any idea how to actually get @std/esm to work with Jest?
See #7018 for latest progress on that, although that proposal will not work alongside babel-jest
not going anywhere as in it is not going to disappear, we believe it will stick around for all future implementations
Indeed, v12 released new experimental support for .mjs
. Any updates in the light of that?
https://github.com/nodejs/node/issues/27387 may be of interest
I have a node_module (Ramda) that is building to a .mjs
file. And now I have tests failing that are relying on ramda.
https://github.com/ramda/ramda/commit/79a7d9d893dd50c995b25b8fd4e1ecd8e96a4abc
Is there a way to fix this issue with Babel?
Here's what I did in my package.json
to fix this issue I was having ^^^^
"jest": {
"moduleNameMapper": {
"ramda": "ramda/src/index.js",
}
}
Any updates now that ES modules are no longer behind an experimental flag?
Most helpful comment
Any updates now that ES modules are no longer behind an experimental flag?