2021-05-03
|~2 min read
|311 words
If you are taking advantage of ES Modules, whether through a .mjs
extension or babel transpilation, it’s likely that you’re using the import
/export
syntax. This can pose problems for Jest which defaults to using Node’s require
syntax.
A quick fix for this problem, assuming babel is responsible for the transpilation (and perhaps Webpack is responsible for tree-shaking), is to check whether tests are being run before determining who should transpile the modules.
For example, imagine the above scenario: babel owns transpiling, but defers to Webpack for tree-shaking, and so doesn’t handle the conversion to modules. You might have something like the following:
module.exports = {
presets = [
['@babel/preset-env',{modules: false}]
],
}
const path = require("path")
module.exports = {
resolve: {
modules: ["node_modules", path.join(__dirname, "src"), "shared"],
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: "babel-loader",
},
],
},
}
Here, we explicitly tell Babel to ignore modules and then resolve them with Webpack. The issue is that if we wanted to use one of our methods within a Jest test, we’d be forced to use require
. Without it, we’ll get a syntax error:
import { myUtility } from "../utils.js"
//...
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { getFormattedValue } from './utils';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
The fix is straightforward: interrogate the NODE_ENV
to determine if we’re running tests, and if we are, pull the module resolution into Babel’s purview. If we’re not, allow Webpack to continue owning this responsibility.
+ isTest = process.env.NODE_ENV === 'test'
module.exports = {
presets = [
- ['@babel/preset-env',{modules: false}]
+ ['@babel/preset-env',{modules: isTest ? 'commonjs' : false}]
],
}
Because our .babelrc
is written in Javascript, this is as simple as assigning a value to isTest
and then using a ternary expression. With that change, Jest can now use ES modules!
Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!