В Vue.js слоты позволяют компонентам быть гибкими и расширяемыми за счёт передачи содержимого из родительского компонента. Тестирование слотов является важной частью обеспечения корректного поведения компонентов, особенно если логика или отображение зависит от динамического содержимого.
В Vue Test Utils слоты передаются при создании обёртки компонента с
помощью метода mount или shallowMount через
опцию slots. Эта опция принимает объект, где ключи
соответствуют именам слотов, а значения — содержимому, которое будет
вставлено.
Пример базового использования:
import { mount } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'
const wrapper = mount(MyComponent, {
slots: {
default: '<p>Текст слота</p>',
header: '<h1>Заголовок</h1>'
}
})
В этом примере компонент MyComponent получает два слота:
default и header. Содержимое будет отрендерено
внутри соответствующих <slot> тегов компонента.
Для проверки содержимого используется метод html() или
селекторы внутри обёртки компонента. Часто проверяют:
Пример проверки текста слота:
expect(wrapper.html()).toContain('Текст слота')
Можно также использовать метод find для более точного
поиска элементов внутри слота:
expect(wrapper.find('p').text()).toBe('Текст слота')
expect(wrapper.find('h1').exists()).toBe(true)
Если слоты именованные, следует проверять их отдельно через селекторы по классу или атрибуту, которые компоненты добавляют к слотам.
Слоты часто зависят от данных родителя. Чтобы проверить динамическое поведение, создаются обёртки с изменяемыми пропсами или реактивными данными. Например:
import { reactive } from 'vue'
const state = reactive({ message: 'Привет' })
const wrapper = mount(MyComponent, {
slots: {
default: `<p>${state.message}</p>`
}
})
expect(wrapper.find('p').text()).toBe('Привет')
state.message = 'Пока'
await wrapper.vm.$nextTick()
expect(wrapper.find('p').text()).toBe('Пока')
Здесь проверяется, что слот корректно реагирует на изменение данных, переданных из родителя.
Содержимое слота может быть другим компонентом. В этом случае
проверка ведётся через findComponent или
findAllComponents:
import ChildComponent from '@/components/ChildComponent.vue'
const wrapper = mount(MyComponent, {
slots: {
default: ChildComponent
}
})
expect(wrapper.findComponent(ChildComponent).exists()).toBe(true)
Также можно передавать компонент с пропсами, используя функцию рендеринга:
const wrapper = mount(MyComponent, {
slots: {
default: (props) => h(ChildComponent, { title: props.title })
}
})
Это позволяет тестировать слоты, которые используют
v-slot с передачей параметров из компонента.
Если слот не передан, Vue рендерит fallback-контент. Проверка этого поведения необходима для обеспечения корректного отображения:
const wrapper = mount(MyComponent)
expect(wrapper.find('.default-slot').text()).toBe('Контент по умолчанию')
Здесь .default-slot — элемент, в котором находится
дефолтный контент слота.
Слоты могут содержать интерактивные элементы, которые вызывают события компонента. Для проверки взаимодействия важно соединять проверку слота и событий:
const wrapper = mount(MyComponent, {
slots: {
default: '<button class="btn">Клик</button>'
}
})
await wrapper.find('button').trigger('click')
expect(wrapper.emitted()).toHaveProperty('button-clicked')
Таким образом, тесты покрывают не только визуальное отображение, но и поведение компонентов, встроенных в слоты.
Эти методы обеспечивают глубокую и точную проверку поведения слотов, что критично для компонентов с динамическим содержимым и сложной структурой.