はじめに
こんばんは。
皆さんjsのテストって書いてますでしょうか?
僕はほぼほぼか書かないです!!
2〜3個前の案件で jestで書いて以来、そこから全く触っていません。
これはそろそろ...
と思い、重い腰を上げてやってみました。
今回は、今の案件でも使用している vueのテストをjestでやってみました。
多分新規プロジェクトとかだと、インストールツールでインタラクティブインストール時にテストツールとか選択できてたと思うのですが、テストだけ導入するにはどする?ってところでやってみました。
参考はこちらのサイト
本題
1. セットアップ
1. テストツールのinstall
現在の自分のプロジェクトでは、以下のライブラリをインストールすることになりました。
$ npm install --save-dev jest vue-jest babel-jest @vue/test-utils babel-core@bridge babel-preset-env
2. package.jsonの修正
"scripts": { "test": "jest" }, "jest": { "moduleFileExtensions": [ "js", "json", "vue" ], "transform": { ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest", "^.+\\.js$": "<rootDir>/node_modules/babel-jest" } }
3. .babelrcの修正
{ "presets": [ [ "env", { "modules": false } ] ], "env": { "test": { "presets": [ [ "env", { "targets": { "node": "current" } } ] ] } } }
テスト
テストで使うvueは以下
特定のステータスをラジオボタンで変更するコンポーネントなイメージです。
<template> <label :class="{ 'status-checked': checked }"> <input v-model="innerChoiceStatusId" type="radio" name="status[]" :value="statusId" > {{ label }} </label> </template> <script> export default { name: "StatusRadioButton", props: { statusId: { type: Number, default: null }, label: { type: String, default: '' }, choiceStatusId: { type: Number, default: null } }, computed: { innerChoiceStatusId: { get() { return this.choiceStatusId }, set(choiceStatusId) { if (this.choiceStatusId !== choiceStatusId) { this.$emit('update:choiceStatusId', choiceStatusId) } } }, checked() { return this.statusId === this.innerChoiceStatusId } } } </script> <style scoped> </style>
1. 参考サイトにあったやつのテスト
import { mount } from '@vue/test-utils' import StatusRadioButton from '@js/StatusRadioButton' describe('Component', () => { test('is a Vue instance', () => { const wrapper = mount(StatusRadioButton) expect(wrapper.vm).toBeTruthy() }) })
実行
npm test > jest PASS tests/example.spec.js Component ✓ is a Vue instance (15 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 3.396 s Ran all test suites.
参考サイトにあった expect(wrapper.isVueInstance()).toBeTruthy()
を行うと、エラーが出まして、次期バージョンでは削除されるとのことでした。
なので、こちらの方法で試すことにしました。
2. emitされてるか
describe('Component', () => { test('チェックされたら値が更新される', async () => { const wrapper = mount(StatusRadioButton, { propsData: { statusId: 100, label: 'タイプ100', choiceStatusId: null, } }) const radioInput = wrapper.find('input[type="radio"]') await radioInput.setChecked() expect(wrapper.emitted('update:choiceStatusId')).toBeTruthy() expect(wrapper.emitted('update:choiceStatusId')[0][0]).toBe(100) }) })
実行
$ npm test > jest PASS tests/Spec/example.spec.js Component ✓ is a Vue instance (16 ms) ✓ チェックされたら値が更新される (10 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 6.856 s Ran all test suites.
propsDataをセットして、 emitされたかどうかのチェックは emitted
でみるみたいです。
3. クラスが変更されているか
test('チェックされたらlabelにstatus-checkedクラスが付与される', async () => { const wrapper = mount(StatusRadioButton, { propsData: { statusId: 100, label: 'タイプ100', choiceStatusId: null, } }) const radioInput = wrapper.find('input[type="radio"]') await radioInput.setChecked() await wrapper.setProps({ choiceStatusId: wrapper.emitted('update:choiceStatusId')[0][0]}) expect(wrapper.vm.checked).toEqual(true) })
実行
$ npm test > jest PASS tests/Spec/example.spec.js Component ✓ is a Vue instance (15 ms) ✓ チェックされたら値が更新される (10 ms) ✓ チェックされたらlabelにstatus-checkedクラスが付与される (5 ms) Test Suites: 1 passed, 1 total Tests: 3 passed, 3 total Snapshots: 0 total Time: 3.39 s Ran all test suites.
syncでpropsを指定している際、update emit後本来ならば値が変更されているんですが、テストではどう書くかわからなかったので、2番のテストと似たような感じになりました...
終わりに
テスト各事自体はやりやすいんですが、テスト環境を作ることが大変です...
現場からは以上です。