snapshot of https://github.com/excalidraw/excalidraw.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Tests / test (push) Failing after 15s

This commit is contained in:
upstream-mirror
2026-09-16 05:31:04 +05:00
commit 1a8d07ca6c
1286 changed files with 360144 additions and 0 deletions

View File

@@ -0,0 +1,167 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { AnimationController } from "../renderer/animation";
const FIRST_KEY = "animation-test-first";
const SECOND_KEY = "animation-test-second";
describe("AnimationController", () => {
beforeEach(() => {
vi.useFakeTimers();
window.EXCALIDRAW_THROTTLE_RENDER = false;
});
afterEach(() => {
AnimationController.cancel(FIRST_KEY);
AnimationController.cancel(SECOND_KEY);
window.EXCALIDRAW_THROTTLE_RENDER = undefined;
vi.useRealTimers();
});
it("starts a new animation after the previous last animation was cancelled", async () => {
let firstFrames = 0;
AnimationController.start(FIRST_KEY, () => {
firstFrames++;
return { keep: true };
});
expect(firstFrames).toBe(1);
AnimationController.cancel(FIRST_KEY);
await vi.runOnlyPendingTimersAsync();
let secondFrames = 0;
AnimationController.start(SECOND_KEY, () => {
secondFrames++;
return secondFrames === 1 ? { keep: true } : null;
});
expect(secondFrames).toBe(1);
await vi.runOnlyPendingTimersAsync();
expect(secondFrames).toBe(2);
expect(AnimationController.running(SECOND_KEY)).toBe(false);
});
it("cancels a frame scheduled during a tick if no animations remain", async () => {
let firstFrames = 0;
let secondFrames = 0;
AnimationController.start(FIRST_KEY, ({ state }) => {
if (!state) {
return { keep: true };
}
firstFrames++;
AnimationController.start(SECOND_KEY, () => {
secondFrames++;
return { keep: true };
});
AnimationController.cancel(SECOND_KEY);
return null;
});
await vi.runOnlyPendingTimersAsync();
expect(firstFrames).toBe(1);
expect(secondFrames).toBe(1);
expect(vi.getTimerCount()).toBe(0);
});
it("does not resurrect an animation cancelled during its initial callback", () => {
let frames = 0;
AnimationController.start(FIRST_KEY, () => {
frames++;
AnimationController.cancel(FIRST_KEY);
return { keep: true };
});
expect(frames).toBe(1);
expect(AnimationController.running(FIRST_KEY)).toBe(false);
expect(vi.getTimerCount()).toBe(0);
});
it("cleans up the registration when the initial callback throws", () => {
expect(() =>
AnimationController.start(FIRST_KEY, () => {
throw new Error("initial frame failed");
}),
).toThrow("initial frame failed");
expect(AnimationController.running(FIRST_KEY)).toBe(false);
expect(vi.getTimerCount()).toBe(0);
});
it("preserves a same-key replacement started during the initial callback", async () => {
let originalFrames = 0;
let replacementFrames = 0;
const replacement = ({ state }: { state?: { keep: true } }) => {
replacementFrames++;
return state ? null : { keep: true as const };
};
AnimationController.start(FIRST_KEY, () => {
originalFrames++;
AnimationController.cancel(FIRST_KEY);
AnimationController.start(FIRST_KEY, replacement);
return { keep: true };
});
expect(originalFrames).toBe(1);
expect(replacementFrames).toBe(1);
expect(AnimationController.running(FIRST_KEY)).toBe(true);
await vi.runOnlyPendingTimersAsync();
expect(originalFrames).toBe(1);
expect(replacementFrames).toBe(2);
expect(AnimationController.running(FIRST_KEY)).toBe(false);
});
it("does not let a completed callback delete its same-key replacement", async () => {
// tests for this unwanted case:
//
// 1. The original animation’s scheduled callback begins.
// 2. Before it returns, application code cancels it and starts
// a replacement using the same key.
// 3. The original callback returns null.
// 4. Previously, tick() then called delete(key), accidentally deleting
// the replacement.
let originalFrames = 0;
let replacementFrames = 0;
const replacement = ({ state }: { state?: { keep: true } }) => {
replacementFrames++;
return state ? null : { keep: true as const };
};
AnimationController.start(FIRST_KEY, ({ state }) => {
if (!state) {
return { keep: true };
}
originalFrames++;
AnimationController.cancel(FIRST_KEY);
AnimationController.start(FIRST_KEY, replacement);
return null;
});
await vi.runOnlyPendingTimersAsync();
expect(originalFrames).toBe(1);
expect(replacementFrames).toBe(1);
expect(AnimationController.running(FIRST_KEY)).toBe(true);
await vi.runOnlyPendingTimersAsync();
expect(originalFrames).toBe(1);
expect(replacementFrames).toBe(2);
expect(AnimationController.running(FIRST_KEY)).toBe(false);
});
});