В приложениях на Vue, использующих Vue Router, навигация управляется
объектом router. Основные способы перехода между маршрутами
— это использование компонентов <router-link> и
программная навигация через методы router.push,
router.replace и router.go. Для тестирования
корректности переходов важно симулировать эти действия и проверять
состояние маршрутизатора после них.
Для тестирования навигации необходим реальный или моковый экземпляр
маршрутизатора. Чаще всего используют createRouter с
режимом memory (для Vue Router 4) для изоляции тестов:
import { createRouter, createMemoryHistory } from 'vue-router'
import { mount } from '@vue/test-utils'
import App from '@/App.vue'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
const routes = [
{ path: '/', name: 'Home', component: Home },
{ path: '/about', name: 'About', component: About },
]
const router = createRouter({
history: createMemoryHistory(),
routes,
})
const wrapper = mount(App, {
global: {
plugins: [router]
}
})
Использование createMemoryHistory позволяет тестам
работать в изолированной памяти, без реального изменения URL
браузера.
<router-link>Компоненты <router-link> создают ссылки для
навигации. Проверка включает:
href.Пример теста:
import { nextTick } from 'vue'
const wrapper = mount(App, {
global: { plugins: [router] }
})
// Проверка атрибута href
const link = wrapper.find('a[href="/about"]')
expect(link.exists()).toBe(true)
// Симуляция клика
await link.trigger('click')
await router.isReady() // дождаться завершения навигации
expect(router.currentRoute.value.name).toBe('About')
router.isReady() гарантирует, что переход завершён,
прежде чем проверять currentRoute.
Для компонентов, использующих router.push или
router.replace:
const wrapper = mount(MyComponent, {
global: { plugins: [router] }
})
// Вызов метода навигации компонента
await wrapper.vm.goToAbout()
await router.isReady()
expect(router.currentRoute.value.name).toBe('About')
Здесь важно проверять не только имя маршрута, но и путь или параметры, если они используются.
Многие маршруты содержат динамические параметры:
{ path: '/user/:id', name: 'User', component: User }
Для тестирования необходимо передать параметры при навигации:
await router.push({ name: 'User', params: { id: '42' } })
await router.isReady()
expect(router.currentRoute.value.params.id).toBe('42')
Для <router-link> с параметрами:
const link = wrapper.findComponent({ ref: 'userLink' })
await link.trigger('click')
await router.isReady()
expect(router.currentRoute.value.params.id).toBe('42')
Query-параметры передаются через объект query:
await router.push({ path: '/about', query: { ref: 'newsletter' } })
await router.isReady()
expect(router.currentRoute.value.query.ref).toBe('newsletter')
Это позволяет проверять фильтры, состояние поиска и другие функциональности, завязанные на query.
Для юнит-тестирования компонентов без реального маршрутизатора можно создать мок:
const mockRouter = {
push: jest.fn(),
replace: jest.fn(),
}
const wrapper = mount(MyComponent, {
global: { mocks: { $router: mockRouter } }
})
wrapper.vm.goToAbout()
expect(mockRouter.push).toHaveBeenCalledWith({ name: 'About' })
Использование моков ускоряет тесты и исключает необходимость полной инициализации маршрутизатора.
Все переходы во Vue Router асинхронны. Для корректного тестирования
важно использовать await router.isReady() после
push/replace и await nextTick()
при необходимости обновления DOM. Без этих шагов тесты могут завершаться
до завершения перехода, что приведёт к ложноположительным или
ложноотрицательным результатам.
Компоненты <router-link> добавляют класс
router-link-active при совпадении маршрута. Тестирование
активного состояния:
const link = wrapper.find('a[href="/about"]')
expect(link.classes()).toContain('router-link-active')
Это полезно для проверки навигационных меню и визуальной подсветки текущего маршрута.
Маршруты могут иметь редиректы или beforeEnter guards.
Для тестирования важно учитывать, что переход может быть отменён или
перенаправлен:
const routes = [
{ path: '/secret', redirect: '/login' },
]
await router.push('/secret')
await router.isReady()
expect(router.currentRoute.value.path).toBe('/login')
Также можно проверять вызовы guard-функций через моки:
const guard = jest.fn((to, from, next) => next())
{ path: '/protected', beforeEnter: guard }
await router.push('/protected')
expect(guard).toHaveBeenCalled()
Методы router.go(n) позволяют эмулировать действия
истории браузера. Для тестов используют router.push и
router.back:
await router.push('/about')
await router.push('/contact')
await router.back()
await router.isReady()
expect(router.currentRoute.value.path).toBe('/about')
Это полезно для проверки кнопок «назад» и поведения истории.
createMemoryHistory для изоляции.router.isReady() или nextTick.$router и $route.