概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Testing Vue.js in Rails with Webpacker and Jest
- 原文公開日: 2018/01/16
- 著者: Mario Saul
RailsのVue.jsをWebpackerとJestでテストする(翻訳)
今やっているプロジェクトで、既存のRailsアプリにVue.jsを統合する方法の調査をを命じられました。とりあえず公式ガイドを読み、チュートリアルを視聴し、ブログを読みまくった結果、Vueコンポーネントを完全に動かせるようになりました。
最後の段階でいくつかテストを書こうとしましたが、残念なことにWebpacker gemにはテスト向け設定が含まれていなかったので、自分で設定せざるを得ませんでした。
驚いたことに、満足な設定方法がドキュメントに見当たらなかったのです。そこで私が何とかこれを動かせるようにしたときの方法を本記事で皆様と共有したいと考えました。
1. Jestのインストール
特にこれといった好みもなかったので、Jestを使うことに決めました。vue-cliも同梱されていたので使いました。
Jestのインストールで必要なのは、プロジェクトのルートディレクトリでyarn add --dev jest
を実行することだけです。続いて、package.json
に自分のテストスクリプトを追加します。
{
"scripts": {
"test": "jest",
...
},
...
}
これで、yarn test
を実行すればテストが走ります。
2. テストの置き場所を定義する
この時点でyarn test
を実行しようとすると、config/webpack/test.js
でコケます。これは、Jestがプロジェクト内のテストファイルを探索する方法が原因です。基本的にはプロジェクト全体のうち.spec.js
か.test.js
にマッチするすべてのファイルを実行します。ここではテストファイルが*.test.js
とマッチしたので、テストとして実行されようとしていたのです。
自分たちのテストを実行する基準を満たすプロジェクト内の他のファイルと同様、Webpack configファイルを使わないようにしたいので、探索するファイルの場所をJestに指定する必要があります。
ここではRspecを使っていることもあり、spec/javascripts
ディレクトリを探索場所として指定することにしました。もちろん、自分のプロジェクトに合う場所を自由に指定することもできます。
これを行うには、package.json
ファイルにrootsを追加しなければなりません。
"jest": {
"roots": [
"spec/javascript"
]
},
package.json
のサイズがかなり大きいのでこのファイルにこれ以上設定を追加したくない場合は、--config <path/to/js|json>
オプションでJest設定を定義できます。この方法にする場合、package.json
は次のような感じになるはずです。
{
"scripts": {
"test": "jest --config spec/javascript/jest.conf.js",
...
},
...
}
これが動作することを確認するために、以下のようなシンプルなテストをspec/javascript/team.spec.js
ファイルを作成してもよいでしょう。
test('there is no I in team', () => {
expect('team').not.toMatch(/I/);
});
これで再びyarn test
を実行すれば、greenの「PASS」が表示され、動作していることがわかるはずです。
3. babelをrescueする
最初のテストが動くようになったので、一歩進めてVueコンポーネントをテストしてみましょう。
最初にやってみるのは、たいていspec/javascript/
の下にファイルを作成してmy_component.spec.js
のような名前を付けることでしょう。続いて次のようにimportステートメントで自分のコンポーネントをspecにインポートしてみましょう。
import MyComponent from '../../app/javascript/my_component.vue';
これをやってみた方は、そのままyarn test
でテストを実行してみてください。SyntaxError: Unexpected token import
エラーが出力されます。
ここでの問題は、import
がECMAScript 6の一部である点です。つまりBabelなどのトランスパイラの助けが必要になるということです。
動くようにするには、yarn add --dev babel-jest babel-preset-es2015
で2つのパッケージをインストールし、.babelrc
ファイルにes2015
プリセットを追加する必要があります。
{
"presets": ["es2015",
["env", {
...
さらに一歩進めてみたい方は、moduleDirectoriesをpackage.json
に追加すると、モジュールへのフルパスを入力しなくても済むようになります。
"jest": {
...
"moduleDirectories": [
"node_modules",
"app/javascript"
]
}
これで、先ほどのパスを簡単にできます。
import MyComponent from '../../app/javascript/my_component.vue';
上のパスは以下のように書けます。
import MyComponent from 'my_component.vue';
4. Vueが見つからない
ここまでの手順をすべて行った場合、yarn test
でテストを実行するとまたしてもSyntaxError
が表示されます。これは、コンポーネントのimport
は成功したものの、.vue
ファイルフォーマットを理解できていないためです。
幸い、この辺りの面倒を見てくれるvue-jestを使えます。早速yarn add --dev vue-jest
を実行してvue-jestをインストールし、READMEの指示に沿ってmoduleFileExtensions
、transform
、mapCoverage
を追加します。追加後のpackage.json
は次のような感じになるはずです。
"jest": {
...
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
},
"mapCoverage": true
}
moduleFileExtensionsを使うと、単一のファイルコンポーネントのimport
で.vue
拡張子が不要になります。
import MyComponent from 'my_component.vue';
上のパスは、以下のように書き換えられます。
import MyComponent from 'my_component';.
これで、import
をシームレスに使えるようになりました。
transform
セクションに記述されたルールでは、テストするファイルの変換を担当するパッケージを指定します。ここではすべての.vue
ファイルの扱いをvue-jest
に任せたいので、これらのファイルはJestで扱われる前に純粋なJavaScriptに変換されます。
mapCoverage
は、トランスフォーマーが生成するソースマップを使うために設定してあります。Jestはこのソースマップを用いて、カバレッジの試行や、レポート生成時や閾値チェック中に元のソースコードとのマッピングを行います。
最後に、Vue.js公式の単体テストユーティリティライブラリであるvue-test-utilsを追加しましょう。yarn add --dev @vue/test-utils
を実行するだけですぐ使えるようになります。
ついにVueコンポーネントのテストを書けるようになりました🎉。
クレジット
本記事は、Jest公式ドキュメントやHow to setup JavaScript testing in Rails 5.1 with Webpacker and JestなどWeb上の多数のドキュメントから集めた情報を元に執筆いたしました。