В Vue.js приложения часто используют маршрутизацию через
vue-router, и корректная работа роутов является критической
частью функциональности. Тестирование компонентов с маршрутизатором
требует точного подхода к проверке переходов, параметров маршрутов и их
влияния на состояние компонентов. Vue Test Utils предоставляет гибкие
инструменты для изоляции компонентов и симуляции работы роутера.
Для тестирования компонентов, использующих маршруты, необходимо
создать экземпляр маршрутизатора и интегрировать его с тестируемым
компонентом. Обычно используется createRouter из
vue-router и mount из Vue Test Utils.
import { mount } from '@vue/test-utils'
import { createRouter, createWebHistory } from 'vue-router'
import MyComponent from '@/components/MyComponent.vue'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
const routes = [
{ path: '/', name: 'home', component: Home },
{ path: '/about/:id', name: 'about', component: About }
]
const router = createRouter({
history: createWebHistory(),
routes
})
const wrapper = mount(MyComponent, {
global: {
plugins: [router]
}
})
Ключевые моменты:
global.plugins позволяет подключить
роутер к изолированному экземпляру компонента.router.isReady() перед проверкой рендеринга.await router.isReady()
Компоненты часто используют текущий маршрут через
this.$route или useRoute. Для проверки
текущего пути и параметров:
expect(wrapper.vm.$route.name).toBe('home')
expect(wrapper.vm.$route.path).toBe('/')
Если используется Composition API:
import { useRoute } from 'vue-router'
const route = useRoute()
expect(route.params.id).toBeUndefined()
Особенности:
:id)
необходимо сначала выполнить переход или передать параметры через
router.push().await router.push({ name: 'about', params: { id: '123' } })
await router.isReady()
expect(wrapper.vm.$route.params.id).toBe('123')
Навигация в тестах имитируется вызовами методов роутера:
router.push() – переход к новому маршрутуrouter.replace() – замена текущего маршрута без
добавления в историюrouter.back() / router.forward() –
управление историей навигацииawait router.push('/about/456')
await router.isReady()
expect(wrapper.vm.$route.params.id).toBe('456')
Использование await router.isReady() гарантирует, что
компонент полностью обновил состояние перед проверкой.
Динамические параметры маршрутов могут влиять на реактивные данные
компонента. Vue Test Utils позволяет отслеживать изменения с помощью
setProps или перерендера при смене маршрута:
await router.push({ name: 'about', params: { id: '789' } })
await router.isReady()
expect(wrapper.text()).toContain('ID: 789')
Важно: Если компонент использует watch
на $route.params, необходимо учитывать асинхронность
обновлений.
Иногда тестирование полного роутера не требуется. Можно использовать
мок объекта $route и $router:
const wrapper = mount(MyComponent, {
global: {
mocks: {
$route: { params: { id: '42' }, name: 'about' },
$router: { push: jest.fn() }
}
}
})
expect(wrapper.vm.$route.params.id).toBe('42')
wrapper.vm.$router.push('/home')
expect(wrapper.vm.$router.push).toHaveBeenCalledWith('/home')
Преимущества:
Компоненты часто используют <router-link> или
методы this.$router.push для навигации. Vue Test Utils
позволяет эмулировать клики и проверять переходы:
const link = wrapper.find('a.router-link')
await link.trigger('click')
expect(wrapper.vm.$route.name).toBe('about')
Если используется Composition API с router.push() в
методах:
await wrapper.find('button.navigate').trigger('click')
expect(wrapper.vm.$router.push).toHaveBeenCalledWith({ name: 'about', params: { id: '101' } })
Кроме динамических сегментов пути, маршруты могут содержать query-параметры:
await router.push({ name: 'about', query: { ref: 'test' } })
await router.isReady()
expect(wrapper.vm.$route.query.ref).toBe('test')
Query-параметры являются реактивными, поэтому изменение query автоматически обновляет компонент.
Если маршруты используют динамическую загрузку компонентов через
defineAsyncComponent, необходимо учитывать асинхронность
при проверке:
await router.push('/about/999')
await router.isReady()
await flushPromises() // ожидает завершения загрузки асинхронного компонента
expect(wrapper.text()).toContain('ID: 999')
flushPromises гарантирует, что все промисы внутри
компонентов завершены, и тест проверяет фактический рендер.
Vue Router позволяет использовать beforeEnter или
глобальные guards. Их поведение можно тестировать, вызывая переход и
проверяя результат:
const mockGuard = jest.fn((to, from, next) => next())
const routes = [
{ path: '/protected', component: Protected, beforeEnter: mockGuard }
]
await router.push('/protected')
await router.isReady()
expect(mockGuard).toHaveBeenCalled()
Guards могут блокировать или перенаправлять навигацию, что важно учитывать при тестировании компонентов с доступом по ролям или состоянию.
Проверка роутов и параметров в Vue Test Utils требует понимания реактивности маршрутизатора и асинхронности переходов. Корректная настройка роутера, имитация навигации, проверка параметров и query позволяют полностью контролировать поведение компонентов, зависящих от маршрутизации.