Laravel-Mixでvue-test-utilsを使ってvueのコンポーネントテストを実行するまで


## 概要
Laravel-mixで使うVueのテスト書くのにLaravel Dusk使うのもええんですけども、[Vue Test Utils](https://vue-test-utils.vuejs.org/ja/)なるものがあるのでそれを導入したお話。
プッシュしたタイミングでCircleCIさんがテストを実行してくれるようになるまで丸一日かかったのでやった手順を書き残す事にしやした。

## 環境
- php 7.2
- laravel 5.6
- node.js 8.10
- npm 5.6
- circleci 2
- docker compose 3

## 前提
- Laravel-mixを使ってLaravelのasset/js配下にあるコンポーネントをコンパイルして使う
- `/tests/javascript`配下にテストファイルを置く
- CircleCIのテスト環境はローカルのdocker composeと同じ構成にする

## 手順
必要なパッケージをインストール

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

package.jsonに新しいコマンドを登録

```json:package.json
"scripts": {
    ・・・・,
    "test": "mocha-webpack --webpack-config=node_modules/laravel-mix/setup/webpack.config.js --require tests/Javascript/setup.js tests/Javascript/**/*.spec.js"
},
```

tests/Javascriptにsetup.jsを追加

```javascript:tests/Javascript/setup.js
require('jsdom-global')()

global.expect = require('expect')
```

tests/Javascriptにテストファイルを追加

```javascript:tests/Javascript/Counter.spec.js
import { shallowMount } from '@vue/test-utils'
import Counter from '../../resources/assets/js/Counter.vue'

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

テスト対象のコンポーネントを追加

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

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

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

`npm run test`でテストを実行する

## CircleCIでプッシュ時にテスト実行してくれるまで
`CircleCIのテスト環境はローカルのdocker composeと同じ構成にする`ってのがあったので、なかなか手間取ったのかもしれません。

config.ymlに以下を追加する

```yml:config.yml
- run:
    name: Setup Vue
    command: |
        cd docker
        docker-compose -f docker-compose-circleci.yml run {project-name} /bin/bash -c 'npm install'
- run:
    name: Run Test
    command: |
        cd docker
        docker-compose -f docker-compose-circleci.yml run {project-name} /bin/bash -c 'npm run test'
```

### permission denied
普通に`npm install`するだけではinstall途中の特定のパッケージだけ`permision denied`が出てテスト環境がCircleCI上で構築できない。
`npm install --unsafe-perm`する事で回避！

### lib-pngがねぇよって怒られる
インストールする

```bash:Dockerfile
RUN yum install -y libpng-devel
```

## くじけそうな時に手を差し伸べてくれたものたち(参考になった記事)
- [Vue Test Utiils 公式ドキュメント](https://vue-test-utils.vuejs.org/ja/guides/testing-single-file-components-with-mocha-webpack.html)
- [Unit Testing Vue components with vue-test-utils in Laravel](https://medium.com/@sergiturbadenas/unit-testing-vue-componets-with-vue-test-utils-in-laravel-918188178207)
- [`npm install`時の`Error: EACCES: permission denied`](https://stackoverflow.com/questions/47460293/sudo-npm-install-gives-me-a-access-denied)
- [lib-pngがインストールされていないエラーがでた](https://qiita.com/happy_ryo/items/64fc937a1bdf3ef531a9)

## ハイライト
- permission deniedになる原因を探るためにconfig.yml内で`docker exec`しようとした。
- 毎回プッシュしてCicleCIの環境ができてるか調べた。
- 現config.ymlは`workflows`使ってて、CicleCIをlocalで動かそうとしたらworkflowsが対応してないって言われて涙目。