はじめに
NuxtのnavigateTo
を以下のような感じでテストしたかったのですが、
utils/sample.ts
export default async () => {
await navigateTo({
path: "/",
query: { redirect: undefined, tenantId: undefined },
})
}
utils/sample.spec.ts
describe('sample', () => {
it('navigate to top', async () => {
const mock = vi.fn() // いい感じにnavigateToをモック
const expectArgs = {
path: "/",
query: { redirect: undefined, tenantId: undefined },
}
await sample()
expect(mock).toHaveBeenCalledWith(expectArgs)
})
})
そこそこ詰まったので解決方法を記載します。
環境
Nuxt: 3.12.1
vitest: 1.6.0
TL;DR
utils/sample.spec.ts
import * as Nuxt from "#app/composables/router"
import sample from './sample'
describe('sample', () => {
it('navigate to top', async () => {
const mock = vi.spyOn(Nuxt, 'navigateTo')
const expectArgs = {
path: "/",
query: { redirect: undefined, tenantId: undefined },
}
await sample()
expect(mock).toHaveBeenCalledWith(expectArgs)
})
})
内容
まず以下記事を参考に、
以下のようなコードで検証しました。
utils/sample.spec.ts
import * as Nuxt from "nuxt/app"
import sample from './sample'
describe('sample', () => {
it('navigate to top', async () => {
const mock = vi.spyOn(Nuxt, 'navigateTo')
// vi.stubGlobal('navigateTo', mock)
const expectArgs = {
path: "/",
query: { redirect: undefined, tenantId: undefined },
}
await sample()
expect(mock).toHaveBeenCalledWith(expectArgs)
})
})
しかし、上記コードでテストを実行すると以下エラーとなりました。
(vi.stubGlobal
を実行しても変わらず)
エラー
FAIL utils/sample.spec.ts > sample > navigate to top
AssertionError: expected "navigateTo" to be called with arguments: [ { path: '/', query: { …(2) } } ]
Received:
Number of calls: 0
❯ utils/sample.spec.ts:15:18
13|
14| await sample()
15| expect(mock).toHaveBeenCalledWith(expectArgs)
| ^
16| })
17| })
また、vi.stubGlobal
を実行した状態でsample.ts
側でglobal.navigateTo
を実行するとテスト成功しました。
utils/sample.ts
export default async () => {
await global.navigateTo({
path: '/',
query: { redirect: undefined, tenantId: undefined },
})
}
テスト結果
✓ utils/sample.spec.ts (1)
✓ sample (1)
✓ navigate to top
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 15:39:45
Duration 221ms
そのため、navigateTo
は少なくともglobalと違うところで定義されているものを読み込んでいると思われます。
というわけで、.nuxt/imports.d.ts
を見てnavigateTo
がどこからimportされているか確認したところ、以下でした。
.nuxt/imports.d.ts
export { abortNavigation, addRouteMiddleware, defineNuxtRouteMiddleware, setPageLayout, navigateTo, useRoute, useRouter, onBeforeRouteLeave, onBeforeRouteUpdate } from '#app/composables/router';
そのため、モックのためにimportしているモジュールの記載を変更しました。
utils/sample.spec.ts
- import * as Nuxt from "nuxt/app"
+ import * as Nuxt from "#app/composables/router"
import sample from './sample'
describe('sample', () => {
it('navigate to top', async () => {
const mock = vi.spyOn(Nuxt, 'navigateTo')
const expectArgs = {
path: "/",
query: { redirect: undefined, tenantId: undefined },
}
await sample()
expect(mock).toHaveBeenCalledWith(expectArgs)
})
})
これでテスト成功しました。
テスト結果
✓ utils/sample.spec.ts (1)
✓ sample (1)
✓ navigate to top
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 16:13:30
Duration 163ms