Files
multica/apps/web/test/setup.ts
2a643cc740 MUL-6291: stop paying for jsdom in pure-logic frontend suites (#7081)
MUL-6291. Vitest's own breakdown for `@multica/views` showed the shape of the
problem: environment 633s and import 644s against only 508s of actual test
execution. Two thirds of a cold frontend-test run went on building a jsdom per
file and importing its module graph, not on running assertions.

- 94 pure-logic `.test.ts` files across views/web/desktop now declare
  `// @vitest-environment node`. Measured on the 45 converted views files:
  environment 53.15s -> 4ms, wall 8.72s -> 2.03s. Candidates were picked by
  module-graph analysis (skipping type-only imports) and rejected when the code
  under test branches on `typeof window`/`document`, where node would silently
  take the SSR path and still pass; the remainder were verified empirically and
  reverted where they failed.
- The three jsdom setup files bail out when there is no DOM, so a node-env suite
  can share them.
- schedule-editor: the pure state transitions (isFullDay, displayWindow,
  timeAnchorOf, defaultAtTime, defaultEveryTime, clampWindow, toggleDay) move
  out of the component into transitions.ts, with the full combination matrix as
  a table-driven node-env suite. 34 cases in 3ms, replacing four DOM mounts.
- Cross-layer duplicates removed where a canonical layer already owns the
  matrix: originSourceUrl (skills/lib/origin.test.ts) was re-run through the
  refresh dialog and the detail page; needsSourceBackfill
  (core/onboarding/needs-backfill.test.ts) through the backfill modal. Each
  component keeps one wiring case naming the canonical file.

No behaviour change: the transitions extraction is a pure move, and every
removal names where the same contract is still covered.

Co-authored-by: Bohan-J <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-08-17 18:40:19 +08:00

54 lines
1.8 KiB
TypeScript

import "@testing-library/jest-dom/vitest";
import { vi } from "vitest";
// Everything below patches gaps in jsdom. Pure-logic suites opt out of jsdom
// with `// @vitest-environment node` and share this file, so there is no DOM to
// patch there — bail out rather than guard each stub.
if (typeof window !== "undefined") {
// jsdom doesn't provide ResizeObserver; stub it so components that rely on it
// (e.g. input-otp) can render in tests.
if (typeof globalThis.ResizeObserver === "undefined") {
globalThis.ResizeObserver = class ResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
} as unknown as typeof ResizeObserver;
}
// jsdom doesn't implement elementFromPoint; input-otp uses it internally.
if (typeof document.elementFromPoint !== "function") {
document.elementFromPoint = () => null;
}
// jsdom 29 / Node.js 22+ may not provide a proper Web Storage API.
// Create a proper localStorage mock if methods are missing.
if (
typeof globalThis.localStorage === "undefined" ||
typeof globalThis.localStorage.getItem !== "function"
) {
const store: Record<string, string> = {};
const localStorageMock = {
getItem: vi.fn((key: string) => store[key] ?? null),
setItem: vi.fn((key: string, value: string) => {
store[key] = value;
}),
removeItem: vi.fn((key: string) => {
delete store[key];
}),
clear: vi.fn(() => {
for (const key of Object.keys(store)) {
delete store[key];
}
}),
get length() {
return Object.keys(store).length;
},
key: vi.fn((index: number) => Object.keys(store)[index] ?? null),
};
Object.defineProperty(globalThis, "localStorage", {
value: localStorageMock,
writable: true,
});
}
}