import "@testing-library/jest-dom/vitest"; import { cleanup } from "@testing-library/react"; import { afterEach, vi } from "vitest"; import { clearIntersectionObservers, installIntersectionObserverStub, } from "./src/test/intersection"; // Testing Library's own auto-cleanup only runs when it detects a global `afterEach`, // which it does under Vitest - but registering it explicitly means a component test // that forgets `render` isolation still can't leak DOM into the next one. afterEach(cleanup); // jsdom implements neither, and Base UI (dialogs, selects, popovers) and the app's own // responsive hooks both reach for them on mount. Without these, every test that // renders a dialog throws before it reaches its assertion. Object.defineProperty(window, "matchMedia", { writable: true, value: (query: string) => ({ matches: false, media: query, onchange: null, addListener: vi.fn(), removeListener: vi.fn(), addEventListener: vi.fn(), removeEventListener: vi.fn(), dispatchEvent: vi.fn(), }), }); window.ResizeObserver = class { observe() {} unobserve() {} disconnect() {} }; // Same reason, one layer up: `LoadMoreTrigger` observes its button so a list // pulls its next page in as the diver scrolls, and `new IntersectionObserver` // throws outright in jsdom. The stub reports nothing until a test says the // reader has scrolled there - see `src/test/intersection.ts` for why that is the // honest default and how to ask for the other answer. installIntersectionObserverStub(); afterEach(clearIntersectionObservers); // Popup positioning measures with these; jsdom reports zeroes and warns without them. Element.prototype.scrollIntoView = vi.fn(); // The calendar's swipe captures the pointer once a drag passes its threshold, and // jsdom implements none of the three, so a test swiping it would throw. Element.prototype.hasPointerCapture = () => false; Element.prototype.setPointerCapture = () => {}; Element.prototype.releasePointerCapture = () => {};