これ、みんなどうやっているのか聞きたいので投稿してみる。
もっといい方法が存在するのであれば教えてください。
nuxt.js は SSR によるアプリケーション開発における必要なものが大体揃っており、良いなーということで使い始めてはいるのですが、やはり、まだまだRC版ということで課題もあります。今回は Unit テストで詰まりました。
nuxt.js では、nuxt-build
により store をまとめたり、nuxt.js がプリセットで用意している component を .nuxt/
ディレクトリに用用意する。さらに面倒なことに、.nuxt
で展開されているものは、webpackで使う前提となっています。 内部的には、 require.context
を利用しているためです。
nuxt.js 公式では、 ava による e2e テストの方法について公式で述べているものの、Unitテストについてはイマイチ情報が少ないです。 Unit testing Issue #461 nuxt/nuxt.js あたりも参照のこと。
// 上記の e2e のテストについても毎回 build が走ってしまうので、個人的には気に食わない。
ということで、自分なりにテスト方法について模索してみました。
前提
ここでは、vue-init webpack
によりデフォルトでオススメされる、jest をテストツールとして使います。
導入
yarn で必要なものを入れていく
yarn add -D babel-core babel-jest babel-plugin-dynamic-import-node \
babel-plugin-transform-es2015-modules-commonjs \
babel-plugin-transform-runtime babel-preset-env \
babel-preset-stage-2 babel-register jest jest-serializer-vue vue-jest
必要なファイルを変更したり、作っていく作業を行う
{
"presets": [
["env", {
"modules": false
}],
"stage-2"
],
"plugins": ["transform-runtime"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}
module.exports = {
env: {
jest: true // jest を true にする
}
}
const path = require('path')
module.exports = {
rootDir: path.resolve(__dirname, '../../'),
moduleFileExtensions: [
'js',
'json',
'vue'
],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1'
},
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
},
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
setupFiles: ['<rootDir>/test/unit/setup'],
mapCoverage: true,
coverageDirectory: '<rootDir>/test/unit/coverage',
collectCoverageFrom: [
'components/**/*.{js,vue}'
]
}
import Vue from 'vue'
Vue.config.productionTip = false
テスト記述
import Vue from 'vue'
import Vuex from 'vuex'
import VueRouter from 'vue-router'
import VueI18n from 'vue-i18n'
import AppHeader from '@/components/AppHeader.vue'
const store = require('@/store/')
Vue.use(VueRouter)
Vue.use(Vuex)
Vue.use(VueI18n)
describe('AppHeader.vue', () => {
it('pass', () => {
AppHeader.components = {}
// nuxt-link component を使っている場合は、モックを載せる
// この中身は、.nuxt/components/nuxt-link.js にも出来ているので、
// ビルドが行われている前提であれば、そちらを呼んでも良い。
AppHeader.components.NuxtLink = {
name: 'nuxt-link',
functional: true,
render (h, {data, children}) {
return h('router-link', data, children)
}
}
const Constructor = Vue.extend(AppHeader)
// VueI18n を使っているので、載せる。
// 但しUnitレベルでは別にデータは不要なので、silentTranslationWarn: true にして警告を消す
const vm = new Constructor({router: new VueRouter(), i18n: new VueI18n({silentTranslationWarn: true})})
// store/index.js (Module Mode) から store を作る作業
vm.$store = new Vuex.Store(Object.assign(store, {
state: store.state()
}))
vm.$mount()
// テストを記述する
})
})
テスト実行
yarn run
から実行できるようにする
{
"scripts": {
"unit": "jest --config test/unit/jest.conf.js "
}
}
yarn run unit
悩ましいポイント
- 今のところ、ビルド済みの
.vue/
に依存しない形で書いているが、依存させたほうが良いかな? - Vuex モジュールが増えてくると面倒なことになりそう。
- *.vue ファイルのカバレッジが、何故かちゃんと取得できない場合もある。