/** * happy-dom polyfills tailored for `@suaveplan/react-ui` tests. * * happy-dom (catalog:testing) provides a reasonably complete DOM, but a * handful of browser globals that the chassis touches are either missing * or ship stub implementations: * * - `matchMedia` — `useMobile` and the FOUC inline script both poll * `prefers-color-scheme` / `prefers-reduced-motion` / max-width queries * via `window.matchMedia`. happy-dom includes a partial implementation; * we install a controllable wrapper so individual tests can flip the * stored result. * - `ResizeObserver` / `IntersectionObserver` — Radix UI primitives we * re-export call these in their effect setup. happy-dom returns * `undefined` for both. We polyfill with no-op classes so component * mounts do not throw during render. * * The polyfills are idempotent: if `globalThis` already exposes a * functional implementation, we leave it alone. */ interface MatchMediaState { readonly matches: boolean; readonly media: string; } class FakeMediaQueryList { public readonly matches: boolean; public readonly media: string; private readonly listeners = new Set<(ev: MatchMediaState) => void>(); public constructor(media: string, matches: boolean) { this.media = media; this.matches = matches; } public addEventListener( _evt: string, listener: (ev: MatchMediaState) => void ): void { this.listeners.add(listener); } public removeEventListener( _evt: string, listener: (ev: MatchMediaState) => void ): void { this.listeners.delete(listener); } /** Legacy alias used by some libraries. */ public addListener(listener: (ev: MatchMediaState) => void): void { this.listeners.add(listener); } public removeListener(listener: (ev: MatchMediaState) => void): void { this.listeners.delete(listener); } public dispatchEvent(): boolean { return true; } } declare global { interface Window { __reactUiMatchMediaResult?: (query: string) => boolean; } } if (typeof globalThis.window !== "undefined") { if (typeof globalThis.window.matchMedia !== "function") { globalThis.window.matchMedia = ((query: string) => { const evaluator = (globalThis.window.__reactUiMatchMediaResult ?? (() => false)) as (q: string) => boolean; return new FakeMediaQueryList(query, evaluator(query)); }) as Window["matchMedia"]; } if (typeof globalThis.ResizeObserver === "undefined") { globalThis.ResizeObserver = class FakeResizeObserver { public observe(): void {} public unobserve(): void {} public disconnect(): void {} } as unknown as typeof ResizeObserver; } if (typeof globalThis.IntersectionObserver === "undefined") { globalThis.IntersectionObserver = class FakeIntersectionObserver { public readonly root: Element | null = null; public readonly rootMargin: string = "0px"; public readonly thresholds: readonly number[] = []; public observe(): void {} public unobserve(): void {} public disconnect(): void {} public takeRecords(): readonly IntersectionObserverEntry[] { return []; } } as unknown as typeof IntersectionObserver; } }