insert,
prepend,
renderEffect,
+ setInsertionState,
template,
} from '../src'
-import { currentInstance, nextTick, ref } from '@vue/runtime-dom'
+import {
+ currentInstance,
+ nextTick,
+ ref,
+ toDisplayString,
+} from '@vue/runtime-dom'
import { makeRender } from './_utils'
import type { DynamicSlot } from '../src/componentSlots'
-import { setElementText } from '../src/dom/prop'
+import { setElementText, setText } from '../src/dom/prop'
const define = makeRender<any>()
expect(host.innerHTML).toBe('<div><h1></h1><!--slot--></div>')
})
+ test('consecutive slots with insertion state', async () => {
+ const { component: Child } = define({
+ setup() {
+ const n2 = template('<div><div>baz</div></div>', true)() as any
+ setInsertionState(n2, 0)
+ createSlot('default', null)
+ setInsertionState(n2, 0)
+ createSlot('foo', null)
+ return n2
+ },
+ })
+
+ const { html } = define({
+ setup() {
+ return createComponent(Child, null, {
+ default: () => template('default')(),
+ foo: () => template('foo')(),
+ })
+ },
+ }).render()
+
+ expect(html()).toBe(
+ `<div>` +
+ `default<!--slot-->` +
+ `foo<!--slot-->` +
+ `<div>baz</div>` +
+ `</div>`,
+ )
+ })
++
+ test('render fallback when slot content is not valid', async () => {
+ const Child = {
+ setup() {
+ return createSlot('default', null, () =>
+ document.createTextNode('fallback'),
+ )
+ },
+ }
+
+ const { html } = define({
+ setup() {
+ return createComponent(Child, null, {
+ default: () => {
+ return template('<!--comment-->')()
+ },
+ })
+ },
+ }).render()
+
+ expect(html()).toBe('fallback<!--slot-->')
+ })
+
+ test('render fallback when v-if condition is false', async () => {
+ const Child = {
+ setup() {
+ return createSlot('default', null, () =>
+ document.createTextNode('fallback'),
+ )
+ },
+ }
+
+ const toggle = ref(false)
+
+ const { html } = define({
+ setup() {
+ return createComponent(Child, null, {
+ default: () => {
+ return createIf(
+ () => toggle.value,
+ () => {
+ return document.createTextNode('content')
+ },
+ )
+ },
+ })
+ },
+ }).render()
+
+ expect(html()).toBe('fallback<!--if--><!--slot-->')
+
+ toggle.value = true
+ await nextTick()
+ expect(html()).toBe('content<!--if--><!--slot-->')
+
+ toggle.value = false
+ await nextTick()
+ expect(html()).toBe('fallback<!--if--><!--slot-->')
+ })
+
+ test('render fallback with nested v-if', async () => {
+ const Child = {
+ setup() {
+ return createSlot('default', null, () =>
+ document.createTextNode('fallback'),
+ )
+ },
+ }
+
+ const outerShow = ref(false)
+ const innerShow = ref(false)
+
+ const { html } = define({
+ setup() {
+ return createComponent(Child, null, {
+ default: () => {
+ return createIf(
+ () => outerShow.value,
+ () => {
+ return createIf(
+ () => innerShow.value,
+ () => {
+ return document.createTextNode('content')
+ },
+ )
+ },
+ )
+ },
+ })
+ },
+ }).render()
+
+ expect(html()).toBe('fallback<!--if--><!--slot-->')
+
+ outerShow.value = true
+ await nextTick()
+ expect(html()).toBe('fallback<!--if--><!--if--><!--slot-->')
+
+ innerShow.value = true
+ await nextTick()
+ expect(html()).toBe('content<!--if--><!--if--><!--slot-->')
+
+ innerShow.value = false
+ await nextTick()
+ expect(html()).toBe('fallback<!--if--><!--if--><!--slot-->')
+
+ outerShow.value = false
+ await nextTick()
+ expect(html()).toBe('fallback<!--if--><!--slot-->')
+
+ outerShow.value = true
+ await nextTick()
+ expect(html()).toBe('fallback<!--if--><!--if--><!--slot-->')
+
+ innerShow.value = true
+ await nextTick()
+ expect(html()).toBe('content<!--if--><!--if--><!--slot-->')
+ })
+
+ test('render fallback with v-for', async () => {
+ const Child = {
+ setup() {
+ return createSlot('default', null, () =>
+ document.createTextNode('fallback'),
+ )
+ },
+ }
+
+ const items = ref<number[]>([1])
+ const { html } = define({
+ setup() {
+ return createComponent(Child, null, {
+ default: () => {
+ const n2 = createFor(
+ () => items.value,
+ for_item0 => {
+ const n4 = template('<span> </span>')() as any
+ const x4 = child(n4) as any
+ renderEffect(() =>
+ setText(x4, toDisplayString(for_item0.value)),
+ )
+ return n4
+ },
+ )
+ return n2
+ },
+ })
+ },
+ }).render()
+
+ expect(html()).toBe('<span>1</span><!--for--><!--slot-->')
+
+ items.value.pop()
+ await nextTick()
+ expect(html()).toBe('fallback<!--for--><!--slot-->')
+
+ items.value.pop()
+ await nextTick()
+ expect(html()).toBe('fallback<!--for--><!--slot-->')
+
+ items.value.push(2)
+ await nextTick()
+ expect(html()).toBe('<span>2</span><!--for--><!--slot-->')
+ })
+
+ test('render fallback with v-for (empty source)', async () => {
+ const Child = {
+ setup() {
+ return createSlot('default', null, () =>
+ document.createTextNode('fallback'),
+ )
+ },
+ }
+
+ const items = ref<number[]>([])
+ const { html } = define({
+ setup() {
+ return createComponent(Child, null, {
+ default: () => {
+ const n2 = createFor(
+ () => items.value,
+ for_item0 => {
+ const n4 = template('<span> </span>')() as any
+ const x4 = child(n4) as any
+ renderEffect(() =>
+ setText(x4, toDisplayString(for_item0.value)),
+ )
+ return n4
+ },
+ )
+ return n2
+ },
+ })
+ },
+ }).render()
+
+ expect(html()).toBe('fallback<!--for--><!--slot-->')
+
+ items.value.push(1)
+ await nextTick()
+ expect(html()).toBe('<span>1</span><!--for--><!--slot-->')
+
+ items.value.pop()
+ await nextTick()
+ expect(html()).toBe('fallback<!--for--><!--slot-->')
+
+ items.value.pop()
+ await nextTick()
+ expect(html()).toBe('fallback<!--for--><!--slot-->')
+
+ items.value.push(2)
+ await nextTick()
+ expect(html()).toBe('<span>2</span><!--for--><!--slot-->')
+ })
})
})