mirror of
https://gh-proxy.org/https://github.com/klinsmaya/multica.git
synced 2026-11-09 01:46:46 +08:00
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]>
61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
import "@testing-library/jest-dom/vitest";
|
|
|
|
function createMemoryStorage(): Storage {
|
|
const values = new Map<string, string>();
|
|
|
|
return {
|
|
get length() {
|
|
return values.size;
|
|
},
|
|
clear: () => values.clear(),
|
|
getItem: (key: string) => values.get(key) ?? null,
|
|
key: (index: number) => Array.from(values.keys())[index] ?? null,
|
|
removeItem: (key: string) => {
|
|
values.delete(key);
|
|
},
|
|
setItem: (key: string, value: string) => {
|
|
values.set(key, value);
|
|
},
|
|
};
|
|
}
|
|
|
|
// 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") {
|
|
const localStorageIsUsable =
|
|
typeof globalThis.localStorage?.getItem === "function" &&
|
|
typeof globalThis.localStorage?.setItem === "function" &&
|
|
typeof globalThis.localStorage?.removeItem === "function" &&
|
|
typeof globalThis.localStorage?.clear === "function";
|
|
|
|
if (!localStorageIsUsable) {
|
|
const storage = createMemoryStorage();
|
|
Object.defineProperty(globalThis, "localStorage", {
|
|
configurable: true,
|
|
value: storage,
|
|
});
|
|
Object.defineProperty(window, "localStorage", {
|
|
configurable: true,
|
|
value: storage,
|
|
});
|
|
}
|
|
|
|
// jsdom doesn't provide matchMedia; the sidebar's compact breakpoint and
|
|
// auto-collapse band both read it. Nothing matches, so a shell mounted here
|
|
// renders at its full desktop width. Mirrors packages/views/test/setup.ts.
|
|
if (typeof window.matchMedia !== "function") {
|
|
window.matchMedia = (query: string) =>
|
|
({
|
|
matches: false,
|
|
media: query,
|
|
onchange: null,
|
|
addListener: () => {},
|
|
removeListener: () => {},
|
|
addEventListener: () => {},
|
|
removeEventListener: () => {},
|
|
dispatchEvent: () => false,
|
|
}) as MediaQueryList;
|
|
}
|
|
}
|