Skip to content

Commit 9bbab23

Browse files
committed
fix tests and implementation
1 parent c1ac6d0 commit 9bbab23

File tree

3 files changed

+137
-9
lines changed

3 files changed

+137
-9
lines changed

packages/runtime-core/__tests__/components/Suspense.spec.ts

Lines changed: 114 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,7 @@ describe('Suspense', () => {
15301530
})
15311531

15321532
// #5844
1533-
test('Suspense + Transition', async () => {
1533+
test('Suspense + Transition HTML DOM', async () => {
15341534
const InnerA = defineComponent({
15351535
setup: () => {
15361536
const el = ref<HTMLDivElement | null>(null)
@@ -1577,7 +1577,8 @@ describe('Suspense', () => {
15771577
Transition,
15781578
{
15791579
name: 'page',
1580-
mode: 'out-in'
1580+
mode: 'out-in',
1581+
duration: 1
15811582
},
15821583
{
15831584
default: () => [
@@ -1601,15 +1602,120 @@ describe('Suspense', () => {
16011602
const root = document.createElement('div')
16021603
try {
16031604
document.body.appendChild(root)
1604-
renderDOM(h(Comp), document.body)
1605-
outerToggle.value = true
1606-
await nextTick()
1605+
renderDOM(h(Comp), root)
1606+
expect(document.body.innerHTML).toContain('innerA')
16071607

1608+
outerToggle.value = true
1609+
// give some time for the transition to finish
1610+
await new Promise(r => setTimeout(r, 100))
1611+
expect(document.body.innerHTML).toContain('innerB')
16081612
outerToggle.value = false
1609-
// delay it more to error from happening on the CI
1610-
await new Promise(r => setTimeout(r, 10))
1613+
// give some time for the transition to finish
1614+
await new Promise(r => setTimeout(r, 100))
1615+
expect(document.body.innerHTML).toContain('innerA')
1616+
1617+
outerToggle.value = true
1618+
1619+
// give some time for the transition to finish
1620+
await new Promise(r => setTimeout(r, 100))
1621+
expect(document.body.innerHTML).toContain('innerB')
16111622
} finally {
1612-
document.body.innerHTML = ''
1623+
document.body.removeChild(root)
16131624
}
16141625
})
1626+
1627+
// #5844
1628+
test('Suspense + Transition', async () => {
1629+
const expectInnerA = '<div id="innerA">innerA</div>'
1630+
const expectInnerB = '<div id="innerB">innerB</div>'
1631+
1632+
const InnerA = defineComponent({
1633+
setup: () => {
1634+
const el = ref<HTMLDivElement | null>(null)
1635+
onMounted(() => {
1636+
expect(el.value).toBeTruthy()
1637+
expect(serializeInner(root)).toBe(expectInnerA)
1638+
})
1639+
return () =>
1640+
h(
1641+
'div',
1642+
{
1643+
ref: el,
1644+
id: 'innerA'
1645+
},
1646+
'innerA'
1647+
)
1648+
}
1649+
})
1650+
1651+
const InnerB = defineComponent({
1652+
setup: () => {
1653+
const el = ref<HTMLDivElement | null>(null)
1654+
onMounted(() => {
1655+
expect(el.value).toBeTruthy()
1656+
console.log('inner b', serializeInner(root))
1657+
expect(serializeInner(root)).toBe(expectInnerB)
1658+
})
1659+
return () =>
1660+
h(
1661+
'div',
1662+
{
1663+
ref: el,
1664+
id: 'innerB'
1665+
},
1666+
'innerB'
1667+
)
1668+
}
1669+
})
1670+
const outerToggle = ref(false)
1671+
1672+
const Comp = defineComponent({
1673+
setup() {
1674+
return () =>
1675+
h(
1676+
Transition,
1677+
{
1678+
name: 'page',
1679+
mode: 'out-in',
1680+
duration: 1
1681+
},
1682+
{
1683+
default: () => [
1684+
h(Suspense, null, {
1685+
default: [
1686+
outerToggle.value
1687+
? h(InnerB, {
1688+
key: 1
1689+
})
1690+
: h(InnerA, {
1691+
key: 2
1692+
})
1693+
]
1694+
})
1695+
]
1696+
}
1697+
)
1698+
}
1699+
})
1700+
1701+
const root = nodeOps.createElement('div')
1702+
render(h(Comp), root)
1703+
expect(serializeInner(root)).toBe(expectInnerA)
1704+
1705+
outerToggle.value = true
1706+
// give some time for the transition to finish
1707+
await new Promise(r => setTimeout(r, 100))
1708+
expect(serializeInner(root)).toContain('innerB')
1709+
outerToggle.value = false
1710+
// give some time for the transition to finish
1711+
await new Promise(r => setTimeout(r, 100))
1712+
expect(serializeInner(root)).toContain('innerA')
1713+
1714+
outerToggle.value = true
1715+
1716+
// give some time for the transition to finish
1717+
await new Promise(r => setTimeout(r, 100))
1718+
expect(serializeInner(root)).toContain('innerB')
1719+
// }
1720+
})
16151721
})

packages/runtime-core/src/components/BaseTransition.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,20 @@ export function getTransitionRawChildren(
511511
getTransitionRawChildren(child.children as VNode[], keepComment, key)
512512
)
513513
}
514+
// #5844 suspense children should be able to transition
515+
else if (child.shapeFlag & ShapeFlags.SUSPENSE) {
516+
ret = ret.concat(
517+
getTransitionRawChildren(
518+
Array.isArray(child.children)
519+
? (child.children as VNode[])
520+
: typeof child.children === 'object'
521+
? (child.children?.default as VNode[])
522+
: [],
523+
keepComment,
524+
key
525+
)
526+
)
527+
}
514528
// comment placeholders should be skipped, e.g. v-if
515529
else if (keepComment || child.type !== Comment) {
516530
ret.push(key != null ? cloneVNode(child, { key }) : child)

packages/runtime-test/src/nodeOps.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ export interface TestElement {
2323
children: TestNode[]
2424
props: Record<string, any>
2525
eventListeners: Record<string, Function | Function[]> | null
26+
classList: {
27+
add: (c: string) => void
28+
remove: (c: string) => void
29+
}
2630
}
2731

2832
export interface TestText {
@@ -79,7 +83,11 @@ function createElement(tag: string): TestElement {
7983
children: [],
8084
props: {},
8185
parentNode: null,
82-
eventListeners: null
86+
eventListeners: null,
87+
classList: {
88+
add(c: string) {},
89+
remove(c: string) {}
90+
}
8391
}
8492
logNodeOp({
8593
type: NodeOpTypes.CREATE,

0 commit comments

Comments
 (0)