前回(JestでNuxt+Vuetifyのテストを書いてみる)に続き、今回は初期表示の正常系テストを書いてみました。
最初に対応する時に役立つのでメモしておきます。
injectしている関数のMockを作らなくても動くようにする
前回(pluginでinjectしている関数のテスト)では、使用するテストファイル毎にMockを作っていましたが、手間なのと期待値の確認(表示されたか)もしやすくなので、どこでも関数が呼ばれるようにする事にしました。
test/setup.js に追加
import Vue from 'vue' import Vuetify from 'vuetify' import { TestPluginUtils } from '~/plugins/utils.js' Vue.use(Vuetify) Vue.use(TestPluginUtils)
plugins/utils.js のTestPluginを修正
export const TestPluginUtils = { install (Vue) { Vue.prototype.$dateFormat = dateFormat Vue.prototype.$timeFormat = timeFormat Vue.prototype.$pageFirstNumber = pageFirstNumber Vue.prototype.$pageLastNumber = pageLastNumber } }
呼び出し元
下記のように定義していたmocksが不要になりました。
test/page/users/undo_delete.spec.js
return shallowMount(Page, { localVue, vuetify, mocks: { - $dateFormat: jest.fn(), - $timeFormat: jest.fn()
i18nの値がネスト(入れ子)だと取れない
前回作成した($tが無いと言われる)ではネスト(入れ子)にした連想配列だと、undefinedになってしまうバグがありました。
こんな感じで定義していて、
locales/ja.js
network: { failure: '通信に失敗しました。しばらく時間をあけてから、やり直してください。', error: '通信エラーが発生しました。しばらく時間をあけてから、やり直してください。' },
テストで使うとundefinedに。
Expected: "通信に失敗しました。しばらく時間をあけてから、やり直してください。" Received: undefined
test/setup.js を修正
import Vue from 'vue' import Vuetify from 'vuetify' import { config, RouterLinkStub } from '@vue/test-utils' import { TestPluginUtils } from '~/plugins/utils.js' import locales from '~/locales/ja.js' Vue.use(Vuetify) Vue.use(TestPluginUtils) // Mock i18n config.mocks = { $t: (key) => { let locale = locales const parts = key.split('.') for (const part of parts) { locale = locale[part] } // eslint-disable-next-line no-throw-literal if (locale == null) { throw 'Not found: i18n(' + key + ')' } return locale } } // Stub NuxtLink config.stubs.NuxtLink = RouterLinkStub
NuxtLinkのパスが存在するかのテスト
RouterLinkStubのprops().toで取れますが、複数ある場合が多いので、先に一覧化して、含まれるかをテストするようにしました。
また、よく使うのでclass作って、importしています。
test/page/infomations/index.spec.js
import { Helper } from '~/test/helper.js' const helper = new Helper()
const links = helper.getLinks(wrapper)
expect(links.includes('/infomations/' + list.id)).toBe(list.body_present) // [本文あり]お知らせ詳細
test/helper.js
import { RouterLinkStub } from '@vue/test-utils' export class Helper { // NuxtLinkのURL一覧を配列で返却 getLinks = (wrapper) => { const routerlinks = wrapper.findAllComponents(RouterLinkStub) const links = [] for (let i = 0; i < routerlinks.length; i++) { const link = routerlinks.at(i).props().to if (link.name === 'infomations-id___ja') { links.push('/infomations/' + link.params.id) // お知らせ一覧 } else { links.push(link) } } return links } }
> <NuxtLink to="/infomations">
toがlinksに含まれるかでテストできます。
> <NuxtLink :to="{ name: 'infomations-id___ja', params: { id: list.id }}">
ただ、こんな感じにパラメータを渡している場合、props().toで取れる値には下記のように設定されますが、includesだとtrueにならないので、linksに入れる時に実際のパスを保存するように、テストも実際のパスで行っています。
> { name: 'infomations-id___ja', params: { id: 1 } }
async/awaitの挙動について
下記のように、awaitの後に処理があった場合、
pages/users/delete.vue
async created () { try { await this.$auth.fetchUser() } catch (error) { if (error.response == null) { this.$toasted.error(this.$t('network.failure')) } else if (error.response.status === 401) { return this.appSignOut() } else { this.$toasted.error(this.$t('network.error')) } return this.$router.push({ path: '/' }) } if (!this.$auth.loggedIn) { return this.appRedirectAuth() } if (this.$auth.user.destroy_schedule_at !== null) { return this.appRedirectDestroyReserved() } this.processing = false this.loading = false },
下記のようにテストを書くと、上のawaitの所までの状態となり、
その後(今回はloadingがfalse)を期待したテストが失敗します。
console.log(wrapper.html())も途中の状態が表示されます。
test/page/users/delete.spec.js
await expect(authFetchUserMock).toBeCalledTimes(1) expect(wrapper.findComponent(Loading).exists()).toBe(false)
sleepして対応
毎回定義するのは手間なので、上で作成したhelperに追加しました。
import { Helper } from '~/test/helper.js' const helper = new Helper()
await helper.sleep(1) expect(authFetchUserMock).toBeCalledTimes(1) expect(wrapper.findComponent(Loading).exists()).toBe(false)
await/sleepの前は、awaitの前の状態のテスト、
後は最終的な状態のテストを書けるようになります。
test/helper.js
export class Helper { // 一定時間停止 sleep = ms => new Promise(resolve => setTimeout(resolve, ms)) }
“JestでNuxt+Vuetifyのテストを書く時のTips #1” に対して1件のコメントがあります。