Jest＋vue-test-utilsでVeeValidateのエラー文言をテストしてみた

今までテストを書いたことが無く、物は試し、まずはログイン画面の簡単（そう）なところからとりあえず書いてみよう！　と試みた結果色々ハマったので備忘として。

## バージョン
- vue: 2.5.13
- vee-validate: 2.0.3
- jest: 22.1.4
- vue-test-utils: 1.0.0-beta.11


## テスト対象

```Javascript:IndexPage.vue
<template>
  <form @submit.prevent="login">
    <dl>
      <dt>ID</dt>
      <dd><input
        name="id"
        type="text"
        placeholder="必須"
        v-validate="{required:'required', regex:/^[a-zA-Z0-9]+$/}"
        data-vv-as="ID"
        v-model="id">
        <div class="id-err" v-show="errors.has('id')">{{errors.first('id')}}</div>
      </dd>
    </dl>
    <button type="submit">Login</button>
  </form>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  name: 'IndexPage',
  data () {
    return {
      id: null
    }
  },
  methods: {
    ...mapActions('auth', {
      tryLogin: 'tryLogin'
    }),
    login () {
      this.$validator.validateAll().then((result) => {
        if (result) {
          this.tryLogin({
            id: this.id
            router: this.$router
          }).then((res) => {
            // なんか処理
          }, (err) => {
            // なんか処理
          })
        } else {
          // なんか処理
        }
      })
    }
  }
}
</script>
```

「.id-err」に想定通りのエラーが表示されているかどうかをテストしたい。

```Javascript:main.js
import Vue from 'vue'
import App from './App'
import VeeValidate, { Validator } from 'vee-validate'
import ja from 'vee-validate/dist/locale/ja'
import store from './vuex'
import router from './router'
import customValid from './validations'

Validator.localize('ja', ja)
Vue.use(VeeValidate, customValid)

Vue.config.productionTip = false

new Vue({
  el: '#app',
  store,
  router,
  components: { App },
  template: '<App/>'
})
```

```Javascript:validations/index.js
export default {
  locale: 'ja',
  dictionary: {
    ja: {
      custom: {
        id: {
          required: 'IDは必須です',
          regex: 'IDが間違っています'
        }
      }
    }
  }
}
```

バリデーションの日本語化とカスタムはこんな感じで。

## テスト

```Javascript:Login.test.js
import { shallow, createLocalVue } from 'vue-test-utils'
import IndexPage from '@/IndexPage'
import Vuex from 'vuex'
import VueRouter from 'vue-router'
import VeeValidate, { Validator } from 'vee-validate'
import ja from 'vee-validate/dist/locale/ja'
import customValid from '@/validations'

const localVue = createLocalVue()

localVue.use(Vuex)
localVue.use(VueRouter)
Validator.localize('ja', ja)
localVue.use(VeeValidate, customValid)

describe('IndexPage.vue', () => {
  const wrapper = shallow(IndexPage, {
    localVue,
    stubs: ['router-link', 'router-view']
  })

  describe('IDテスト', () => {
    let idCheck = async (errorText) => {
      await wrapper.vm.$validator.validateAll()

      expect(wrapper.find('.id-err').text()).toBe(errorText)
    }

    it('正常系：数字のみ', () => {
      wrapper.setProps({
        id: '12345678'
      })
      try {
        idCheck('')
      } catch(e) {
        expect(e).toMatch('error')
      }
    })

    it('正常系：英字のみ', () => {
      wrapper.setProps({
        id: 'abcdefgh'
      })
      try {
        idCheck('')
      } catch(e) {
        expect(e).toMatch('error')
      }
    })

    it('エラー：必須', () => {
      wrapper.setProps({
        id: ''
      })
      try {
        idCheck('IDは必須です')
      } catch(e) {
        expect(e).toMatch('error')
      }
    })
  })
})
```

idCheckに想定しているエラー文言を渡して、実際表示されたエラーと一致するかを確認しています。

## 余談
テストを書く前は「.id-err」の表示をv-showではなくv-ifで切り替えていました。
結果、テスト時に「.id-err」の存在判定を入れなければならなくなり、煩雑になったためv-showに変更しました。
（そもそもerrorsの中身を直接判定すればいい話ではあります）

（書いてみたは良いけど、テストってこれでいいのだろうか……）