Введение

Настройка

Для быстрого старта работы с Vue Test Utils, клонируйте наш демонстрационный репозиторий с базовыми настройками и установите зависимости:

git clone https://github.com/vuejs/vue-test-utils-getting-started
cd vue-test-utils-getting-started
npm install

Вы увидите, что проект содержит простой компонент counter.js:

// counter.js

export default {
  template: `
    <div>
      <span class="count">{{ count }}</span>
      <button @click="increment">Increment</button>
    </div>
  `,

  data() {
    return {
      count: 0
    }
  },

  methods: {
    increment() {
      this.count++
    }
  }
}

Монтирование компонентов

Vue Test Utils тестирует компоненты Vue монтируя их изолированно, создавая моки необходимых входных данных (входные параметры, инъекции и пользовательские события) и выполняя проверки над результатом (результат рендеринга, вызванные пользовательские события).

Примонтированные компоненты возвращаются внутри Wrapper, который предоставляет множество удобных методов для манипулирования, перемещения и различных запросов для экземпляра компонента Vue.

Вы можете создавать wrapper с помощью метода mount. Давайте создадим файл test.js:

// test.js

// Импортируем метод `mount()` из `vue-test-utils`
// и компонент, который хотим протестировать
import { mount } from '@vue/test-utils'
import Counter from './counter'

// Теперь монтируем компонент и у нас появляется wrapper
const wrapper = mount(Counter)

// Вы можете получить доступ к экземпляру Vue через `wrapper.vm`
const vm = wrapper.vm

// Чтобы изучить wrapper подробнее, просто выведите его в консоль
// и ваши приключения с `vue-test-utils` начнутся
console.log(wrapper)

Тестирование отрендеренного HTML компонента

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

import { mount } from '@vue/test-utils'
import Counter from './counter'

describe('Компонент Counter', () => {
  // Теперь монтируем компонент и получаем wrapper
  const wrapper = mount(Counter)

  it('отображает корректную разметку', () => {
    expect(wrapper.html()).toContain('<span class="count">0</span>')
  })

  // также легко проверить наличие других элементов
  it('имеет кнопку', () => {
    expect(wrapper.contains('button')).toBe(true)
  })
})

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

Симуляция пользовательских действий

Наш счётчик должен увеличивать значение, когда пользователь нажимает кнопку. Чтобы симулировать это поведение, нам необходимо сначала получить кнопку с помощью wrapper.find(), который возвращает wrapper для элемента кнопки. Мы можем симулировать клик с помощью вызова .trigger() на wrapper кнопки:

it('нажатие кнопки должно увеличивать счётчик', () => {
  expect(wrapper.vm.count).toBe(0)
  const button = wrapper.find('button')
  button.trigger('click')
  expect(wrapper.vm.count).toBe(1)
})

Что делать с nextTick?

Vue собирает пачку предстоящих обновлений DOM и применяет их асинхронно для избежания ненужных повторных рендерингов, вызываемых множественными изменениями данных. Вот почему на практике нe часто приходится использовать Vue.nextTick для ожидания, пока Vue выполнит фактическое обновление DOM после того, как мы инициируем некоторое изменение состояния.

Для упрощения работы, vue-test-utils применяет все обновления синхронно, поэтому вам не потребуется использовать Vue.nextTick для ожидания обновления DOM в ваших тестах.

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

Если вам всё ещё нужно использовать nextTick в ваших тестовых файлах, имейте ввиду, что любые ошибки, выброшенные внутри него, могут не быть отловлены вашей программой для запуска тестов, поскольку внутри он реализован на Promise. Существует два подхода исправления этого: либо вы можете установить коллбэк done как глобальный обработчик ошибок Vue в начале теста, либо вы можете вызывать nextTick без аргумента и вернуть его как Promise:

// эта ошибка не будет отловлена
it('ошибка не будет отслеживаться', done => {
  Vue.nextTick(() => {
    expect(true).toBe(false)
    done()
  })
})

// два следующих теста будут работать как ожидается
it('должен отлавливать ошибку с использованием done', done => {
  Vue.config.errorHandler = done
  Vue.nextTick(() => {
    expect(true).toBe(false)
    done()
  })
})

it('должен отлавливать ошибку с использованием promise', () => {
  return Vue.nextTick().then(function() {
    expect(true).toBe(false)
  })
})

Что дальше