建設予定地

当面はやったことの備忘録

【解決】画像ファイルの読み込みでシンタックスエラーが発生する

画像ファイルをインポートする必要のある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