From 1e6718e2fdca351c246f70d315dae2b314f54a09 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Fri, 10 Jul 2026 22:52:48 -0400 Subject: [PATCH] test(web): disable Mantine transition timers in the unit env MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI failed with an unhandled `ReferenceError: window is not defined` thrown from a Mantine `Transition` `setTimeout` (`use-transition.mjs`) firing after the test environment was torn down — every test passed, but the leaked timer failed the run. happy-dom has no `matchMedia`, so `useReducedMotion` resolves to "motion allowed" and every Transition (ScreenStage, Modal, …) schedules real enter/exit timers; a timer that outlives its test throws post-teardown. This surfaced now because MonitoringScreen started wrapping its screens in ScreenStage (a Transition) where it previously rendered them directly. Mock `window.matchMedia` in the test setup to report `prefers-reduced-motion: reduce`, so Mantine transitions render instantly (no timers). All other queries return `false`, matching the prior absent-matchMedia behavior, so `useMediaQuery`-driven layout is unchanged. Full unit suite passes with no unhandled errors across repeated runs. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01BrihGWcrM9JGRyu41nzZYw --- clients/web/src/test/setup.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/clients/web/src/test/setup.ts b/clients/web/src/test/setup.ts index 05defc1d..004f10a9 100644 --- a/clients/web/src/test/setup.ts +++ b/clients/web/src/test/setup.ts @@ -57,6 +57,32 @@ Object.defineProperty(globalThis, "fetch", { ), }); +// happy-dom doesn't implement `matchMedia`, so Mantine's `useReducedMotion` +// resolves to "motion allowed" and every `Transition` (ScreenStage, Modal, …) +// schedules real enter/exit `setTimeout`s. A timer that outlives its test fires +// after the environment is torn down and throws `window is not defined` from +// deep in react-dom — an unhandled error that fails the run even though every +// test passed. Report `prefers-reduced-motion: reduce` so Mantine transitions +// render instantly (no timers); all other queries stay `false`, matching the +// prior (absent-matchMedia) behavior so `useMediaQuery`-driven layout is +// unchanged. Tests that need specific media results still mock `@mantine/hooks` +// or stub `matchMedia` themselves. +Object.defineProperty(window, "matchMedia", { + configurable: true, + writable: true, + value: (query: string): MediaQueryList => + ({ + matches: /prefers-reduced-motion/.test(query), + media: query, + onchange: null, + addEventListener: () => {}, + removeEventListener: () => {}, + addListener: () => {}, + removeListener: () => {}, + dispatchEvent: () => false, + }) as unknown as MediaQueryList, +}); + afterEach(() => { cleanup(); window.localStorage.clear();