Тестирование компонентов с RouterLink

При тестировании Vue-компонентов, содержащих навигационные элементы, такие как <RouterLink>, важно учитывать, что эти компоненты зависят от экземпляра маршрутизатора Vue Router. Без корректной настройки тестовой среды попытки рендеринга компонентов с <RouterLink> могут привести к ошибкам или некорректному поведению.


Мокирование маршрутизатора

Для изоляции компонента от реального маршрутизатора используется мокирование. В тестах на основе vue-test-utils достаточно создать фейковый экземпляр маршрутизатора:

import { mount } from '@vue/test-utils';
import { createRouter, createWebHistory } from 'vue-router';
import MyComponent from '@/components/MyComponent.vue';

const routes = [
  { path: '/', name: 'Home' },
  { path: '/about', name: 'About' }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

router.push('/'); // Начальное состояние маршрута

test('RouterLink рендерится корректно', async () => {
  const wrapper = mount(MyComponent, {
    global: {
      plugins: [router]
    }
  });

  await router.isReady(); // Ждем готовности маршрутизатора

  expect(wrapper.find('a').attributes('href')).toBe('/');
});

Ключевой момент — использование router.isReady(). Без ожидания маршрутизатор может быть не инициализирован, что приведет к ошибкам при попытке взаимодействия с <RouterLink>.


Проверка переходов по ссылкам

Компоненты с <RouterLink> можно тестировать на корректность навигации. Для этого важно симулировать клик и убедиться, что маршрут изменился:

test('переход по RouterLink', async () => {
  const wrapper = mount(MyComponent, {
    global: {
      plugins: [router]
    }
  });

  await router.isReady();

  const link = wrapper.find('a');
  await link.trigger('click');

  expect(router.currentRoute.value.fullPath).toBe('/about');
});

При этом <RouterLink> не обязательно рендерится в реальный <a> тег, если используется компонентная реализация, поэтому проверка может включать атрибут to:

expect(wrapper.findComponent({ name: 'RouterLink' }).props('to')).toBe('/about');

В некоторых случаях тестирование компонента не должно зависеть от реального маршрутизатора. В таких ситуациях удобно мокировать <RouterLink>, заменяя его простым компонентом-заглушкой:

const RouterLinkStub = {
  props: ['to'],
  template: '<a><slot /></a>'
};

const wrapper = mount(MyComponent, {
  global: {
    stubs: {
      RouterLink: RouterLinkStub
    }
  }
});

expect(wrapper.find('a').exists()).toBe(true);
expect(wrapper.find('a').text()).toBe('Перейти на About');

Такой подход позволяет тестировать визуальное отображение и слоты без необходимости конфигурировать полноценный маршрутизатор.


Навигация и параметры маршрута

Для компонентов, которые используют динамические параметры маршрута, важно правильно мокировать текущий маршрут. Например, если компонент получает id из URL:

import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  { path: '/user/:id', name: 'User' }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

router.push('/user/42');

const wrapper = mount(UserProfile, {
  global: {
    plugins: [router]
  }
});

await router.isReady();

expect(wrapper.vm.$route.params.id).toBe('42');

Это позволяет проверять отображение данных, зависящих от параметров маршрута, без необходимости запускать полноценное приложение.


Интеграционное тестирование с Vue Router

Для более сложных тестов полезно использовать реальный экземпляр маршрутизатора, чтобы проверить навигацию между компонентами:

const wrapper = mount(App, {
  global: {
    plugins: [router]
  }
});

await router.isReady();

await wrapper.find('a[href="/about"]').trigger('click');
expect(wrapper.html()).toContain('Страница About');

Здесь проверяется не только <RouterLink>, но и то, что рендерится соответствующий компонент при смене маршрута.


Практические рекомендации

  • Использовать router.isReady() перед взаимодействием с компонентами, зависящими от маршрутизатора.
  • Мокировать <RouterLink> для юнит-тестов, чтобы тест был независимым и быстрым.
  • Для тестов навигации применять реальный экземпляр маршрутизатора и проверять router.currentRoute.value.
  • Проверять как атрибут to, так и реальные клики по ссылкам, чтобы убедиться в правильной интеграции маршрутизатора и компонентов.

Эти методы позволяют обеспечить полное покрытие компонентов, работающих с навигацией, и избежать неожиданных ошибок при изменениях маршрутов.