jest SyntaxError: Cannot use import statement outside a module エラーメモ
SyntaxError: Cannot use import statement outside a module
出ていたエラーはこれで、
SyntaxError: Cannot use import statement outside a module
エラー文は、CommonJSとES Modulesの違いによるエラーっぽいなって感じ。
module.exports = {
...
- preset: "ts-jest",
+ preset: "ts-jest/presets/js-with-babel-esm",
+ transformIgnorePatterns: ["/node_modules/(?!lodash-es)"],
}
transformIgnorePatternsだけでなく、jest.config.jsのpresetも変更したら通りました。
ts-jestではうまいことコンパイルしてくれてないのかな?
jest.config.jsのpresetについて調べてみた
jest.config.jsのpreset変更したけど、これが何かよくわからない。
公式にはこう書いてある
A preset that is used as a base for Jest's configuration. A preset should point to an npm module that has a jest-preset.json, jest-preset.js, jest-preset.cjs or jest-preset.mjs file at the root.
要は、ベースとなるconfigfileをどうするのかということらしい。
defaultはundefined
ネットでよく見かけるのは、ts-jestだが、それを使っていたらエラーが出て、
ts-jest/presets/js-with-babel-esmを使ったら解消された。
違いがよくわからなかったので、nodemoduleを覗いてみた。
ts-jest/presets/index.jsのファイルの中身はこれ
const { JS_EXT_TO_TREAT_AS_ESM, TS_EXT_TO_TREAT_AS_ESM } = require('../dist/constants')
const { createJestPreset } = require('../dist/presets/create-jest-preset')
module.exports = {
get defaults() {
return createJestPreset()
},
get defaultsLegacy() {
return createJestPreset(true, false)
},
get defaultsESM() {
return createJestPreset(false, false, { extensionsToTreatAsEsm: TS_EXT_TO_TREAT_AS_ESM })
},
get defaultsESMLegacy() {
return createJestPreset(true, false, { extensionsToTreatAsEsm: TS_EXT_TO_TREAT_AS_ESM })
},
get jsWithTs() {
return createJestPreset(false, true)
},
get jsWithTsLegacy() {
return createJestPreset(true, true)
},
get jsWithTsESM() {
return createJestPreset(false, true, {
extensionsToTreatAsEsm: [...JS_EXT_TO_TREAT_AS_ESM, ...TS_EXT_TO_TREAT_AS_ESM],
})
},
get jsWithTsESMLegacy() {
return createJestPreset(true, true, {
extensionsToTreatAsEsm: [...JS_EXT_TO_TREAT_AS_ESM, ...TS_EXT_TO_TREAT_AS_ESM],
})
},
get jsWithBabel() {
return createJestPreset(false, false, {
transform: {
'^.+\\.jsx?$': 'babel-jest',
},
})
},
get jsWithBabelLegacy() {
return createJestPreset(true, false, {
transform: {
'^.+\\.jsx?$': 'babel-jest',
},
})
},
get jsWithBabelESM() {
return createJestPreset(false, false, {
extensionsToTreatAsEsm: [...JS_EXT_TO_TREAT_AS_ESM, ...TS_EXT_TO_TREAT_AS_ESM],
transform: {
'^.+\\.m?[j]sx?$': 'babel-jest',
},
})
},
get jsWithBabelESMLegacy() {
return createJestPreset(true, false, {
extensionsToTreatAsEsm: [...JS_EXT_TO_TREAT_AS_ESM, ...TS_EXT_TO_TREAT_AS_ESM],
transform: {
'^.+\\.m?[j]sx?$': 'babel-jest',
},
})
},
}
ts-jest/presets/js-with-babel-esmの設定がこれ
module.exports = require('..').jsWithBabelESM
indexに全ての関数が集約されてて、他のファイルからそれを読んでくるだけになってるのね。
presetにts-jestと書くだけなら多分、この設定が使われている。
get defaults() {
return createJestPreset()
},
presetにts-jest/presets/js-with-babel-esmと書くとこれが使われるっぽい
get jsWithBabelESM() {
return createJestPreset(false, false, {
extensionsToTreatAsEsm: [...JS_EXT_TO_TREAT_AS_ESM, ...TS_EXT_TO_TREAT_AS_ESM],
transform: {
'^.+\\.m?[j]sx?$': 'babel-jest',
},
})
},
transformってオプションがついてるし、この設定使ったらbabelってくれそう。
余談
jestのテストでSyntaxError: Cannot use import statement outside a moduleが出た時に
このサイトのように解決策
module.exports = {
...
transformIgnorePatterns: ['node_modules/(?!@mui/material)/'],
}
を書いてくれているのが多かったが、それ通りやってもエラーが変わらなかった
結局、presetをしっかり理解してたら、変にハマらんかったってことか。
参考
https://jestjs.io/docs/tutorial-react-native#transformignorepatterns-customization
Discussion