Fix tests

This commit is contained in:
Marcel Mraz 2025-04-29 22:50:15 +02:00
parent eb9b6ac837
commit 09135e827e
No known key found for this signature in database
GPG key ID: 4EBD6E62DC830CD2
11 changed files with 18432 additions and 18201 deletions

View file

@ -1233,27 +1233,3 @@ export const sizeOf = (
? value.size ? value.size
: Object.keys(value).length; : Object.keys(value).length;
}; };
/**
* Deep freeze an object to prevent any modifications to the object or its nested properties.
*/
export const deepFreeze = <T>(obj: T): T => {
// Return if obj is null or not an object
if (obj === null || typeof obj !== "object") {
return obj;
}
// Freeze the object itself
Object.freeze(obj);
// Freeze all properties
Object.getOwnPropertyNames(obj).forEach((prop) => {
const value = (obj as any)[prop];
if (value && typeof value === "object") {
deepFreeze(value);
}
});
return obj;
};

View file

@ -6,7 +6,6 @@ import {
isTestEnv, isTestEnv,
randomId, randomId,
Emitter, Emitter,
deepFreeze,
} from "@excalidraw/common"; } from "@excalidraw/common";
import type { DTO, ValueOf } from "@excalidraw/common/utility-types"; import type { DTO, ValueOf } from "@excalidraw/common/utility-types";
@ -427,7 +426,6 @@ export class DurableIncrement extends StoreIncrement {
public readonly delta: StoreDelta, public readonly delta: StoreDelta,
) { ) {
super("durable", change); super("durable", change);
deepFreeze(this);
} }
} }
@ -437,7 +435,6 @@ export class DurableIncrement extends StoreIncrement {
export class EphemeralIncrement extends StoreIncrement { export class EphemeralIncrement extends StoreIncrement {
constructor(public readonly change: StoreChange) { constructor(public readonly change: StoreChange) {
super("ephemeral", change); super("ephemeral", change);
deepFreeze(this);
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -44,7 +44,7 @@ exports[`duplicate element on move when ALT is clicked > rectangle 6`] = `
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 50, "height": 50,
"id": "id2", "id": "id4",
"index": "a1", "index": "a1",
"isDeleted": false, "isDeleted": false,
"link": null, "link": null,
@ -108,7 +108,7 @@ exports[`move element > rectangles with binding arrow 5`] = `
"backgroundColor": "transparent", "backgroundColor": "transparent",
"boundElements": [ "boundElements": [
{ {
"id": "id2", "id": "id6",
"type": "arrow", "type": "arrow",
}, },
], ],
@ -147,7 +147,7 @@ exports[`move element > rectangles with binding arrow 6`] = `
"backgroundColor": "transparent", "backgroundColor": "transparent",
"boundElements": [ "boundElements": [
{ {
"id": "id2", "id": "id6",
"type": "arrow", "type": "arrow",
}, },
], ],
@ -156,7 +156,7 @@ exports[`move element > rectangles with binding arrow 6`] = `
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 300, "height": 300,
"id": "id1", "id": "id3",
"index": "a1", "index": "a1",
"isDeleted": false, "isDeleted": false,
"link": null, "link": null,
@ -189,7 +189,7 @@ exports[`move element > rectangles with binding arrow 7`] = `
"elbowed": false, "elbowed": false,
"endArrowhead": "arrow", "endArrowhead": "arrow",
"endBinding": { "endBinding": {
"elementId": "id1", "elementId": "id3",
"focus": "-0.46667", "focus": "-0.46667",
"gap": 10, "gap": 10,
}, },
@ -197,7 +197,7 @@ exports[`move element > rectangles with binding arrow 7`] = `
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": "87.29887", "height": "87.29887",
"id": "id2", "id": "id6",
"index": "a2", "index": "a2",
"isDeleted": false, "isDeleted": false,
"lastCommittedPoint": null, "lastCommittedPoint": null,

View file

@ -23,6 +23,7 @@ import {
waitFor, waitFor,
togglePopover, togglePopover,
unmountComponent, unmountComponent,
checkpointHistory,
} from "./test-utils"; } from "./test-utils";
import type { ShortcutName } from "../actions/shortcuts"; import type { ShortcutName } from "../actions/shortcuts";
@ -33,11 +34,12 @@ const checkpoint = (name: string) => {
`[${name}] number of renders`, `[${name}] number of renders`,
); );
expect(h.state).toMatchSnapshot(`[${name}] appState`); expect(h.state).toMatchSnapshot(`[${name}] appState`);
expect(h.history).toMatchSnapshot(`[${name}] history`);
expect(h.elements.length).toMatchSnapshot(`[${name}] number of elements`); expect(h.elements.length).toMatchSnapshot(`[${name}] number of elements`);
h.elements.forEach((element, i) => h.elements.forEach((element, i) =>
expect(element).toMatchSnapshot(`[${name}] element ${i}`), expect(element).toMatchSnapshot(`[${name}] element ${i}`),
); );
checkpointHistory(h.history, name);
}; };
const mouse = new Pointer("mouse"); const mouse = new Pointer("mouse");

View file

@ -62,6 +62,7 @@ import {
render, render,
togglePopover, togglePopover,
getCloneByOrigId, getCloneByOrigId,
checkpointHistory,
} from "./test-utils"; } from "./test-utils";
import type { AppState } from "../types"; import type { AppState } from "../types";
@ -84,51 +85,14 @@ const checkpoint = (name: string) => {
} = h.state; } = h.state;
expect(strippedAppState).toMatchSnapshot(`[${name}] appState`); expect(strippedAppState).toMatchSnapshot(`[${name}] appState`);
expect(h.elements.length).toMatchSnapshot(`[${name}] number of elements`); expect(h.elements.length).toMatchSnapshot(`[${name}] number of elements`);
h.elements h.elements
.map(({ seed, versionNonce, ...strippedElement }) => strippedElement) .map(({ seed, versionNonce, ...strippedElement }) => strippedElement)
.forEach((element, i) => .forEach((element, i) =>
expect(element).toMatchSnapshot(`[${name}] element ${i}`), expect(element).toMatchSnapshot(`[${name}] element ${i}`),
); );
const stripSeed = (deltas: Record<string, { deleted: any; inserted: any }>) => checkpointHistory(h.history, name);
Object.entries(deltas).reduce((acc, curr) => {
const { inserted, deleted, ...rest } = curr[1];
delete inserted.seed;
delete deleted.seed;
acc[curr[0]] = {
inserted,
deleted,
...rest,
};
return acc;
}, {} as Record<string, any>);
expect(
h.history.undoStack.map((x) => ({
...x,
elementsChange: {
...x.elements,
added: stripSeed(x.elements.added),
removed: stripSeed(x.elements.updated),
updated: stripSeed(x.elements.removed),
},
})),
).toMatchSnapshot(`[${name}] undo stack`);
expect(
h.history.redoStack.map((x) => ({
...x,
elementsChange: {
...x.elements,
added: stripSeed(x.elements.added),
removed: stripSeed(x.elements.updated),
updated: stripSeed(x.elements.removed),
},
})),
).toMatchSnapshot(`[${name}] redo stack`);
}; };
const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene"); const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene");

View file

@ -14,6 +14,7 @@ import { API } from "./helpers/api";
import { Keyboard, Pointer, UI } from "./helpers/ui"; import { Keyboard, Pointer, UI } from "./helpers/ui";
import { import {
assertSelectedElements, assertSelectedElements,
checkpointHistory,
fireEvent, fireEvent,
render, render,
screen, screen,
@ -39,11 +40,12 @@ const checkpoint = (name: string) => {
`[${name}] number of renders`, `[${name}] number of renders`,
); );
expect(h.state).toMatchSnapshot(`[${name}] appState`); expect(h.state).toMatchSnapshot(`[${name}] appState`);
expect(h.history).toMatchSnapshot(`[${name}] history`);
expect(h.elements.length).toMatchSnapshot(`[${name}] number of elements`); expect(h.elements.length).toMatchSnapshot(`[${name}] number of elements`);
h.elements.forEach((element, i) => h.elements.forEach((element, i) =>
expect(element).toMatchSnapshot(`[${name}] element ${i}`), expect(element).toMatchSnapshot(`[${name}] element ${i}`),
); );
checkpointHistory(h.history, name);
}; };
beforeEach(async () => { beforeEach(async () => {
unmountComponent(); unmountComponent();

View file

@ -22,6 +22,8 @@ import { STORAGE_KEYS } from "../../../excalidraw-app/app_constants";
import { Pointer, UI } from "./helpers/ui"; import { Pointer, UI } from "./helpers/ui";
import * as toolQueries from "./queries/toolQueries"; import * as toolQueries from "./queries/toolQueries";
import type { History } from "../history";
import type { RenderResult, RenderOptions } from "@testing-library/react"; import type { RenderResult, RenderOptions } from "@testing-library/react";
import type { ImportedDataState } from "../data/types"; import type { ImportedDataState } from "../data/types";
@ -432,3 +434,45 @@ export const assertElements = <T extends AllPossibleKeys<ExcalidrawElement>>(
expect(h.state.selectedElementIds).toEqual(selectedElementIds); expect(h.state.selectedElementIds).toEqual(selectedElementIds);
}; };
const stripSeed = (deltas: Record<string, { deleted: any; inserted: any }>) =>
Object.entries(deltas).reduce((acc, curr) => {
const { inserted, deleted, ...rest } = curr[1];
delete inserted.seed;
delete deleted.seed;
acc[curr[0]] = {
inserted,
deleted,
...rest,
};
return acc;
}, {} as Record<string, any>);
export const checkpointHistory = (history: History, name: string) => {
expect(
history.undoStack.map((x) => ({
...x,
elements: {
...x.elements,
added: stripSeed(x.elements.added),
removed: stripSeed(x.elements.removed),
updated: stripSeed(x.elements.updated),
},
})),
).toMatchSnapshot(`[${name}] undo stack`);
expect(
history.redoStack.map((x) => ({
...x,
elements: {
...x.elements,
added: stripSeed(x.elements.added),
removed: stripSeed(x.elements.removed),
updated: stripSeed(x.elements.updated),
},
})),
).toMatchSnapshot(`[${name}] redo stack`);
};