Passer au contenu

Tester avec Vue Router

Mise en place d’un router de test

Pour tester des composants qui dépendent de Vue Router, vous devez créer un router simulé:

import { mount } from '@vue/test-utils'
import { createRouter, createWebHistory } from 'vue-router'
import { describe, it, expect, beforeEach } from 'vitest'
import AppNavigation from '@/components/AppNavigation.vue'
import Home from '@/pages/Home.vue'
import About from '@/pages/About.vue'
describe('AppNavigation.vue', () => {
let router
beforeEach(() => {
// Créer un router de test avec des routes simulées
router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', name: 'home', component: Home },
{ path: '/about', name: 'about', component: About }
]
})
})
it('highlights the current route link', async () => {
// Monter le composant avec le routeur
const wrapper = mount(AppNavigation, {
global: {
plugins: [router]
}
})
// Naviguer vers la route "about"
await router.push('/about')
// Vérifier que le lien "about" a la classe "active"
expect(wrapper.find('a[href="/about"]').classes()).toContain('active')
expect(wrapper.find('a[href="/"]').classes()).not.toContain('active')
})
})

Mocker le routeur avec createRouterMock

Au lieu de créer un routeur complet, vous pouvez mocker uniquement les fonctionnalités dont vous avez besoin:

import { mount } from '@vue/test-utils'
import { describe, it, expect, vi } from 'vitest'
import ProductLink from '@/components/ProductLink.vue'
describe('ProductLink.vue', () => {
it('navigates to the product page when clicked', async () => {
// Mocker $router et $route
const mockRouter = {
push: vi.fn()
}
const mockRoute = {
params: {}
}
const wrapper = mount(ProductLink, {
props: {
productId: '123'
},
global: {
mocks: {
$router: mockRouter,
$route: mockRoute
}
}
})
// Simuler un clic sur le lien
await wrapper.find('.product-link').trigger('click')
// Vérifier que router.push a été appelé avec le bon chemin
expect(mockRouter.push).toHaveBeenCalledWith({
name: 'product-details',
params: { id: '123' }
})
})
})

Tester les composants avec des paramètres de route

Si votre composant utilise les paramètres de route, vous pouvez les simuler ainsi:

import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import UserProfile from '@/components/UserProfile.vue'
describe('UserProfile.vue', () => {
it('displays user information based on route param', () => {
// Simuler un objet route avec des paramètres
const mockRoute = {
params: { userId: '42' }
}
const wrapper = mount(UserProfile, {
global: {
mocks: {
$route: mockRoute
}
}
})
// Vérifier que le composant utilise le paramètre correctement
expect(wrapper.text()).toContain('User ID: 42')
})
})

Tester les gardes de navigation

Si vous avez des composants qui utilisent des gardes de navigation, vous pouvez les tester ainsi:

import { mount } from '@vue/test-utils'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { createRouter, createWebHistory } from 'vue-router'
import AdminPanel from '@/components/AdminPanel.vue'
import LoginPage from '@/pages/LoginPage.vue'
import { useAuthStore } from '@/stores/auth'
import { createPinia } from 'pinia'
describe('Navigation Guards', () => {
let router
let pinia
let authStore
beforeEach(() => {
// Créer un store Pinia
pinia = createPinia()
// Créer un router de test
router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/admin',
name: 'admin',
component: AdminPanel,
meta: { requiresAuth: true }
},
{
path: '/login',
name: 'login',
component: LoginPage
}
]
})
// Ajouter un garde de navigation
router.beforeEach((to, from) => {
const auth = useAuthStore()
if (to.meta.requiresAuth && !auth.isAuthenticated) {
return { name: 'login' }
}
})
// Monter l'application avec le router et pinia
mount({
template: '<router-view />',
}, {
global: {
plugins: [router, pinia]
}
})
// Accéder au store d'authentification
authStore = useAuthStore()
})
it('redirects to login when accessing protected route as unauthenticated user', async () => {
// Simuler un utilisateur non authentifié
authStore.isAuthenticated = false
// Essayer d'accéder à une route protégée
await router.push('/admin')
// Vérifier la redirection
expect(router.currentRoute.value.name).toBe('login')
})
it('allows access to protected route for authenticated users', async () => {
// Simuler un utilisateur authentifié
authStore.isAuthenticated = true
// Accéder à une route protégée
await router.push('/admin')
// Vérifier qu'il n'y a pas de redirection
expect(router.currentRoute.value.name).toBe('admin')
})
})

Pour tester les composants qui utilisent router-link:

import { mount } from '@vue/test-utils'
import { describe, it, expect, vi } from 'vitest'
import MainMenu from '@/components/MainMenu.vue'
import { RouterLinkStub } from '@vue/test-utils'
describe('MainMenu.vue', () => {
it('renders router links with correct props', () => {
const wrapper = mount(MainMenu, {
global: {
stubs: {
RouterLink: RouterLinkStub
}
}
})
const homeLink = wrapper.findComponent(RouterLinkStub)
// Vérifier les props du RouterLink
expect(homeLink.props().to).toEqual({ name: 'home' })
// Vérifier le nombre de liens
const links = wrapper.findAllComponents(RouterLinkStub)
expect(links.length).toBe(3) // supposant qu'il y a 3 liens dans le menu
})
})