test: test nested suspense & nested async deps

This commit is contained in:
Evan You
2019-09-11 23:44:37 -04:00
parent bbc3442c52
commit b30b17d22d
4 changed files with 281 additions and 6 deletions

View File

@@ -105,6 +105,53 @@ describe('renderer: suspense', () => {
expect(serializeInner(root)).toBe(`<div>async</div>`)
})
test('nested async deps', async () => {
const calls: string[] = []
const AsyncOuter = createAsyncComponent({
setup() {
onMounted(() => {
calls.push('outer mounted')
})
return () => h(AsyncInner)
}
})
const AsyncInner = createAsyncComponent(
{
setup() {
onMounted(() => {
calls.push('inner mounted')
})
return () => h('div', 'inner')
}
},
10
)
const Comp = {
setup() {
return () =>
h(Suspense, null, {
default: h(AsyncOuter),
fallback: h('div', 'fallback')
})
}
}
const root = nodeOps.createElement('div')
render(h(Comp), root)
expect(serializeInner(root)).toBe(`<div>fallback</div>`)
await deps[0]
await nextTick()
expect(serializeInner(root)).toBe(`<div>fallback</div>`)
await Promise.all(deps)
await nextTick()
expect(serializeInner(root)).toBe(`<div>inner</div>`)
})
test('onResolve', async () => {
const Async = createAsyncComponent({
render() {
@@ -286,15 +333,219 @@ describe('renderer: suspense', () => {
expect(calls).toEqual([])
})
test('unmount suspense after resolve', () => {})
test('unmount suspense after resolve', async () => {
const toggle = ref(true)
const unmounted = jest.fn()
test.todo('unmount suspense before resolve')
const Async = createAsyncComponent({
setup() {
onUnmounted(unmounted)
return () => h('div', 'async')
}
})
test.todo('nested suspense')
const Comp = {
setup() {
return () =>
toggle.value
? h(Suspense, null, {
default: h(Async),
fallback: h('div', 'fallback')
})
: null
}
}
test.todo('new async dep after resolve should cause suspense to restart')
const root = nodeOps.createElement('div')
render(h(Comp), root)
expect(serializeInner(root)).toBe(`<div>fallback</div>`)
await Promise.all(deps)
await nextTick()
expect(serializeInner(root)).toBe(`<div>async</div>`)
expect(unmounted).not.toHaveBeenCalled()
toggle.value = false
await nextTick()
expect(serializeInner(root)).toBe(`<!---->`)
expect(unmounted).toHaveBeenCalled()
})
test('unmount suspense before resolve', async () => {
const toggle = ref(true)
const mounted = jest.fn()
const unmounted = jest.fn()
const Async = createAsyncComponent({
setup() {
onMounted(mounted)
onUnmounted(unmounted)
return () => h('div', 'async')
}
})
const Comp = {
setup() {
return () =>
toggle.value
? h(Suspense, null, {
default: h(Async),
fallback: h('div', 'fallback')
})
: null
}
}
const root = nodeOps.createElement('div')
render(h(Comp), root)
expect(serializeInner(root)).toBe(`<div>fallback</div>`)
toggle.value = false
await nextTick()
expect(serializeInner(root)).toBe(`<!---->`)
expect(mounted).not.toHaveBeenCalled()
expect(unmounted).not.toHaveBeenCalled()
await Promise.all(deps)
await nextTick()
// should not resolve and cause unmount
expect(mounted).not.toHaveBeenCalled()
expect(unmounted).not.toHaveBeenCalled()
})
test('nested suspense (parent resolves first)', async () => {
const calls: string[] = []
const AsyncOuter = createAsyncComponent(
{
setup: () => {
onMounted(() => {
calls.push('outer mounted')
})
return () => h('div', 'async outer')
}
},
1
)
const AsyncInner = createAsyncComponent(
{
setup: () => {
onMounted(() => {
calls.push('inner mounted')
})
return () => h('div', 'async inner')
}
},
10
)
const Inner = {
setup() {
return () =>
h(Suspense, null, {
default: h(AsyncInner),
fallback: h('div', 'fallback inner')
})
}
}
const Comp = {
setup() {
return () =>
h(Suspense, null, {
default: [h(AsyncOuter), h(Inner)],
fallback: h('div', 'fallback outer')
})
}
}
const root = nodeOps.createElement('div')
render(h(Comp), root)
expect(serializeInner(root)).toBe(`<div>fallback outer</div>`)
await deps[0]
await nextTick()
expect(serializeInner(root)).toBe(
`<!----><div>async outer</div><div>fallback inner</div><!---->`
)
expect(calls).toEqual([`outer mounted`])
await Promise.all(deps)
await nextTick()
expect(serializeInner(root)).toBe(
`<!----><div>async outer</div><div>async inner</div><!---->`
)
expect(calls).toEqual([`outer mounted`, `inner mounted`])
})
test('nested suspense (child resolves first)', async () => {
const calls: string[] = []
const AsyncOuter = createAsyncComponent(
{
setup: () => {
onMounted(() => {
calls.push('outer mounted')
})
return () => h('div', 'async outer')
}
},
10
)
const AsyncInner = createAsyncComponent(
{
setup: () => {
onMounted(() => {
calls.push('inner mounted')
})
return () => h('div', 'async inner')
}
},
1
)
const Inner = {
setup() {
return () =>
h(Suspense, null, {
default: h(AsyncInner),
fallback: h('div', 'fallback inner')
})
}
}
const Comp = {
setup() {
return () =>
h(Suspense, null, {
default: [h(AsyncOuter), h(Inner)],
fallback: h('div', 'fallback outer')
})
}
}
const root = nodeOps.createElement('div')
render(h(Comp), root)
expect(serializeInner(root)).toBe(`<div>fallback outer</div>`)
await deps[1]
await nextTick()
expect(serializeInner(root)).toBe(`<div>fallback outer</div>`)
expect(calls).toEqual([])
await Promise.all(deps)
await nextTick()
expect(serializeInner(root)).toBe(
`<!----><div>async outer</div><div>async inner</div><!---->`
)
expect(calls).toEqual([`inner mounted`, `outer mounted`])
})
test.todo('error handling')
test.todo('new async dep after resolve should cause suspense to restart')
test.todo('portal inside suspense')
})