Слоты
Vue Test Utils предоставляет несколько полезных функций для тестирования компонентов, используя slots
.
Простой пример
Возможно, у вас есть <layout>
компонент, который использует слот по умолчанию для отображения некоторого содержимого. Например:
const Layout = {
template: `
<div>
<h1>Welcome!</h1>
<main>
<slot />
</main>
<footer>
Thanks for visiting.
</footer>
</div>
`
}
Возможно, вы хотите написать тест, чтобы убедиться в том, что содержимое слота по умолчанию отрисовано. VTU предоставляет slots
опцию монтирования для этой цели:
test('layout default slot', () => {
const wrapper = mount(Layout, {
slots: {
default: 'Main Content'
}
})
expect(wrapper.html()).toContain('Main Content')
})
Тест пройден! В этом примере мы передаем содержимое некоторого текста в слот по умолчанию. Если ты хочешь быть еще более конкретным и убедиться, что содержимое слота по умолчанию отрисовано в <main>
, вы могли бы изменить проверку:
test('layout default slot', () => {
const wrapper = mount(Layout, {
slots: {
default: 'Main Content'
}
})
expect(wrapper.find('main').text()).toContain('Main Content')
})
Именованные слоты
У вас может быть более сложный <layout>
компонент с несколькими именованными слотами. Например:
const Layout = {
template: `
<div>
<header>
<slot name="header" />
</header>
<main>
<slot name="main" />
</main>
<footer>
<slot name="footer" />
</footer>
</div>
`
}
VTU также поддерживает это. Вы можете написать тест следующим образом. Обратите внимание, в этом примере мы передаем HTML вместо содержимого текста в слоты.
test('layout full page layout', () => {
const wrapper = mount(Layout, {
slots: {
header: '<div>Header</div>',
main: '<div>Main Content</div>',
footer: '<div>Footer</div>'
}
})
expect(wrapper.html()).toContain('<div>Header</div>')
expect(wrapper.html()).toContain('<div>Main Content</div>')
expect(wrapper.html()).toContain('<div>Footer</div>')
})
Множественные слоты
Вы также можете передать массив слотов:
test('layout full page layout', () => {
const wrapper = mount(Layout, {
slots: {
default: [
'<div id="one">One</div>',
'<div id="two">Two</div>'
]
}
})
expect(wrapper.find('#one').exists()).toBe(true)
expect(wrapper.find('#two').exists()).toBe(true)
})
Продвинутое использование
Ты также можешь передать функцию отрисовки, объект с шаблоном или даже SFC, импортированный из vue
файла, в слот опцию монтирования:
import { h } from 'vue'
import Header from './Header.vue'
test('layout full page layout', () => {
const wrapper = mount(Layout, {
slots: {
header: Header,
main: h('div', 'Main Content'),
sidebar: { template: '<div>Sidebar</div>' },
footer: '<div>Footer</div>'
}
})
expect(wrapper.html()).toContain('<div>Header</div>')
expect(wrapper.html()).toContain('<div>Main Content</div>')
expect(wrapper.html()).toContain('<div>Footer</div>')
})
Изучите тесты с большим количеством примеров и вариантов использования.
Слоты с ограниченной областью действия
Слоты с ограниченной областью действия и привязки также доступны.
const ComponentWithSlots = {
template: `
<div class="scoped">
<slot name="scoped" v-bind="{ msg }" />
</div>
`,
data() {
return {
msg: 'world'
}
}
}
test('scoped slots', () => {
const wrapper = mount(ComponentWithSlots, {
slots: {
scoped: `<template #scoped="scope">
Hello {{ scope.msg }}
</template>
`
}
})
expect(wrapper.html()).toContain('Hello world')
})
Когда используется шаблоны строк для содержимого слота, если явно не указан <template #scoped="scopeVar">
тег, слот становится доступным как params
объект при вычислении слота.
test('scoped slots', () => {
const wrapper = mount(ComponentWithSlots, {
slots: {
scoped: `Hello {{ params.msg }}` // no wrapping template tag provided, slot scope exposed as "params"
}
})
expect(wrapper.html()).toContain('Hello world')
})
Заключение
- Используйте
slots
опцию монтирования для тестирования компонента, использующегоslot
, чтобы проверить правильность отрисовки. - Содержимое может быть либо строкой, либо функцией рендеринга или импортированным SFC.
- Используйте
default
для слота по умолчанию и корректное имя для именованных слотов. - Слоты с ограниченной областью действия и
#
сокращение также поддерживаются.