Я собрал несколько примеров из своей прошлой работы с Vue.js при тестировании приложений и понял, что могу написать статью, которая поможет моим коллегам и (надеюсь) вам.

Vue.js - очень популярный фреймворк javascript с открытым исходным кодом для создания пользовательских интерфейсов и одностраничных приложений, простой для понимания и который многие компании начинают применять.

Для тестирования приложений Vue.js я использую Vue Test Utils в качестве утилиты для тестирования javascript. В нем есть много хороших методов, которые помогут вам смонтировать ваши компоненты и протестировать кейсы, которые вам нужно протестировать. Например, модульное тестирование функций ваших компонентов или тестовых взаимодействий.

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

Так почему бы не создать карманный справочник для дальнейшего использования?
Приступим?

Состояние компонента

Одна вещь, с которой вам нужно быть осторожным, - это мутировать состояние. В Vue, если вы не объявите свойства состояния, вы не сможете их изменять, потому что они не реактивные!

Обязательно используйте все необходимые свойства и не делайте ничего подобного, потому что это не сработает:

beforeEach(() => {
  state = {};
}
it('should do someting', () => {
 state.foo = 'bar';
});

Тебе следует:

beforeEach(() => {
  state = {
    foo: 'hello',
  }
}
it('should do someting', () => {
 state.foo = 'bar';
});

Обратите внимание, что я использую метод beforeEach для сброса состояния перед каждым тестом.

Компонентное крепление

Первое, что нужно сделать, это смонтировать компонент. Для этого мы воспользуемся Vue Test Utils, чтобы помочь нам.

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

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

Экземпляр Vue

Чтобы создать класс Vue wrapper, не загрязняя глобальный класс Vue при добавлении компонентов, миксинов, свойств и т. Д., Мы также будем использовать метод из Vue test utils, метод createLocalVue.

import Vue from 'vue';
import { shallowMount, createLocalVue } from '@vue/test-utils';
const localVue = createLocalVue();
describe('caption.vue', () => {
  let wrapper;
beforeEach(() => {
    wrapper = shallowMount(ComponentName, {
      localVue,
      propsData: {},
    });
  });
});

Насмешливые функции

Чтобы имитировать функции, мы воспользуемся помощью Jest и специального метода fn, который возвращает фиктивную функцию, а у вас есть доступ к некоторым полезным методам. Я покажу вам больше ниже!

Чтобы смоделировать метод из вашего экземпляра Vue, вы можете получить доступ, используя переменную vm вашего класса Vue.

wrapper.vm.didBlur = jest.fn();

Имитация возвращаемых значений функций

Если вам нужно имитировать возвращаемое значение метода из модуля, вам потребуется require весь модуль, даже если вы использовали именованный экспорт.

const captionsHelper = require('@/js/helpers/captions');
captionsHelper.didClickOutside.mockReturnValueOnce(false);

Ожидайте n вызовов функций

Если вы ожидаете, что какая-то функция будет вызываться n раз, будьте осторожны, если вы вызываете функцию в другом it операторе.

Для expect n вызовов функций:
expect(wrapper.vm.didBlur.mock.calls.length).toBe(1);

Ожидайте, если событие было сгенерировано

Событие, передаваемое через компонент

  • Вам нужно вызвать функцию, которая будет генерировать событие
  • Проверьте, было ли событие сгенерировано
  • Проверить, какие аргументы были переданы
describe('#didBlur', () => {
  it('should emit setActiveCaptionState event', () => {
    wrapper.vm.didBlur();
    
    expect(wrapper.emitted('setActiveCaptionState')).toBeTruthy();
    expect(wrapper.emitted('setActiveCaptionState')).toEqual([
      [{ caption: wrapper.vm.subtitle, isActive: false }],
    ]);
  });
});

Событие через глобальный $ eventHub

  • Создайте функцию-заглушку с помощью jest
  • Добавьте заглушку как обратный вызов события
  • Вызов метода, который будет генерировать событие
  • Проверьте, было ли инициировано событие или переданы аргументы
it('emit handleCaptionClicked event', () => {
  const stub = jest.fn();
  wrapper.vm.$eventHub.$on('handleCaptionClicked', stub);
  wrapper.vm.handleClick();
  expect(stub).toBeCalled();
  expect(stub).toBeCalledWith(wrapper.vm.subtitle.start_time);
});

Проверьте, был ли вызван метод в компоненте

  • Вызов метода, который будет генерировать событие
  • Проверьте, было ли инициировано событие или переданы аргументы
it('emit changeLineBackgroundWarning event', () => {
  wrapper.vm.changeLineBackgroundWarning  = jest.fn();
  wrapper.vm.handleInput(event);
  
  expect(wrapper.vm.changeLineBackgroundWarning).toHaveBeenCalled();
});

Наблюдатели за тестами

  • Установите реквизит или состояние, которое вы смотрите
  • Измените реквизит или состояние, которое вы смотрите
  • Ожидание
it('should change the state prop isRead to true', () => {
  wrapper = shallowMount(Caption, {
    localVue,
    propsData: {
      subtitle: {
        start_time: 0.5,
      },
      currentTime: 0,
    },
  });
  
  wrapper.setData({ isRead: false });
  wrapper.setProps({
    currentTime: 1,
  });
  expect(wrapper.vm.isRead).toBeTruthy();
});

Независимое тестирование Vuex

Не забывайте, что вам нужно импортировать real mutation / action / getter, который вы хотите протестировать, потому что вы вызовете его позже.

Действия при тестировании

  • Вы должны вызвать действие из магазина
  • Фиксация, отправка и т. Д. Должны быть шутливыми функциями, чтобы вы могли проверить, были ли они вызваны или нет.

Если вы хотите проверить, отправляет ли действие другие действия или совершает ли какую-либо мутацию, вы можете сделать:

// Check if a specific action has been called
it('should initiate the smartcheck plugin', () => {
  state.showSmartcheck = true;
  actions.setTaskState(
    { dispatch, commit, getters, state },
    { taskFromServer: task, localStorageTaskType: 'captioning' },
  );
  expect(dispatch).toHaveBeenCalledWith('initSmartcheckPlugin');
});

Тестирование геттеров

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

describe('taskInfo', () => {
  const state = {
    id: 'cenas',
    type: 'cenas',
    status: 'cenas',
  };
  it('should return the right properties', () => {
    expect(getters.taskInfo(state)).toEqual({
      id: state.id,
      type: state.type,
    });
  });
});

Тестирование мутаций

Чтобы проверить мутации, единственное, что вам нужно проверить, - это изменилось ли состояние. Для этого мы:

  • Создать объект состояния
  • Передайте состояние как аргумент мутации
  • Проверьте, соответствует ли состояние ожидаемому
import mutations from '@/js/store/modules/foo/mutations';
beforeEach(() => {
  state = {
    foo: 'bar'
  };
});
it('should change foo state to john', () => {
  mutations.CHANGE_TO_JOHN(state);
  expect(state).toEqual({
    foo: 'john',
  });
});

На этом пока все!
Я, наверное, добавлю в статью больше случаев. Это будет мой карманный справочник для будущих справок!