Слоты в Vue — это механизм, позволяющий компонентам быть более гибкими и настраиваемыми за счёт передачи им содержимого извне. Тестирование компонентов со слотами требует особого подхода, так как слоты влияют на структуру DOM, поведение и визуальное отображение компонента. Понимание принципов работы слотов критично для написания надежных тестов.
По умолчанию (Default Slot) Это основной слот, в который вставляется контент без указания имени. Он применяется, когда компонент должен принимать произвольное содержимое.
<MyComponent>
<p>Контент по умолчанию</p>
</MyComponent>Именованные слоты (Named Slots) Позволяют
различать несколько областей компонента для вставки контента.
Используются атрибут name на <slot> и
соответствующий v-slot:name при передаче содержимого.
<MyComponent>
<template v-slot:header>
<h1>Заголовок</h1>
</template>
<template v-slot:footer>
<p>Подвал</p>
</template>
</MyComponent>Слоты с пропсами (Scoped Slots) Передают данные от компонента родителю, позволяя родительскому контенту динамически изменяться на основе состояния компонента.
<MyComponent>
<template v-slot:item="slotProps">
<p>{{ slotProps.text }}</p>
</template>
</MyComponent>Слоты могут изменять поведение компонента, добавлять новые элементы в DOM и влиять на рендеринг. Неправильная работа слотов может привести к нарушению интерфейса или логики компонента. Тестирование слотов помогает:
Vue Test Utils предоставляет гибкие методы для работы с компонентами и их слотами.
Для тестирования слота используется опция slots при
вызове mount или shallowMount.
import { mount } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'
test('рендерит контент по умолчанию', () => {
const wrapper = mount(MyComponent, {
slots: {
default: '<p>Контент слота</p>'
}
})
expect(wrapper.html()).toContain('Контент слота')
})
Именованные слоты передаются объектом с ключами, соответствующими имени слота.
const wrapper = mount(MyComponent, {
slots: {
header: '<h1>Заголовок</h1>',
footer: '<p>Подвал</p>'
}
})
expect(wrapper.find('h1').text()).toBe('Заголовок')
expect(wrapper.find('p').text()).toBe('Подвал')
Для scoped слотов необходимо использовать функцию, возвращающую строку с разметкой или компонент.
const wrapper = mount(MyComponent, {
slots: {
item: `<template #item="{ text }"><span>{{ text }}</span></template>`
}
})
expect(wrapper.find('span').exists()).toBe(true)
Если слот содержит элементы с событиями, можно тестировать их через
trigger.
const wrapper = mount(MyComponent, {
slots: {
default: '<button @click="$emit(\'clicked\')">Клик</button>'
}
})
wrapper.find('button').trigger('click')
expect(wrapper.emitted('clicked')).toBeTruthy()
wrapper.find или wrapper.findAll
позволяют проверять конкретные элементы.<template> для scoped slots — приведет к неправильной
привязке пропсов.Слоты часто проверяются совместно с Jest, что позволяет писать комплексные тесты:
import { mount } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'
describe('MyComponent слоты', () => {
it('рендерит несколько слотов', () => {
const wrapper = mount(MyComponent, {
slots: {
header: '<h1>Заголовок</h1>',
default: '<p>Основной контент</p>',
footer: '<footer>Футер</footer>'
}
})
expect(wrapper.find('h1').text()).toBe('Заголовок')
expect(wrapper.find('p').text()).toBe('Основной контент')
expect(wrapper.find('footer').text()).toBe('Футер')
})
})
Тестирование слотов позволяет убедиться в полной корректности передачи и отображения контента, обеспечивая надежность компонентов и предотвращая регрессии при изменении кода.