Guard’ы (маршрутизаторы и навигационные охранники) играют ключевую роль в управлении переходами между маршрутами во Vue-приложениях. Правильное тестирование guard’ов обеспечивает надежность логики навигации, предотвращает доступ к запрещенным страницам и позволяет корректно обрабатывать условия перехода. В экосистеме Vue Test Utils процесс тестирования guard’ов требует внимания к контексту маршрутизатора и состоянию приложения.
Для начала необходимо настроить Vue Router в тестовой среде. Обычно
используются функции createRouter и
createWebHistory (или createMemoryHistory для
тестов), чтобы эмулировать поведение маршрутов без зависимости от
браузера.
import { mount } from '@vue/test-utils';
import { createRouter, createMemoryHistory } from 'vue-router';
import MyComponent from '@/components/MyComponent.vue';
const routes = [
{ path: '/', component: MyComponent },
{ path: '/protected', component: MyComponent, meta: { requiresAuth: true } }
];
const router = createRouter({
history: createMemoryHistory(),
routes
});
Использование createMemoryHistory позволяет полностью
контролировать переходы между маршрутами, не затрагивая реальный адрес в
браузере.
Глобальные guard’ы, такие как router.beforeEach, часто
используются для проверки авторизации или условий доступа. Тестирование
этих guard’ов сводится к имитации состояния приложения и проверке
правильности редиректа или разрешения перехода.
router.beforeEach((to, from, next) => {
const isAuthenticated = false;
if (to.meta.requiresAuth && !isAuthenticated) {
next('/');
} else {
next();
}
});
test('редирект на / если пользователь не авторизован', async () => {
router.push('/protected');
await router.isReady();
expect(router.currentRoute.value.fullPath).toBe('/');
});
Ключевые моменты:
router.isReady() гарантирует, что
асинхронная навигация завершена.router.push() инициирует переход к маршруту.router.currentRoute.value позволяет убедиться,
что guard корректно отработал.Локальные guard’ы назначаются на конкретные маршруты и проверяются аналогично глобальным, но с фокусом на отдельный маршрут.
const routes = [
{
path: '/admin',
component: MyComponent,
beforeEnter: (to, from, next) => {
const isAdmin = false;
isAdmin ? next() : next('/');
}
}
];
test('локальный guard перенаправляет неадмина', async () => {
router.push('/admin');
await router.isReady();
expect(router.currentRoute.value.fullPath).toBe('/');
});
Особенность тестирования локальных guard’ов:
currentRoute.Guard’ы могут содержать асинхронную логику, например, запросы к API
для проверки прав доступа. В таких случаях необходимо использовать
async/await в тестах и ожидать завершения навигации.
router.beforeEach(async (to, from, next) => {
const hasAccess = await checkAccess(to.path);
hasAccess ? next() : next('/');
});
test('асинхронный guard корректно блокирует доступ', async () => {
router.push('/protected');
await router.isReady();
expect(router.currentRoute.value.fullPath).toBe('/');
});
Ключевые моменты:
await router.isReady() синхронизирует тест с
навигацией.Иногда важно проверять, что guard влияет на поведение компонентов. Для этого Vue Test Utils позволяет монтировать компоненты с интегрированным маршрутизатором.
import { mount } from '@vue/test-utils';
test('компонент не рендерится при блокировке guard', async () => {
const wrapper = mount(MyComponent, {
global: {
plugins: [router]
}
});
router.push('/protected');
await router.isReady();
expect(wrapper.html()).toBe('');
});
Принципы:
router.wrapper.html() позволяет убедиться, что
содержимое корректно отрендерено или отсутствует.Часто guard’ы используют данные из meta маршрута для
определения условий перехода. Тестирование должно учитывать разные
комбинации этих данных.
const routes = [
{ path: '/vip', component: MyComponent, meta: { requiresVIP: true } }
];
router.beforeEach((to, from, next) => {
const isVIP = false;
to.meta.requiresVIP && !isVIP ? next('/') : next();
});
test('meta guard перенаправляет не VIP пользователя', async () => {
router.push('/vip');
await router.isReady();
expect(router.currentRoute.value.fullPath).toBe('/');
});
Принципы:
currentRoute.router.isReady() или
nextTick().Тестирование guard’ов с Vue Test Utils и Vue Router обеспечивает надежность навигационной логики и позволяет выявлять ошибки доступа на раннем этапе разработки. Правильная организация тестов, внимание к асинхронности и метаданным маршрутов делают тесты стабильными и воспроизводимыми.