141 lines
3.9 KiB
TypeScript
141 lines
3.9 KiB
TypeScript
import { API } from "@excalidraw/excalidraw/tests/helpers/api";
|
|
|
|
import { arrayToMap } from "@excalidraw/common";
|
|
|
|
import type App from "@excalidraw/excalidraw/components/App";
|
|
|
|
import type { ObservedAppState } from "@excalidraw/excalidraw/types";
|
|
import type {
|
|
ExcalidrawElement,
|
|
SceneElementsMap,
|
|
} from "@excalidraw/element/types";
|
|
|
|
import {
|
|
CaptureUpdateAction,
|
|
Store,
|
|
StoreSnapshot,
|
|
newElementWith,
|
|
} from "../src";
|
|
|
|
const getScheduledMicroActionCount = (store: Store) =>
|
|
(
|
|
store as unknown as {
|
|
scheduledMicroActions: Array<() => void>;
|
|
}
|
|
).scheduledMicroActions.length;
|
|
|
|
const flushMicroActions = (store: Store) => {
|
|
(
|
|
store as unknown as {
|
|
flushMicroActions: () => void;
|
|
}
|
|
).flushMicroActions();
|
|
};
|
|
|
|
const toSceneElementsMap = (
|
|
elements: readonly ExcalidrawElement[],
|
|
): SceneElementsMap => arrayToMap(elements) as SceneElementsMap;
|
|
|
|
const createStoreHarness = (elements: SceneElementsMap) => {
|
|
const appState: ObservedAppState = StoreSnapshot.empty().appState;
|
|
const app = {
|
|
scene: {
|
|
getElementsMapIncludingDeleted: () => elements,
|
|
},
|
|
state: appState,
|
|
} as unknown as App;
|
|
|
|
const store = new Store(app);
|
|
store.snapshot = StoreSnapshot.create(elements, appState);
|
|
|
|
return { store, appState };
|
|
};
|
|
|
|
describe("Store synthetic increment isolation", () => {
|
|
it("keeps pending immediate micro actions queued across synthetic commit", () => {
|
|
const element = API.createElement({
|
|
type: "rectangle",
|
|
id: "store-isolated-immediate",
|
|
x: 0,
|
|
y: 0,
|
|
});
|
|
const baselineElements = toSceneElementsMap([element]);
|
|
const { store } = createStoreHarness(baselineElements);
|
|
|
|
const incrementTypes: Array<"durable" | "ephemeral"> = [];
|
|
const detach = store.onStoreIncrementEmitter.on((increment) => {
|
|
incrementTypes.push(increment.type);
|
|
});
|
|
|
|
store.scheduleMicroAction({
|
|
action: CaptureUpdateAction.IMMEDIATELY,
|
|
elements: [newElementWith(element, { y: 240 })],
|
|
appState: undefined,
|
|
});
|
|
|
|
expect(getScheduledMicroActionCount(store)).toBe(1);
|
|
|
|
const committed = store.commitSyntheticIncrement({
|
|
logicalBefore: {
|
|
elements: baselineElements,
|
|
},
|
|
logicalAfter: {
|
|
elements: toSceneElementsMap([newElementWith(element, { x: 120 })]),
|
|
},
|
|
});
|
|
|
|
expect(committed).toBe(true);
|
|
expect(incrementTypes).toEqual(["durable"]);
|
|
expect(getScheduledMicroActionCount(store)).toBe(1);
|
|
|
|
flushMicroActions(store);
|
|
|
|
expect(incrementTypes).toEqual(["durable", "durable"]);
|
|
expect(getScheduledMicroActionCount(store)).toBe(0);
|
|
detach();
|
|
});
|
|
|
|
it("keeps pending eventually micro actions queued across synthetic commit", () => {
|
|
const element = API.createElement({
|
|
type: "rectangle",
|
|
id: "store-isolated-eventually",
|
|
x: 0,
|
|
y: 0,
|
|
});
|
|
const baselineElements = toSceneElementsMap([element]);
|
|
const { store } = createStoreHarness(baselineElements);
|
|
|
|
const incrementTypes: Array<"durable" | "ephemeral"> = [];
|
|
const detach = store.onStoreIncrementEmitter.on((increment) => {
|
|
incrementTypes.push(increment.type);
|
|
});
|
|
|
|
store.scheduleMicroAction({
|
|
action: CaptureUpdateAction.EVENTUALLY,
|
|
elements: [newElementWith(element, { y: 240 })],
|
|
appState: undefined,
|
|
});
|
|
|
|
expect(getScheduledMicroActionCount(store)).toBe(1);
|
|
|
|
const committed = store.commitSyntheticIncrement({
|
|
logicalBefore: {
|
|
elements: baselineElements,
|
|
},
|
|
logicalAfter: {
|
|
elements: toSceneElementsMap([newElementWith(element, { x: 120 })]),
|
|
},
|
|
});
|
|
|
|
expect(committed).toBe(true);
|
|
expect(incrementTypes).toEqual(["durable"]);
|
|
expect(getScheduledMicroActionCount(store)).toBe(1);
|
|
|
|
flushMicroActions(store);
|
|
|
|
expect(incrementTypes).toEqual(["durable", "ephemeral"]);
|
|
expect(getScheduledMicroActionCount(store)).toBe(0);
|
|
detach();
|
|
});
|
|
});
|