import { afterEach } from 'bun:test'; import { GlobalWindow } from 'happy-dom'; const window = new GlobalWindow(); // Copy window properties to globalThis Object.assign(globalThis, { window, document: window.document, navigator: window.navigator, location: window.location, history: window.history, // Several modules read storage at import time, so this must exist before the first import, not first render. localStorage: window.localStorage, sessionStorage: window.sessionStorage, HTMLElement: window.HTMLElement, Element: window.Element, Node: window.Node, Event: window.Event, CustomEvent: window.CustomEvent, MouseEvent: window.MouseEvent, KeyboardEvent: window.KeyboardEvent, InputEvent: window.InputEvent, FocusEvent: window.FocusEvent, DocumentFragment: window.DocumentFragment, MutationObserver: window.MutationObserver, ResizeObserver: window.ResizeObserver, getComputedStyle: window.getComputedStyle.bind(window), requestAnimationFrame: window.requestAnimationFrame.bind(window), cancelAnimationFrame: window.cancelAnimationFrame.bind(window), setTimeout: window.setTimeout.bind(window), clearTimeout: window.clearTimeout.bind(window), setInterval: window.setInterval.bind(window), clearInterval: window.clearInterval.bind(window), }); /** * Unmount every rendered tree between tests — globally, because the library's own version of this is * order-dependent in a way that produces a bewildering failure. * * `@testing-library/react` auto-registers `afterEach(cleanup)` at *module import* time. Bun evaluates a * module once and attaches lifecycle hooks to whichever file is loading at that moment, so the file that * happens to import the library first gets the cleanup and every later file silently gets none — its * renders pile up in `document.body` and the next `screen.getAllByRole` sees the previous test's DOM. * Adding one test file was enough to break fourteen assertions in a file it does not import, does not * touch, and was passing on its own. * * Registering it here removes the ordering from the question: preload has no enclosing file scope, so this * hook is global. The dynamic import is deliberate — `@testing-library/dom` builds `screen` from * `document.body` while it initialises, so it must not load until the happy-dom globals above exist. */ const { cleanup } = await import('@testing-library/react'); afterEach(cleanup);