Files
excalidraw/packages/element/tests/shape.test.ts
T
dwelle 3e53dcd956 wip
2026-04-03 16:34:26 +02:00

121 lines
3.2 KiB
TypeScript

import { pointFrom } from "@excalidraw/math";
import { API } from "@excalidraw/excalidraw/tests/helpers/api";
import { vi } from "vitest";
vi.mock("perfect-freehand", () => ({
getStroke: vi.fn(() => []),
}));
import { getStroke } from "perfect-freehand";
import { getFreedrawOutlinePoints, ShapeCache } from "../src/shape";
describe("freedraw stroke shape", () => {
beforeEach(() => {
vi.mocked(getStroke).mockClear();
ShapeCache.destroy();
});
it("renders fixed strokes from the centerline path", () => {
const element = API.createElement({
type: "freedraw",
strokeShape: "fixed",
points: [pointFrom(0, 0), pointFrom(10, 10), pointFrom(20, 15)],
});
const shapes = ShapeCache.generateElementShape(element, null);
expect(shapes).toEqual([expect.any(String)]);
expect(shapes[0]).not.toContain("Z");
expect(vi.mocked(getStroke)).not.toHaveBeenCalled();
});
it("renders fixed stroke corners as straight segments", () => {
const element = API.createElement({
type: "freedraw",
strokeShape: "fixed",
points: [pointFrom(0, 0), pointFrom(10, 0), pointFrom(10, 10)],
});
const [path] = ShapeCache.generateElementShape(element, null);
expect(path).toBe("M0,0 L10,0 L10,10 ");
});
it("smooths dense fixed stroke points without dropping them", () => {
const element = API.createElement({
type: "freedraw",
strokeShape: "fixed",
points: [
pointFrom(0, 0),
pointFrom(0.3, 0.1),
pointFrom(0.6, 0.35),
pointFrom(1, 0.9),
],
});
const [path] = ShapeCache.generateElementShape(element, null);
expect(path).toContain("Q0.3,0.1 ");
expect(path).toContain("Q0.6,0.35 ");
});
it("drops synthetic loop closure for fixed strokes", () => {
const element = API.createElement({
type: "freedraw",
strokeShape: "fixed",
points: [pointFrom(0, 0), pointFrom(10, 0), pointFrom(0, 0)],
});
const [path] = ShapeCache.generateElementShape(element, null);
expect(path).toBe("M0,0 L10,0 ");
});
it("uses fixed perfect-freehand settings for fixed strokes", () => {
const element = API.createElement({
type: "freedraw",
strokeShape: "fixed",
strokeWidth: 8,
points: [pointFrom(0, 0), pointFrom(10, 10), pointFrom(20, 15)],
});
getFreedrawOutlinePoints(element);
expect(vi.mocked(getStroke)).toHaveBeenCalledWith(
element.points,
expect.objectContaining({
simulatePressure: false,
size: element.strokeWidth,
thinning: 0,
}),
);
});
it("keeps pressure-aware perfect-freehand settings for variable strokes", () => {
const element = API.createElement({
type: "freedraw",
points: [pointFrom(0, 0), pointFrom(10, 10), pointFrom(20, 15)],
});
getFreedrawOutlinePoints({
...element,
simulatePressure: false,
pressures: [0.2, 0.8, 0.4],
});
expect(vi.mocked(getStroke)).toHaveBeenCalledWith(
[
[0, 0, 0.2],
[10, 10, 0.8],
[20, 15, 0.4],
],
expect.objectContaining({
simulatePressure: false,
size: element.strokeWidth * 4.25,
thinning: 0.6,
}),
);
});
});