Laravelでvue-test-utilsを使ってVueのテストをやってみた


はじめに

最近、Laravel + Vueをよく使うのでVueのテストをうまいことできないか調べて試してみた備忘録的なものになります。
Vueのテストをするのにvue-test-utilsというものがあるようなので、それを使ってテストの環境を作ってみた話です。
(テストランナはいくつかあるようですが、mochaを使ってみました)

テストを行いたい環境

  • Laravel 9.0
  • vue 2.5.17
  • webpack 5.52.17
  • npm 8.5.3

やってみた

こちらのページを参考に以下を実行しました。

npm install --save-dev @vue/test-utils mocha mocha-webpack jsdom jsdom-global expect

めっちゃエラーで怒られました

なぜ?と思いmocha-webpackについてよくよく見てみると

mocha-webpack works with
webpack in version 2.x.x & 3.x.x

webpackバージョン2または3までしか対応していないとのこと。
ここでハマってしまい(正直、mochaをやめてJestにしようか)と思いながらも、気を取り直してなんかないか探しました。
そして見つけました。

instant-mocha

FAQをみると、なんかよくわからんけれど良さそう!

This project was created from scratch because mocha-webpack is no longer maintained and doesn't have Webpack 5 support (and neither does its fork, mochapack).

  • instant-mochaのサポートしているmochaバージョンは8
  • @vue/test-utilsもそのままでは何気にバージョンの問題が発生していた
    ということで、以下のように修正。
npm install --save-dev @vue/test-utils@1 mocha@8 instant-mocha jsdom jsdom-global expect

エラーが出まくって怒られることもなく無事だったので、再び先ほどの参考ページに倣って準備を進めます。
(パスとかちょいちょい変えてます)

package.jsonに以下追記

package.json
{
  "scripts": {
    (中略)
    "test": "instant-mocha --webpack-config node_modules/laravel-mix/setup/webpack.config.js --require test/setup.js test/**/*.spec.js"
  }
}

test/setup.js作成

test/setup.js
require('jsdom-global')()

global.expect = require('expect')

テスト対象ファイル(resources/js/Assets/Counter.vue)作成

resources/js/Assets/Counter.vue
<template>
  <div>
    {{ count }}
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        count: 0
      }
    },

    methods: {
      increment() {
        this.count++
      }
    }
  }
</script>

テストファイル(test/Assets/Counter.spec.js)作成

test/Assets/Counter.spec.js
import { shallowMount } from '@vue/test-utils'
import Counter from '../../resources/js/Assets/Counter.vue'

describe('Counter.vue', () => {
  it('increments count when button is clicked', async () => {
    const wrapper = shallowMount(Counter)
    await wrapper.find('button').trigger('click')
    expect(wrapper.find('div').text()).toMatch('1')
  })
})

これで npm run test を実行。

  Counter.vue
    ✓ increments count when button is clicked


  1 passing (39ms)

まとめ

  • webpack5 の環境では mocha-webpack ではなく instant-mocha を使う。