Vue CLI 環境で Jest によるユニットテスト環境を構築しようとしたところ、 scss や CSS Modules との兼ね合いでうまくテストを走らせられませんでした。
スタイルに関するユニットテストをしないなら、テスト時はスタイルのコンパイルを止められるのではないかと考え調べてみたところ、実現できることがわかったのでその設定を紹介します。
動作確認した環境
- macOS Catalina
- Chrome 83
- Node.js 12.18.1
- npm 6.14.5
- Vue CLI v4.4.4
-
vue
2.6.11 -
sass
(dart-sass) 1.26.5 -
sass-loader
8.0.2 -
@vue/test-utils
1.0.3 -
@vue/cli-plugin-unit-jest
4.4.0
-
テスト時のスタイルのコンパイルを止める方法
vue-jest
の設定で experimentalCSSCompile
1を false
にします:
module.exports = {
preset: '@vue/cli-plugin-unit-jest/presets/typescript',
globals: {
'vue-jest': {
experimentalCSSCompile: false
}
}
}
ユニットテスト時のスタイルのコンパイルを止めた理由
理由1: スタイルに関するユニットテストは難しい
デザインの変更が頻繁に発生する場合、「この状態のときは○○の色が赤である」といったテストは壊れやすいのではないかと思います。
(デザイナーがわずかに色を調整するとユニットテストが通らなくなる、といったケースなど)
スタイルに関するユニットテストはしないという選択をする場合、テスト時は vue ファイルのスタイルブロックを無視できるのではないかと考えました。
理由2: scss 変数を vue ファイルのスタイルブロックに自動挿入しているケースに対応できる
sass-loader
の prependData
という設定2で、 vue ファイルの各 <style lang="scss">
ブロック(scoped
, module
付きを含む)の先頭部分に scss 変数等を自動挿入することができます。
Vue Loader のドキュメントでも紹介されている手法で、使われている方も多いかと思います。
module.exports = {
css: {
loaderOptions: {
scss: {
prependData: `$main-color: #333333;`
}
}
}
}
テスト時のスタイルのコンパイルを止めない場合 jest.config.js
の jest.globals['vue-jest'].resources.scss
で vue.config.js
の prependData
と近い設定ができるようですが、設定の重複管理は避けたいと思いました。
スタイルのコンパイルを止めることで、この問題を解決できました。
理由3: <style lang="scss" module>
があると node-sass
のインストールを求められる
テスト時のスタイルのコンパイルを止めない場合、 CSS Modules と scss を併用している vue ファイルのテストをしようとすると node-sass
のインストールが必須となります:
FAIL tests/unit/example.spec.ts
● Test suite failed to run
[vue-jest] Error: You are trying to use "scss". node-sass is missing.
To install run:
npm install --save-dev node-sass
上記のメッセージに従って node-sass
をインストールすることでもこのエラーを回避できます。
しかし node-sass
は OS 依存のバイナリを含んでいたり sass
(dart-sass) と同じく scss をコンパイルする役割を持つパッケージのため、インストールは避けたいと思いました。
スタイルのコンパイルを止めることで、この問題を解決できました。
理由4: CSS Modules を使っていてもテンプレート上の $style.class_name
で例外が発生しない
vue ファイルに <style module>
ブロックがあると $style
というオブジェクトが注入されテンプレート上で利用することになります。
単純に vue ファイルから <style module>
ブロックを消すことを考えると、 $style
のオブジェクトが注入されなくなってテンプレート上にある $style.class_name
のようなプロパティへのアクセスで例外が発生しそうです。
ですが、紹介した設定ではテスト対象の vue ファイルに <style module>
がある場合はブロック内の記述は無視しつつ $style = {}
を注入してくれるため、上記のような例外は発生しないようになっています。
-
vue-jest
のREADME.md
のコミットログを追ったところ 2018/04/09 のコミット でexperimentalCSSCompile
に関する記述が追加されていました。2年以上経過していますが "experimental" は外れていないようです ↩ -
sass-loader
7.x.x まではdata
で、 9.x.x からはadditionalData
となるようです。additionalData
は prepend だけでなく append もできるそうですが、 8.x.x のprependData
と同じように使うことができました ↩