Это руководство было написано для Vue.js 3 и Vue Test Utils v2.

Версия для Vue.js 2 здесь.

# Тестирования пользовательских событий

С ростом приложения растёт количество компонентов. Когда им нужно общаться между собой, дочерний компонент может породить событие, а родитель ответить на него.

vue-test-utils предоставляет emitted API, который позволит нам сделать проверку на пользовательские события. Документацию для emitted можно найти здесь.

Исходный код для тестов на этой странице можно взять тут.

# Написание компонента и теста к нему

Давайте сделаем простой компонент. Назовём его <Emitter> и добавим следующий код:

<template>
  <div>
  </div>
</template>

<script>
  export default {
    name: "Emitter",

    methods: { 
      emitEvent() {
        this.$emit("myEvent", "name", "password")
      }
    }
  }
</script>

Тест назовём emitEvent:

import Emitter from "@/components/Emitter.vue"
import { mount } from "@vue/test-utils"

describe("Emitter.vue", () => {
  it("Порождает событие с двумя аргументами", () => {
    const wrapper = mount(Emitter)

    wrapper.vm.emitEvent()

    console.log(wrapper.emitted())
  })
})

Используя emitted API, предоставленный нам vue-test-utils, мы можем с лёгкостью посмотреть все порождённые события.

Запустим тест, написав yarn test:unit.

PASS  tests/unit/Emitter.spec.js
● Console

  console.log tests/unit/Emitter.spec.js:10
    { myEvent: [ [ 'name', 'password' ] ] }

# Синтаксис emitted

emitted возвращает объект. Порождённые события сохраняются, как свойства объекта. Вы можете проверять события, используя emitted().[event]:

emitted().myEvent //=>  [ [ 'name', 'password' ] ]

Давайте попробуем вызвать emitEvent дважды:

it("Порождает событие с двумя аргументами", () => {
  const wrapper = mount(Emitter)

  wrapper.vm.emitEvent()
  wrapper.vm.emitEvent()

  console.log(wrapper.emitted().myEvent)
})

Запустим тест, написав yarn test:unit.

console.log tests/unit/Emitter.spec.js:11
  [ [ 'name', 'password' ], [ 'name', 'password' ] ]

emitted().emitEvent возвращает массив. Первый экземпляр emitEvent можно достать через emitted().emitEvent[0]. Аргументы получают похожим синтаксисом: emitted().emitEvent[0][0] и так далее.

Давайте сделаем реальную проверку для порождённых событий:

it("Порождает событие с двумя аргументами", () => {
  const wrapper = mount(Emitter)

  wrapper.vm.emitEvent()

  expect(wrapper.emitted().myEvent[0]).toEqual(["name", "password"])
})

Тест проходит проверку.

# Тестирование событий без монтирования компонента

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

it("Порождает событие без монтирования компонента", () => {
  const events = {}
  const $emit = (event, ...args) => { events[event] = [...args] }

  Emitter.methods.emitEvent.call({ $emit })

  expect(events.myEvent).toEqual(["name", "password"])
})

Так как $emit – обычный JavaScript объект, мы может замокать $emit и использовать call, чтобы прикрепить его к контексту this из emitEvent. Используя call, вы также можете вызывать методы без монтирования компонента.

Использовать call может быть полезно в ситуациях, где есть несколько тяжёлых функций в хуках жизненного цикла created или mounted, и вы не хотите их выполнять. Так как вы не монтируете компонент, функции из хуков никогда не выполнятся. Также call полезен при манипулировании контекстом this.

Как правило, вы не хотите вызывать метод вручную, как мы это делаем здесь – если ваш компонент генерирует событие при нажатии кнопки, то вы, вероятнее всего, захотите выполнить wrapper.find ('button').сlick(). Эта статья просто демонстрация других техник.

# Заключение

  • emitted API из vue-test-utils используется, чтобы проверять пользовательские события
  • emitted - это метод возвращающий объект, в свойствах которого находятся порождённые события
  • каждое свойство из emitted является массивом. Чтобы достать экземпляр пользовательских событий, можно использовать синтаксис массивов [0], [1]
  • аргументы для пользовательских событий также сохраняются в виде массивов, которые можно взять, используя [0], [1].
  • $emit можно замокать, используя call. Проверки можно делать без монтирования компонента

Исходный код для тестов на этой странице можно взять тут.