Тестирование дефолтного слота

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

Передача контента в дефолтный слот

Для тестирования дефолтного слота используется опция slots при монтировании компонента с помощью функции mount. Ключ default указывает содержимое, которое будет вставлено в слот. Пример базового использования:

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

const wrapper = mount(MyComponent, {
  slots: {
    default: '<p class="slot-content">Текст слота</p>'
  }
})

В этом примере внутрь компонента MyComponent вставляется параграф с классом slot-content. После монтирования можно проверять, что контент присутствует:

expect(wrapper.find('.slot-content').exists()).toBe(true)
expect(wrapper.text()).toContain('Текст слота')

Использование Vue компонентов внутри слота

В слот можно передавать не только HTML, но и полноценные Vue-компоненты. Это особенно важно для тестирования динамического контента, который зависит от props или методов родительского компонента:

import ChildComponent from '@/components/ChildComponent.vue'

const wrapper = mount(MyComponent, {
  slots: {
    default: ChildComponent
  }
})

В этом случае Vue Test Utils корректно рендерит переданный компонент, и его поведение можно проверять так же, как обычного дочернего компонента:

expect(wrapper.findComponent(ChildComponent).exists()).toBe(true)

Динамические слоты с функцией

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

const wrapper = mount(MyComponent, {
  slots: {
    default: props => `<span>${props.message}</span>`
  }
})

Однако в Vue 3 более правильным подходом является передача VNode через h:

import { h } from 'vue'

const wrapper = mount(MyComponent, {
  slots: {
    default: () => h('span', 'Динамический слот')
  }
})

Проверка рендеринга слота

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

  1. find и findComponent – поиск конкретного элемента или компонента внутри слота.
  2. text() – проверка текстового содержимого.
  3. html() – проверка полной HTML-структуры слота.
  4. exists() – проверка наличия слота в DOM.

Пример комплексной проверки:

const wrapper = mount(MyComponent, {
  slots: {
    default: '<button class="slot-button">Нажми меня</button>'
  }
})

const button = wrapper.find('.slot-button')
expect(button.exists()).toBe(true)
expect(button.text()).toBe('Нажми меня')

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

Если слот содержит интерактивные элементы, важно проверять, как они взаимодействуют с компонентом. Например, слот может содержать кнопку, которая вызывает метод родителя:

const wrapper = mount(MyComponent, {
  slots: {
    default: '<button @click="increment">+</button>'
  },
  methods: {
    increment: jest.fn()
  }
})

await wrapper.find('button').trigger('click')
expect(wrapper.vm.increment).toHaveBeenCalled()

Важные нюансы

  • Слоты не наследуют реактивность родителя, если они рендерятся как статический HTML. Для динамического поведения нужно использовать Vue-компоненты или функции с h.
  • Множественные слоты: даже при наличии именованных слотов дефолтный слот всегда доступен через ключ default.
  • Асинхронный контент: если слот зависит от асинхронных данных, рекомендуется использовать nextTick для ожидания рендеринга:
import { nextTick } from 'vue'

await nextTick()
expect(wrapper.find('.slot-content').exists()).toBe(true)

Советы по организации тестов слотов

  1. Стараться тестировать слот отдельно от логики компонента, чтобы выделить ошибки рендеринга.
  2. Использовать snapshot-тестирование для сложных слотов, чтобы фиксировать HTML-структуру.
  3. Проверять не только существование элементов, но и их взаимодействие с методами родителя и реактивными данными.

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