mirror of https://github.com/usememos/memos
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
3.2 KiB
TypeScript
84 lines
3.2 KiB
TypeScript
import "@testing-library/jest-dom/vitest";
|
|
import { cleanup } from "@testing-library/react";
|
|
import { afterEach } from "vitest";
|
|
|
|
// With `globals: false`, @testing-library/react does not auto-register a
|
|
// cleanup hook, so unmount rendered trees between tests explicitly. This keeps
|
|
// `screen.getByTestId` from seeing DOM from prior tests in the same file.
|
|
afterEach(() => {
|
|
cleanup();
|
|
});
|
|
|
|
// ProseMirror probes layout APIs jsdom doesn't implement.
|
|
if (typeof document !== "undefined") {
|
|
if (!document.elementFromPoint) {
|
|
document.elementFromPoint = () => null;
|
|
}
|
|
if (typeof Range !== "undefined" && !Range.prototype.getClientRects) {
|
|
Range.prototype.getClientRects = () => [] as unknown as DOMRectList;
|
|
Range.prototype.getBoundingClientRect = () =>
|
|
({ x: 0, y: 0, top: 0, left: 0, bottom: 0, right: 0, width: 0, height: 0, toJSON: () => ({}) }) as DOMRect;
|
|
}
|
|
// CodeMirror probes additional layout APIs jsdom doesn't implement while measuring.
|
|
if (typeof Element !== "undefined" && !Element.prototype.getClientRects) {
|
|
Element.prototype.getClientRects = () => [] as unknown as DOMRectList;
|
|
}
|
|
}
|
|
|
|
// jsdom runs with an opaque origin (no URL set), so its built-in localStorage
|
|
// implementation throws SecurityError on every access. Install a Map-backed shim
|
|
// so any test that touches localStorage directly can call getItem/setItem/removeItem/clear
|
|
// without additional per-file setup. Tests that need special behavior (hooks.test.tsx,
|
|
// memo-editor-cache.test.ts) override this via Object.defineProperty / vi.stubGlobal.
|
|
if (typeof globalThis.localStorage === "undefined" || typeof globalThis.localStorage.clear !== "function") {
|
|
let _store = new Map<string, string>();
|
|
const localStorageShim: Storage = {
|
|
get length() {
|
|
return _store.size;
|
|
},
|
|
getItem: (key: string) => _store.get(key) ?? null,
|
|
setItem: (key: string, value: string) => _store.set(key, value),
|
|
removeItem: (key: string) => _store.delete(key),
|
|
clear: () => {
|
|
_store = new Map<string, string>();
|
|
},
|
|
key: (index: number) => Array.from(_store.keys())[index] ?? null,
|
|
};
|
|
Object.defineProperty(globalThis, "localStorage", {
|
|
configurable: true,
|
|
value: localStorageShim,
|
|
});
|
|
}
|
|
|
|
// Defensive shim: `@/auth-state` constructs a BroadcastChannel at module load
|
|
// to coordinate token refreshes across tabs. jsdom historically has not shipped
|
|
// BroadcastChannel, so any future test that transitively imports auth-state
|
|
// would otherwise throw. Current tests avoid that import path on purpose, but
|
|
// installing the shim keeps authoring new tests frictionless. No-op when jsdom
|
|
// already provides an implementation.
|
|
if (typeof globalThis.BroadcastChannel === "undefined") {
|
|
class NoopBroadcastChannel {
|
|
readonly name: string;
|
|
onmessage: ((event: MessageEvent) => void) | null = null;
|
|
|
|
constructor(name: string) {
|
|
this.name = name;
|
|
}
|
|
|
|
postMessage(_data: unknown): void {}
|
|
|
|
close(): void {}
|
|
|
|
addEventListener(): void {}
|
|
|
|
removeEventListener(): void {}
|
|
|
|
dispatchEvent(): boolean {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// @ts-expect-error — attach the shim to the global scope for tests.
|
|
globalThis.BroadcastChannel = NoopBroadcastChannel;
|
|
}
|