画像ファイルをインポートする必要のあるVueコンポーネントをjestでテストした際に発生したエラーでしたが、大分長いこと格闘して、ようやく解決したのでまとめておきます。
症状
Vue.jsのテストコードを書いていて、以下のようなシンタックスエラーに遭遇した
/home/user/hogehoge/src/assets/image.png:1 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){�PNG SyntaxError: Invalid or unexpected token
テストツール
Vue test Utils, Jest
テスト対象のコンポーネント例
// sampleComponent.vue <template> ... </teplate> <script> name: 'sampleComponent', mixins: [sampleMixin], data() { return { hogehoge: require('@/assets/piyopiyo.png'), } }, methods: { move() { ... }, }, } </script> <style></style>
原因と対処法
data()メソッドの返り値を画像ファイルとした場合のみに発生するエラーで、つまるところ
画像ファイルをインポートすると、Jestは画像のバイナリコードを.jsとして解釈しようとするため、エラーが発生します。
reactjs - 画像をインポートするとjestテストが壊れます - ITツールウェブ
ということらしい。インポート時画像ファイルを正しく解釈できるようにする必要があります。
なのd、package.jsonのtransformとmoduleNameMapperに以下のような設定を追加してあげましょう。
jestjs.io
// package.json "transform": { ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest", "^.+\\.js$": "<rootDir>/node_modules/babel-jest", + "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js" }, "moduleNameMapper": { + "\\.(css|scss)$": "<rootDir>/__mocks__/styleMock.js", + "^@/(.*)$": "<rootDir>/src/$1" }
transformでは画像ファイルの拡張子がインポートされたときにroot直下にあるfileTransformer.jsをインポートするように指示しています。
同様に、moduleNameMapperでは、css、scssがインポートされたときにrootディレクトリからmocks/styleMock.jsを参照するように指示しています。
なので、package.jsonの追加記述と対応させてrootディレクトリ(基本的にはpackage.jsonと同階層です)*1にfileTransformer.js、mocksディレクトリを作成し、mocksディレクトリにはstyleMock.jsを作成します。
そのうえで、これらには以下のように記述します。
// fileTransformer.js const path = require('path') module.exports = { process(src, filename, config, options) { return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';' }, }
// styleMock.js module.exports = {}
以上の設定のもと、テスト対象のコンポーネントをmount/shallowMountして検証することにより、問題なくテストが通りました。
参考
【Jest】画像ファイルやCSSのインポートに失敗する場合の対処法 - Qiita
reactjs — JestとReactおよびCSSファイルのインポートを伴うSyntaxError