excalidraw/setupTests.ts

119 lines
3.1 KiB
TypeScript

// vitest.setup.ts
import "vitest-canvas-mock";
import "@testing-library/jest-dom";
import fs from "fs";
import { vi } from "vitest";
import polyfill from "./packages/excalidraw/polyfill";
import { testPolyfills } from "./packages/excalidraw/tests/helpers/polyfills";
import { yellow } from "./packages/excalidraw/tests/helpers/colorize";
Object.assign(globalThis, testPolyfills);
require("fake-indexeddb/auto");
polyfill();
Object.defineProperty(window, "matchMedia", {
writable: true,
value: vi.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: vi.fn(), // deprecated
removeListener: vi.fn(), // deprecated
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn(),
})),
});
Object.defineProperty(window, "FontFace", {
enumerable: true,
value: class {
private family: string;
private source: string;
private descriptors: any;
private status: string;
constructor(family, source, descriptors) {
this.family = family;
this.source = source;
this.descriptors = descriptors;
this.status = "unloaded";
}
load() {
this.status = "loaded";
}
},
});
Object.defineProperty(document, "fonts", {
value: {
load: vi.fn().mockResolvedValue([]),
check: vi.fn().mockResolvedValue(true),
has: vi.fn().mockResolvedValue(true),
add: vi.fn(),
},
});
Object.defineProperty(window, "EXCALIDRAW_ASSET_PATH", {
value: `file://${__dirname}/`,
});
vi.mock(
"./packages/excalidraw/fonts/ExcalidrawFont",
async (importOriginal) => {
const mod = await importOriginal<
typeof import("./packages/excalidraw/fonts/ExcalidrawFont")
>();
const ExcalidrawFontImpl = mod.ExcalidrawFont;
return {
...mod,
ExcalidrawFont: class extends ExcalidrawFontImpl {
public async getContent(): Promise<string> {
const url = this.urls[0];
if (url.protocol !== "file:") {
return super.getContent(new Set());
}
// read local assets directly, without running a server
const content = await fs.promises.readFile(url);
return `data:font/woff2;base64,${content.toString("base64")}`;
}
},
};
},
);
vi.mock("nanoid", () => {
return {
nanoid: vi.fn(() => "test-id"),
};
});
// ReactDOM is located inside index.tsx file
// as a result, we need a place for it to render into
const element = document.createElement("div");
element.id = "root";
document.body.appendChild(element);
const _consoleError = console.error.bind(console);
console.error = (...args) => {
// the react's act() warning usually doesn't contain any useful stack trace
// so we're catching the log and re-logging the message with the test name,
// also stripping the actual component stack trace as it's not useful
if (args[0]?.includes("act(")) {
_consoleError(
yellow(
`<<< WARNING: test "${
expect.getState().currentTestName
}" does not wrap some state update in act() >>>`,
),
);
} else {
_consoleError(...args);
}
};