2018-07-04

Vue componentのevent handlerのテストはwrapper#triggerから

単純なメモ。

<template>
  <container>
    <button @click="handler">押して</button>
  </container>
</template>

<script>
export default {
  methods: {
    handler() {
      // これをテストから直接呼ぶとrender済んでない可能性大
    }
  }
}
</script>

こんな Vue component があるとする。

端折りまくったテストコードはこんな感じに書けるんだけど、ここで handler() を直接呼んではいけない。

import Komponent from 'komponent.vue'
..

describe('Komponent', () => {
  var wrapper

  function mountComponent(component) {
    return mount(component, {localVue, router, ..})
  }

  describe('condition', () => {
    beforeEach(() => {
      wrapper = mountComponent(Komponent)
    })

    it('wrong example', () => {
      wrapper.vm.handler()
    })

    it('good example', () => {
      wrapper.find('button').trigger('click')
    })
  })
})

どうも直接 handler() を呼ぶと component が render される前に handler() が呼ばれてしまうらしく、少なくとも DOM 上のデータは取得できない。

単純なロジックだけのメソッドならこれでもテスト可能だが、event handler としてのテストをする場合はちゃんと event から呼んであげるのがよいらしい。

で、event を起こすには、まず event を起こしたい要素を特定してあげる。wrapper.find() で特定してあげると DOM wrapper のようなオブジェクトが取得できるので、そいつで event を trigger する1。すると実際に Vue component が render されているような状態で handler() を動作させることができる。

※ ちなみに render という function も export されているのだが、これは @vue/test-utils ではなく @vue/server-test-utils に含まれるものであり、component のテストではなく、render された HTML に対するテストしかできない。mount や shallow の代わりには使えない。

  1. @vue/test-utils を使ったテストはとにかく wrapper を相手にする 

About

例によって個人のなんちゃらです