File size: 1,290 Bytes
a1b6014 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import { act, type ReactNode } from 'react'
import { createRoot, type Root } from 'react-dom/client'
/** A React root in a container attached to the document, for the handful of
* suites that cannot use Testing Library's `render`.
*
* They need the component mounted in the real document — a canvas that must
* paint, an element measured by its parent, a portal that reads
* `document.body` — and they need to unmount inside `act` mid-test to assert
* on teardown. Cleanup is idempotent so `afterEach` can call it after a test
* already did. */
export function reactRoot() {
let root: Root | null = null
let container: HTMLDivElement | null = null
return {
get container() {
return container
},
/** The root itself, for a re-render that has to share an `act` with
* something else — a mutation-observer callback, a timer flush. */
get root() {
return root
},
render(ui: ReactNode) {
container = document.createElement('div')
document.body.append(container)
root = createRoot(container)
act(() => {
root!.render(ui)
})
},
unmount() {
if (root) {
act(() => root!.unmount())
}
container?.remove()
root = null
container = null
}
}
}
|