147 lines
4.9 KiB
TypeScript
147 lines
4.9 KiB
TypeScript
|
import ReactDOM from "react-dom";
|
||
|
import { ExcalidrawLinearElement } from "../element/types";
|
||
|
import ExcalidrawApp from "../excalidraw-app";
|
||
|
import { centerPoint } from "../math";
|
||
|
import { reseed } from "../random";
|
||
|
import * as Renderer from "../renderer/renderScene";
|
||
|
import { Keyboard } from "./helpers/ui";
|
||
|
import { screen } from "./test-utils";
|
||
|
|
||
|
import { render, fireEvent } from "./test-utils";
|
||
|
import { Point } from "../types";
|
||
|
import { KEYS } from "../keys";
|
||
|
import { LinearElementEditor } from "../element/linearElementEditor";
|
||
|
|
||
|
const renderScene = jest.spyOn(Renderer, "renderScene");
|
||
|
|
||
|
const { h } = window;
|
||
|
|
||
|
describe(" Test Linear Elements", () => {
|
||
|
let getByToolName: (...args: string[]) => HTMLElement;
|
||
|
let container: HTMLElement;
|
||
|
let canvas: HTMLCanvasElement;
|
||
|
|
||
|
beforeEach(async () => {
|
||
|
// Unmount ReactDOM from root
|
||
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
||
|
localStorage.clear();
|
||
|
renderScene.mockClear();
|
||
|
reseed(7);
|
||
|
const comp = await render(<ExcalidrawApp />);
|
||
|
getByToolName = comp.getByToolName;
|
||
|
container = comp.container;
|
||
|
canvas = container.querySelector("canvas")!;
|
||
|
});
|
||
|
|
||
|
const p1: Point = [20, 20];
|
||
|
const p2: Point = [60, 20];
|
||
|
const midpoint = centerPoint(p1, p2);
|
||
|
|
||
|
const createTwoPointerLinearElement = (
|
||
|
type: ExcalidrawLinearElement["type"],
|
||
|
edge: "Sharp" | "Round" = "Sharp",
|
||
|
roughness: "Architect" | "Cartoonist" | "Artist" = "Architect",
|
||
|
) => {
|
||
|
const tool = getByToolName(type);
|
||
|
fireEvent.click(tool);
|
||
|
fireEvent.click(screen.getByTitle(edge));
|
||
|
fireEvent.click(screen.getByTitle(roughness));
|
||
|
fireEvent.pointerDown(canvas, { clientX: p1[0], clientY: p1[1] });
|
||
|
fireEvent.pointerMove(canvas, { clientX: p2[0], clientY: p2[1] });
|
||
|
fireEvent.pointerUp(canvas, { clientX: p2[0], clientY: p2[1] });
|
||
|
};
|
||
|
|
||
|
const createThreePointerLinearElement = (
|
||
|
type: ExcalidrawLinearElement["type"],
|
||
|
edge: "Sharp" | "Round" = "Sharp",
|
||
|
) => {
|
||
|
createTwoPointerLinearElement("line");
|
||
|
// Extending line via midpoint
|
||
|
fireEvent.pointerDown(canvas, {
|
||
|
clientX: midpoint[0],
|
||
|
clientY: midpoint[1],
|
||
|
});
|
||
|
fireEvent.pointerMove(canvas, {
|
||
|
clientX: midpoint[0] + 50,
|
||
|
clientY: midpoint[1] + 50,
|
||
|
});
|
||
|
fireEvent.pointerUp(canvas, {
|
||
|
clientX: midpoint[0] + 50,
|
||
|
clientY: midpoint[1] + 50,
|
||
|
});
|
||
|
};
|
||
|
|
||
|
const dragLinearElementFromPoint = (point: Point) => {
|
||
|
fireEvent.pointerDown(canvas, {
|
||
|
clientX: point[0],
|
||
|
clientY: point[1],
|
||
|
});
|
||
|
fireEvent.pointerMove(canvas, {
|
||
|
clientX: point[0] + 50,
|
||
|
clientY: point[1] + 50,
|
||
|
});
|
||
|
fireEvent.pointerUp(canvas, {
|
||
|
clientX: point[0] + 50,
|
||
|
clientY: point[1] + 50,
|
||
|
});
|
||
|
};
|
||
|
|
||
|
it("should allow dragging line from midpoint in 2 pointer lines outside editor", async () => {
|
||
|
createTwoPointerLinearElement("line");
|
||
|
const line = h.elements[0] as ExcalidrawLinearElement;
|
||
|
|
||
|
expect(renderScene).toHaveBeenCalledTimes(10);
|
||
|
expect((h.elements[0] as ExcalidrawLinearElement).points.length).toEqual(2);
|
||
|
|
||
|
// drag line from midpoint
|
||
|
dragLinearElementFromPoint(midpoint);
|
||
|
expect(renderScene).toHaveBeenCalledTimes(13);
|
||
|
expect(line.points.length).toEqual(3);
|
||
|
expect(line.points).toMatchSnapshot();
|
||
|
});
|
||
|
|
||
|
describe("Inside editor", () => {
|
||
|
it("should allow dragging line from midpoint in 2 pointer lines", async () => {
|
||
|
createTwoPointerLinearElement("line");
|
||
|
const line = h.elements[0] as ExcalidrawLinearElement;
|
||
|
|
||
|
fireEvent.click(canvas, { clientX: p1[0], clientY: p1[1] });
|
||
|
|
||
|
Keyboard.keyPress(KEYS.ENTER);
|
||
|
expect(h.state.editingLinearElement?.elementId).toEqual(h.elements[0].id);
|
||
|
|
||
|
// drag line from midpoint
|
||
|
dragLinearElementFromPoint(midpoint);
|
||
|
expect(line.points.length).toEqual(3);
|
||
|
expect(line.points).toMatchSnapshot();
|
||
|
});
|
||
|
|
||
|
it("should allow dragging lines from midpoints in between segments", async () => {
|
||
|
createThreePointerLinearElement("line");
|
||
|
|
||
|
const line = h.elements[0] as ExcalidrawLinearElement;
|
||
|
expect(line.points.length).toEqual(3);
|
||
|
fireEvent.click(canvas, { clientX: p1[0], clientY: p1[1] });
|
||
|
|
||
|
Keyboard.keyPress(KEYS.ENTER);
|
||
|
expect(h.state.editingLinearElement?.elementId).toEqual(h.elements[0].id);
|
||
|
|
||
|
let points = LinearElementEditor.getPointsGlobalCoordinates(line);
|
||
|
const firstSegmentMidpoint = centerPoint(points[0], points[1]);
|
||
|
// drag line via first segment midpoint
|
||
|
dragLinearElementFromPoint(firstSegmentMidpoint);
|
||
|
expect(line.points.length).toEqual(4);
|
||
|
|
||
|
// drag line from last segment midpoint
|
||
|
points = LinearElementEditor.getPointsGlobalCoordinates(line);
|
||
|
const lastSegmentMidpoint = centerPoint(points.at(-2)!, points.at(-1)!);
|
||
|
dragLinearElementFromPoint(lastSegmentMidpoint);
|
||
|
expect(line.points.length).toEqual(5);
|
||
|
|
||
|
expect(
|
||
|
(h.elements[0] as ExcalidrawLinearElement).points,
|
||
|
).toMatchSnapshot();
|
||
|
});
|
||
|
});
|
||
|
});
|