Compare commits

2 Commits

Author SHA1 Message Date
Kristaps Fabians Geikins 048db8c65b test fix 2025-06-20 17:24:57 +03:00
Kristaps Fabians Geikins 415fca4383 fix: skip deleting portal root node to avoid race condition 2025-06-20 17:22:32 +03:00
2 changed files with 1 additions and 83 deletions
@@ -167,76 +167,6 @@ it('should be possible to use multiple Portal elements', async () => {
expect(content2).toHaveTextContent('Contents 2 ...') expect(content2).toHaveTextContent('Contents 2 ...')
}) })
it('should cleanup the Portal root when the last Portal is unmounted', async () => {
expect(getPortalRoot()).toBe(null)
renderTemplate({
template: html`
<main id="parent">
<button id="a" @click="toggleA">Toggle A</button>
<button id="b" @click="toggleB">Toggle B</button>
<Portal v-if="renderA">
<p id="content1">Contents 1 ...</p>
</Portal>
<Portal v-if="renderB">
<p id="content2">Contents 2 ...</p>
</Portal>
</main>
`,
setup() {
let renderA = ref(false)
let renderB = ref(false)
return {
renderA,
renderB,
toggleA() {
renderA.value = !renderA.value
},
toggleB() {
renderB.value = !renderB.value
},
}
},
})
let a = document.getElementById('a')
let b = document.getElementById('b')
expect(getPortalRoot()).toBe(null)
// Let's render the first Portal
await click(a)
expect(getPortalRoot()).not.toBe(null)
expect(getPortalRoot().children).toHaveLength(1)
// Let's render the second Portal
await click(b)
expect(getPortalRoot()).not.toBe(null)
expect(getPortalRoot().children).toHaveLength(2)
// Let's remove the first portal
await click(a)
expect(getPortalRoot()).not.toBe(null)
expect(getPortalRoot().children).toHaveLength(1)
// Let's remove the second Portal
await click(b)
expect(getPortalRoot()).toBe(null)
// Let's render the first Portal again
await click(a)
expect(getPortalRoot()).not.toBe(null)
expect(getPortalRoot().children).toHaveLength(1)
})
it('should be possible to render multiple portals at the same time', async () => { it('should be possible to render multiple portals at the same time', async () => {
expect(getPortalRoot()).toBe(null) expect(getPortalRoot()).toBe(null)
@@ -311,7 +241,7 @@ it('should be possible to render multiple portals at the same time', async () =>
// Remove Portal 1 // Remove Portal 1
await click(document.getElementById('a')) await click(document.getElementById('a'))
expect(getPortalRoot()).toBe(null) expect(getPortalRoot().children).toHaveLength(0)
// Render A and B at the same time! // Render A and B at the same time!
await click(document.getElementById('double')) await click(document.getElementById('double'))
@@ -1,6 +1,5 @@
import { import {
Teleport, Teleport,
computed,
defineComponent, defineComponent,
getCurrentInstance, getCurrentInstance,
h, h,
@@ -51,7 +50,6 @@ export let Portal = defineComponent({
}, },
setup(props, { slots, attrs }) { setup(props, { slots, attrs }) {
let element = ref<HTMLElement | null>(null) let element = ref<HTMLElement | null>(null)
let ownerDocument = computed(() => getOwnerDocument(element))
let forcePortalRoot = usePortalRoot() let forcePortalRoot = usePortalRoot()
let groupContext = inject(PortalGroupContext, null) let groupContext = inject(PortalGroupContext, null)
@@ -90,16 +88,6 @@ export let Portal = defineComponent({
didRegister = true didRegister = true
}) })
onUnmounted(() => {
let root = ownerDocument.value?.getElementById('headlessui-portal-root')
if (!root) return
if (myTarget.value !== root) return
if (myTarget.value.children.length <= 0) {
myTarget.value.parentElement?.removeChild(myTarget.value)
}
})
return () => { return () => {
if (!ready.value) return null if (!ready.value) return null
if (myTarget.value === null) return null if (myTarget.value === null) return null