Vue Test Utils カスタムコンポーネントでv-modelを適用したときのテスト


Vue Test Utils カスタムコンポーネントでv-modelを適用したときのテスト

やりたいこと

以下のようなカスタムコンポーネントにv-modelを適用したときに入力値をdataに反映させてテストをする。

sample.vue
<template>
  <div>
    <formInput v-model="test" type="text"></formInput>
  </div>
</template>

<script>
import formInput from '~/components/formInput.vue'

export default {
  components: { formInput },
  data() {
    return {
      test: ''
    }
  }
}
</script>

NG例

input要素だとドキュメントにある通り、以下のようにdataに値を反映することができる。
しかし、上記のようなカスタムコンポーネントでこのコードを実行すると"wrapper.setValue() cannot be called on this element"のようなエラーが表示される。

sample.spec.js
import { shallowMount } from '@vue/test-utils'
import Foo from '~/pages/sample.vue'

const wrapper = shallowMount(Foo)

describe('input要素だとこれでパスする', () => {
  test('テストする', () => {
    const textInput = wrapper.find('[type="text"]')
    textInput.element.value = 'some value'

    expect(wrapper.vm.test).toBe('some value')
  })
})

解決策

inputイベントを発火させることで、入力値をdataに反映させてテストすることが可能。

sample.spec.js
import { shallowMount } from '@vue/test-utils'
import Foo from '~/pages/sample.vue'

const wrapper = shallowMount(Foo)

describe('カスタムコンポーネントのv-modelでもこれでパスする', () => {
  test('テストする', () => {
    const textInput = wrapper.find('[type="text"]')
    textInput.vm.$emit('input', 'some value')

    expect(wrapper.vm.test).toBe('some value')
  })
})

参考

こちらにある通り、v-modelはv-onとv-bindを1行で表現したものなので、イベントを発火することでdataを更新することができます。

<input v-model="searchText">
<input :value="searchText" @input="searchText = $event.target.value">

誰かの役に立つことを願って。。