既存のVue.jsのプロジェクトにJestでのテスト環境を構築する

# TL;DR
- VueのプロジェクトにJestによる環境を構築するためにやったことをまとめた
- Jestについては説明しない

# ディレクトリ構成
```bash
├── jest.config.js
├── package.json
├── src
│   ├── js
│   │   ├── components
│   │   └── main.js
│   └── sass
├── tests
│   └── unit
└── webpack.config.js
```

# パッケージのインストール

とりあえず基本的なものをインストールします。

```bash
$ npm i -D @vue/test-utils jest vue-jest babel-jest
```

`package.json`にテストを走らせるためのタスクを追加します。

```package.json
"scripts": {
  "test:unit": "jest"
}
```

# Jestの設定をする

```jest.config.js
module.exports = {
  moduleFileExtensions: ["js", "jsx", "json", "vue"],
  transform: {
    "^.+\\.vue$": "vue-jest",
    "^.+\\.jsx?$": "babel-jest"
  },
  transformIgnorePatterns: ["node_modules/"],
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/js/$1"
  },
  testMatch: [
    "**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
  ]
};

```


# 試してみる
```bash
$ npm run test:unit

> vue.build@1.0.0 test:unit /Users/xxx/project/vue-jest-test
> jest

 PASS  tests/unit/example.spec.js
  HelloWorld.vue
    ✓ renders props.msg when passed (15ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.206s, estimated 5s
Ran all test suites.
```

# スナップショットテストを導入する
```bash
$ npm i -D jest-serializer-vue
```

## jest.config.js

`jest.config.js`に以下を追加する。

```bash
module.exports = {
  ...
  snapshotSerializers: ["jest-serializer-vue"]
  ...
};
````

追加後の`jest.config.js`

```bash
module.exports = {
  moduleFileExtensions: ["js", "jsx", "json", "vue"],
  transform: {
    "^.+\\.vue$": "vue-jest",
    "^.+\\.jsx?$": "babel-jest"
  },
  transformIgnorePatterns: ["node_modules/"],
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/js/$1"
  },
  snapshotSerializers: ["jest-serializer-vue"],
  testMatch: [
    "**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
  ]
};

```

## 結果
```bash
$ npm run test:unit

> vue.build@1.0.0 test:unit /Users/xxx/project/vue-jest-test
> jest

 PASS  tests/unit/SampleComp.spec.js
  SampleComp.vue
    ✓ renders props.text when passed (16ms)

 › 1 snapshot written.
Snapshot Summary
 › 1 snapshot written from 1 test suite.

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 written, 1 total
Time:        1.429s
Ran all test suites.
```

実行すると、`tests/unit/__snapshots__`以下にsnapshotのファイルが格納される。

## 参考
[Snapshot Testing](https://jestjs.io/docs/ja/22.x/snapshot-testing)

# カバレッジを表示させたい場合
`jest.config.js`に以下を追加する。

```bash
module.exports = {
  ...
  "collectCoverage": true,
  "collectCoverageFrom": ["src/js/**/*.{js,vue}"]
  ...
};
````

追加後の`jest.config.js`

```bash
module.exports = {
  moduleFileExtensions: ["js", "jsx", "json", "vue"],
  transform: {
    "^.+\\.vue$": "vue-jest",
    "^.+\\.jsx?$": "babel-jest"
  },
  transformIgnorePatterns: ["node_modules/"],
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/js/$1"
  },
  snapshotSerializers: ["jest-serializer-vue"],
  testMatch: [
    "**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
  ],
  testURL: "http://localhost/",
  "collectCoverage": true,
  "collectCoverageFrom": ["src/js/**/*.{js,vue}"]
};

```

## エラーが出る場合
`Cannot read property 'bindings' of null`とのエラーが出る場合、


```bash
$ npm i -D @babel/preset-env
```

`.babelrc`を下記の通り修正する。

`{ "presets": ["env"] }`
↓
`{ "presets": ["@babel/preset-env"] }`

[Upgrade to Babel 7: Cannot read property 'bindings' of null](https://stackoverflow.com/questions/52092739/upgrade-to-babel-7-cannot-read-property-bindings-of-null/52092788)



# 参考
[Vue Test Utils + Jest でVue.jsの単体テストを行う](https://qiita.com/daiki7nohe/items/8d29e2d9059296b75fa6)
[Configuring Jest](https://jestjs.io/docs/ja/configuration)