はじめに
こんばんは。
皆さん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番のテストと似たような感じになりました...
終わりに
テスト各事自体はやりやすいんですが、テスト環境を作ることが大変です...
現場からは以上です。