Files
platform/test-setup.ts
pastilhasandClaude Opus 5 4f8046d7e9 test useDashboardState, and fix the revert it proved was inverted
the store every dashboard layout is written through had no tests. writing them found
a live defect on its rollback: the guard asked "does the cache still hold what i wrote?"
by reference, and setQueryData runs react query's structural sharing, which rebuilds an
object rather than storing the one it was handed. verified against 5.101.4 — an object
comes back !==, a string comes back ===. so the check was false for every container the
store exists to hold: every layout, every config.agentName. a refused write kept its
optimistic value while the toast said it had been rolled back, and the change vanished at
the next reload. only primitives ever reverted, which is why it went unnoticed.

replaced with a per-key write sequence, which asks the question the identity check meant
to ask — has anything written this key since — and does not depend on identity at all.

14 tests: readValue's kind guard, the optimistic write and its updater composition, and
five on revert including the object regression pin.

also moves testing-library's cleanup into test-setup. it auto-registers afterEach at
module import time, so bun attaches it to whichever file imports the library first and
every later file silently gets none. adding this test file was enough to break fourteen
assertions in DataTable.test.tsx, which does not import it. preload has no file scope, so
registering there removes the ordering from the question.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:22:26 +00:00

54 lines
2.4 KiB
TypeScript

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);