2
0

setupTests.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import fs from "fs";
  2. // vitest.setup.ts
  3. import "vitest-canvas-mock";
  4. import "@testing-library/jest-dom";
  5. import { vi } from "vitest";
  6. import polyfill from "./packages/excalidraw/polyfill";
  7. import { yellow } from "./packages/excalidraw/tests/helpers/colorize";
  8. import { testPolyfills } from "./packages/excalidraw/tests/helpers/polyfills";
  9. // mock for pep.js not working with setPointerCapture()
  10. HTMLElement.prototype.setPointerCapture = vi.fn();
  11. Object.assign(globalThis, testPolyfills);
  12. require("fake-indexeddb/auto");
  13. polyfill();
  14. Object.defineProperty(window, "matchMedia", {
  15. writable: true,
  16. value: vi.fn().mockImplementation((query) => ({
  17. matches: false,
  18. media: query,
  19. onchange: null,
  20. addListener: vi.fn(), // deprecated
  21. removeListener: vi.fn(), // deprecated
  22. addEventListener: vi.fn(),
  23. removeEventListener: vi.fn(),
  24. dispatchEvent: vi.fn(),
  25. })),
  26. });
  27. Object.defineProperty(window, "FontFace", {
  28. enumerable: true,
  29. value: class {
  30. private family: string;
  31. private source: string;
  32. private descriptors: any;
  33. private status: string;
  34. private unicodeRange: string;
  35. constructor(family, source, descriptors) {
  36. this.family = family;
  37. this.source = source;
  38. this.descriptors = descriptors;
  39. this.status = "unloaded";
  40. this.unicodeRange = "U+0000-00FF";
  41. }
  42. load() {
  43. this.status = "loaded";
  44. }
  45. },
  46. });
  47. Object.defineProperty(document, "fonts", {
  48. value: {
  49. load: vi.fn().mockResolvedValue([]),
  50. check: vi.fn().mockResolvedValue(true),
  51. has: vi.fn().mockResolvedValue(true),
  52. add: vi.fn(),
  53. },
  54. });
  55. Object.defineProperty(window, "EXCALIDRAW_ASSET_PATH", {
  56. value: `file://${__dirname}/`,
  57. });
  58. // mock the font fetch only, so that everything else, as font subsetting, can run inside of the (snapshot) tests
  59. vi.mock(
  60. "./packages/excalidraw/fonts/ExcalidrawFontFace",
  61. async (importOriginal) => {
  62. const mod = await importOriginal<
  63. typeof import("./packages/excalidraw/fonts/ExcalidrawFontFace")
  64. >();
  65. const ExcalidrawFontFaceImpl = mod.ExcalidrawFontFace;
  66. return {
  67. ...mod,
  68. ExcalidrawFontFace: class extends ExcalidrawFontFaceImpl {
  69. public async fetchFont(url: URL): Promise<ArrayBuffer> {
  70. if (!url.toString().startsWith("file://")) {
  71. return super.fetchFont(url);
  72. }
  73. // read local assets directly, without running a server
  74. const content = await fs.promises.readFile(url);
  75. return content.buffer;
  76. }
  77. },
  78. };
  79. },
  80. );
  81. // ReactDOM is located inside index.tsx file
  82. // as a result, we need a place for it to render into
  83. const element = document.createElement("div");
  84. element.id = "root";
  85. document.body.appendChild(element);
  86. const _consoleError = console.error.bind(console);
  87. console.error = (...args) => {
  88. // the react's act() warning usually doesn't contain any useful stack trace
  89. // so we're catching the log and re-logging the message with the test name,
  90. // also stripping the actual component stack trace as it's not useful
  91. if (args[0]?.includes?.("act(")) {
  92. _consoleError(
  93. yellow(
  94. `<<< WARNING: test "${
  95. expect.getState().currentTestName
  96. }" does not wrap some state update in act() >>>`,
  97. ),
  98. );
  99. } else {
  100. _consoleError(...args);
  101. }
  102. };