Конфигурация для различных платформ

Настройка окружения для Vue Test Utils

Vue Test Utils (VTU) предоставляет API для изоляции компонентов и тестирования их поведения. Перед началом тестирования необходимо корректно настроить окружение, учитывая платформу — браузер или сервер (Node.js). Для браузерного тестирования часто используется jsdom, который эмулирует DOM, что позволяет запускать тесты в Node.js без реального браузера. В средах вроде Node.js конфигурация отличается, так как DOM отсутствует по умолчанию.

Пример базовой конфигурации с Jest и jsdom:

import { config } from '@vue/test-utils';
import { beforeEach } from '@jest/globals';

beforeEach(() => {
  config.global.stubs = {};
  config.global.mocks = {};
});

Здесь stubs используется для замены дочерних компонентов заглушками, а mocks — для внедрения глобальных объектов, таких как $router или $store. Для серверного тестирования необходимо учитывать, что асинхронные методы жизненного цикла компонента (например, mounted) могут вести себя иначе, поэтому тесты должны корректно ожидать их завершения.


Глобальные конфигурации

Vue Test Utils позволяет задавать глобальные параметры для всех тестов, включая:

  • stubs — заглушки для компонентов, которые не критичны для теста. Позволяют ускорять рендеринг.
  • mocks — подмена глобальных объектов Vue, таких как $route, $store, $t.
  • plugins — подключение Vue-плагинов, которые необходимы компоненту.
  • directives — регистрация пользовательских директив, используемых в тестируемом компоненте.
  • components — глобальная регистрация компонентов для тестов.

Пример расширенной глобальной конфигурации:

import { config } from '@vue/test-utils';
import Vuex from 'vuex';
import VueRouter from 'vue-router';

config.global.plugins = [new Vuex.Store({}), new VueRouter()];
config.global.stubs = ['ChildComponent'];
config.global.mocks = {
  $t: (msg) => msg,
};
config.global.directives = {
  focus: {
    mounted(el) {
      el.focus();
    },
  },
};

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


Конфигурация для Node.js

В Node.js отсутствует нативный DOM, что требует дополнительных шагов:

  1. Установка jsdom:

    npm install jsdom --save-dev
  2. Создание глобального DOM:

    import { JSDOM } from 'jsdom';
    
    const dom = new JSDOM('<!doctype html><html><body></body></html>');
    global.window = dom.window;
    global.document = dom.window.document;
    global.navigator = { userAgent: 'node.js' };
  3. Настройка Vue Test Utils для Node.js:

    import { config } from '@vue/test-utils';
    
    config.global.stubs = ['router-link'];

Это позволяет компонентам, которые используют браузерные API (window, document), корректно работать в тестовой среде.


Платформо-специфические особенности

Браузер:

  • Полная поддержка DOM, событий и анимаций.
  • Тесты могут быть интеграционными с настоящим рендерингом.
  • Поддерживаются события, такие как click, input, focus.

Node.js:

  • Используется эмуляция DOM.
  • Асинхронные жизненные циклы могут требовать await nextTick() или flushPromises().
  • Ограниченные возможности для тестирования анимаций и визуальных эффектов.

Использование mount и shallowMount

Выбор между mount и shallowMount зависит от платформы и цели теста:

  • mount — полное рендеринг компонента с дочерними компонентами. Предпочтительно в интеграционных тестах.
  • shallowMount — замещает дочерние компоненты заглушками, что ускоряет тестирование и снижает зависимость от внешних компонентов.

Пример адаптации под Node.js:

import { shallowMount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';

const wrapper = shallowMount(MyComponent, {
  global: {
    mocks: { $store: { state: {} } },
  },
});

Настройка асинхронного тестирования

На всех платформах необходимо учитывать асинхронность:

  • Использование await wrapper.vm.$nextTick() для ожидания обновлений DOM.
  • Применение flushPromises() для ожидания завершения всех промисов.
  • Для Node.js критично правильно управлять временем выполнения, так как jsdom не выполняет реальные анимации.
import { flushPromises } from '@vue/test-utils';

await flushPromises();
expect(wrapper.text()).toContain('Загружено');

Интеграция с инструментами CI/CD

Конфигурация платформы должна учитывать запуск тестов в автоматизированных пайплайнах:

  • В Node.js CI/CD чаще используется headless режим, что требует корректной эмуляции DOM.
  • Для браузерных тестов может использоваться Cypress или Playwright, но базовые юнит-тесты остаются на Jest + Vue Test Utils.
  • Глобальные конфигурации обеспечивают одинаковое поведение компонентов на локальной и CI среде.

Настройка для мульти-платформенных библиотек

Если библиотека должна работать и в браузере, и на сервере:

  • Разделяются конфигурации для global.mocks и global.stubs.
  • Подставляются платформо-зависимые заглушки и плагины.
  • Используются условные проверки:
if (typeof window !== 'undefined') {
  config.global.plugins.push(browserSpecificPlugin);
} else {
  config.global.plugins.push(serverSpecificPlugin);
}

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