|
@@ -1,4 +1,5 @@
|
|
-import { fireEvent, queryByTestId } from "@testing-library/react";
|
|
|
|
|
|
+import React from "react";
|
|
|
|
+import { act, fireEvent, queryByTestId } from "@testing-library/react";
|
|
import { Keyboard, Pointer, UI } from "../../tests/helpers/ui";
|
|
import { Keyboard, Pointer, UI } from "../../tests/helpers/ui";
|
|
import { getStepSizedValue } from "./utils";
|
|
import { getStepSizedValue } from "./utils";
|
|
import {
|
|
import {
|
|
@@ -18,13 +19,13 @@ import type {
|
|
ExcalidrawLinearElement,
|
|
ExcalidrawLinearElement,
|
|
ExcalidrawTextElement,
|
|
ExcalidrawTextElement,
|
|
} from "../../element/types";
|
|
} from "../../element/types";
|
|
-import { degreeToRadian, rotate } from "../../math";
|
|
|
|
import { getTextEditor, updateTextEditor } from "../../tests/queries/dom";
|
|
import { getTextEditor, updateTextEditor } from "../../tests/queries/dom";
|
|
import { getCommonBounds, isTextElement } from "../../element";
|
|
import { getCommonBounds, isTextElement } from "../../element";
|
|
import { API } from "../../tests/helpers/api";
|
|
import { API } from "../../tests/helpers/api";
|
|
import { actionGroup } from "../../actions";
|
|
import { actionGroup } from "../../actions";
|
|
import { isInGroup } from "../../groups";
|
|
import { isInGroup } from "../../groups";
|
|
-import React from "react";
|
|
|
|
|
|
+import type { Degrees } from "../../../math";
|
|
|
|
+import { degreesToRadians, pointFrom, pointRotateRads } from "../../../math";
|
|
|
|
|
|
const { h } = window;
|
|
const { h } = window;
|
|
const mouse = new Pointer("mouse");
|
|
const mouse = new Pointer("mouse");
|
|
@@ -32,27 +33,6 @@ const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene");
|
|
let stats: HTMLElement | null = null;
|
|
let stats: HTMLElement | null = null;
|
|
let elementStats: HTMLElement | null | undefined = null;
|
|
let elementStats: HTMLElement | null | undefined = null;
|
|
|
|
|
|
-const editInput = (input: HTMLInputElement, value: string) => {
|
|
|
|
- input.focus();
|
|
|
|
- fireEvent.change(input, { target: { value } });
|
|
|
|
- input.blur();
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-const getStatsProperty = (label: string) => {
|
|
|
|
- const elementStats = UI.queryStats()?.querySelector("#elementStats");
|
|
|
|
-
|
|
|
|
- if (elementStats) {
|
|
|
|
- const properties = elementStats?.querySelector(".statsItem");
|
|
|
|
- return (
|
|
|
|
- properties?.querySelector?.(
|
|
|
|
- `.drag-input-container[data-testid="${label}"]`,
|
|
|
|
- ) || null
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return null;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
const testInputProperty = (
|
|
const testInputProperty = (
|
|
element: ExcalidrawElement,
|
|
element: ExcalidrawElement,
|
|
property: "x" | "y" | "width" | "height" | "angle" | "fontSize",
|
|
property: "x" | "y" | "width" | "height" | "angle" | "fontSize",
|
|
@@ -60,14 +40,16 @@ const testInputProperty = (
|
|
initialValue: number,
|
|
initialValue: number,
|
|
nextValue: number,
|
|
nextValue: number,
|
|
) => {
|
|
) => {
|
|
- const input = getStatsProperty(label)?.querySelector(
|
|
|
|
|
|
+ const input = UI.queryStatsProperty(label)?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(input).toBeDefined();
|
|
expect(input).toBeDefined();
|
|
expect(input.value).toBe(initialValue.toString());
|
|
expect(input.value).toBe(initialValue.toString());
|
|
- editInput(input, String(nextValue));
|
|
|
|
|
|
+ UI.updateInput(input, String(nextValue));
|
|
if (property === "angle") {
|
|
if (property === "angle") {
|
|
- expect(element[property]).toBe(degreeToRadian(Number(nextValue)));
|
|
|
|
|
|
+ expect(element[property]).toBe(
|
|
|
|
+ degreesToRadians(Number(nextValue) as Degrees),
|
|
|
|
+ );
|
|
} else if (property === "fontSize" && isTextElement(element)) {
|
|
} else if (property === "fontSize" && isTextElement(element)) {
|
|
expect(element[property]).toBe(Number(nextValue));
|
|
expect(element[property]).toBe(Number(nextValue));
|
|
} else if (property !== "fontSize") {
|
|
} else if (property !== "fontSize") {
|
|
@@ -110,7 +92,7 @@ describe("binding with linear elements", () => {
|
|
|
|
|
|
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
|
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
|
|
|
|
|
- h.elements = [];
|
|
|
|
|
|
+ API.setElements([]);
|
|
|
|
|
|
fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
|
|
fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
|
|
button: 2,
|
|
button: 2,
|
|
@@ -142,47 +124,47 @@ describe("binding with linear elements", () => {
|
|
|
|
|
|
it("should remain bound to linear element on small position change", async () => {
|
|
it("should remain bound to linear element on small position change", async () => {
|
|
const linear = h.elements[1] as ExcalidrawLinearElement;
|
|
const linear = h.elements[1] as ExcalidrawLinearElement;
|
|
- const inputX = getStatsProperty("X")?.querySelector(
|
|
|
|
|
|
+ const inputX = UI.queryStatsProperty("X")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
|
|
|
|
expect(linear.startBinding).not.toBe(null);
|
|
expect(linear.startBinding).not.toBe(null);
|
|
expect(inputX).not.toBeNull();
|
|
expect(inputX).not.toBeNull();
|
|
- editInput(inputX, String("204"));
|
|
|
|
|
|
+ UI.updateInput(inputX, String("204"));
|
|
expect(linear.startBinding).not.toBe(null);
|
|
expect(linear.startBinding).not.toBe(null);
|
|
});
|
|
});
|
|
|
|
|
|
it("should remain bound to linear element on small angle change", async () => {
|
|
it("should remain bound to linear element on small angle change", async () => {
|
|
const linear = h.elements[1] as ExcalidrawLinearElement;
|
|
const linear = h.elements[1] as ExcalidrawLinearElement;
|
|
- const inputAngle = getStatsProperty("A")?.querySelector(
|
|
|
|
|
|
+ const inputAngle = UI.queryStatsProperty("A")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
|
|
|
|
expect(linear.startBinding).not.toBe(null);
|
|
expect(linear.startBinding).not.toBe(null);
|
|
- editInput(inputAngle, String("1"));
|
|
|
|
|
|
+ UI.updateInput(inputAngle, String("1"));
|
|
expect(linear.startBinding).not.toBe(null);
|
|
expect(linear.startBinding).not.toBe(null);
|
|
});
|
|
});
|
|
|
|
|
|
it("should unbind linear element on large position change", async () => {
|
|
it("should unbind linear element on large position change", async () => {
|
|
const linear = h.elements[1] as ExcalidrawLinearElement;
|
|
const linear = h.elements[1] as ExcalidrawLinearElement;
|
|
- const inputX = getStatsProperty("X")?.querySelector(
|
|
|
|
|
|
+ const inputX = UI.queryStatsProperty("X")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
|
|
|
|
expect(linear.startBinding).not.toBe(null);
|
|
expect(linear.startBinding).not.toBe(null);
|
|
expect(inputX).not.toBeNull();
|
|
expect(inputX).not.toBeNull();
|
|
- editInput(inputX, String("254"));
|
|
|
|
|
|
+ UI.updateInput(inputX, String("254"));
|
|
expect(linear.startBinding).toBe(null);
|
|
expect(linear.startBinding).toBe(null);
|
|
});
|
|
});
|
|
|
|
|
|
it("should remain bound to linear element on small angle change", async () => {
|
|
it("should remain bound to linear element on small angle change", async () => {
|
|
const linear = h.elements[1] as ExcalidrawLinearElement;
|
|
const linear = h.elements[1] as ExcalidrawLinearElement;
|
|
- const inputAngle = getStatsProperty("A")?.querySelector(
|
|
|
|
|
|
+ const inputAngle = UI.queryStatsProperty("A")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
|
|
|
|
expect(linear.startBinding).not.toBe(null);
|
|
expect(linear.startBinding).not.toBe(null);
|
|
- editInput(inputAngle, String("45"));
|
|
|
|
|
|
+ UI.updateInput(inputAngle, String("45"));
|
|
expect(linear.startBinding).toBe(null);
|
|
expect(linear.startBinding).toBe(null);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
@@ -197,7 +179,7 @@ describe("stats for a generic element", () => {
|
|
|
|
|
|
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
|
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
|
|
|
|
|
- h.elements = [];
|
|
|
|
|
|
+ API.setElements([]);
|
|
|
|
|
|
fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
|
|
fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
|
|
button: 2,
|
|
button: 2,
|
|
@@ -231,18 +213,14 @@ describe("stats for a generic element", () => {
|
|
expect(title?.lastChild?.nodeValue)?.toBe(t("stats.elementProperties"));
|
|
expect(title?.lastChild?.nodeValue)?.toBe(t("stats.elementProperties"));
|
|
|
|
|
|
// element type
|
|
// element type
|
|
- const elementType = elementStats?.querySelector(".elementType");
|
|
|
|
|
|
+ const elementType = queryByTestId(elementStats!, "stats-element-type");
|
|
expect(elementType).toBeDefined();
|
|
expect(elementType).toBeDefined();
|
|
expect(elementType?.lastChild?.nodeValue).toBe(t("element.rectangle"));
|
|
expect(elementType?.lastChild?.nodeValue).toBe(t("element.rectangle"));
|
|
|
|
|
|
// properties
|
|
// properties
|
|
- const properties = elementStats?.querySelector(".statsItem");
|
|
|
|
- expect(properties?.childNodes).toBeDefined();
|
|
|
|
["X", "Y", "W", "H", "A"].forEach((label) => () => {
|
|
["X", "Y", "W", "H", "A"].forEach((label) => () => {
|
|
expect(
|
|
expect(
|
|
- properties?.querySelector?.(
|
|
|
|
- `.drag-input-container[data-testid="${label}"]`,
|
|
|
|
- ),
|
|
|
|
|
|
+ stats!.querySelector?.(`.drag-input-container[data-testid="${label}"]`),
|
|
).toBeDefined();
|
|
).toBeDefined();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
@@ -263,18 +241,18 @@ describe("stats for a generic element", () => {
|
|
const rectangle = h.elements[0];
|
|
const rectangle = h.elements[0];
|
|
const rectangleId = rectangle.id;
|
|
const rectangleId = rectangle.id;
|
|
|
|
|
|
- const input = getStatsProperty("W")?.querySelector(
|
|
|
|
|
|
+ const input = UI.queryStatsProperty("W")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(input).toBeDefined();
|
|
expect(input).toBeDefined();
|
|
expect(input.value).toBe(rectangle.width.toString());
|
|
expect(input.value).toBe(rectangle.width.toString());
|
|
- editInput(input, "123.123");
|
|
|
|
|
|
+ UI.updateInput(input, "123.123");
|
|
expect(h.elements.length).toBe(1);
|
|
expect(h.elements.length).toBe(1);
|
|
expect(rectangle.id).toBe(rectangleId);
|
|
expect(rectangle.id).toBe(rectangleId);
|
|
expect(input.value).toBe("123.12");
|
|
expect(input.value).toBe("123.12");
|
|
expect(rectangle.width).toBe(123.12);
|
|
expect(rectangle.width).toBe(123.12);
|
|
|
|
|
|
- editInput(input, "88.98766");
|
|
|
|
|
|
+ UI.updateInput(input, "88.98766");
|
|
expect(input.value).toBe("88.99");
|
|
expect(input.value).toBe("88.99");
|
|
expect(rectangle.width).toBe(88.99);
|
|
expect(rectangle.width).toBe(88.99);
|
|
});
|
|
});
|
|
@@ -285,19 +263,17 @@ describe("stats for a generic element", () => {
|
|
rectangle.x + rectangle.width / 2,
|
|
rectangle.x + rectangle.width / 2,
|
|
rectangle.y + rectangle.height / 2,
|
|
rectangle.y + rectangle.height / 2,
|
|
];
|
|
];
|
|
- const [topLeftX, topLeftY] = rotate(
|
|
|
|
- rectangle.x,
|
|
|
|
- rectangle.y,
|
|
|
|
- cx,
|
|
|
|
- cy,
|
|
|
|
|
|
+ const [topLeftX, topLeftY] = pointRotateRads(
|
|
|
|
+ pointFrom(rectangle.x, rectangle.y),
|
|
|
|
+ pointFrom(cx, cy),
|
|
rectangle.angle,
|
|
rectangle.angle,
|
|
);
|
|
);
|
|
|
|
|
|
- const xInput = getStatsProperty("X")?.querySelector(
|
|
|
|
|
|
+ const xInput = UI.queryStatsProperty("X")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
|
|
|
|
- const yInput = getStatsProperty("Y")?.querySelector(
|
|
|
|
|
|
+ const yInput = UI.queryStatsProperty("Y")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
|
|
|
|
@@ -306,11 +282,9 @@ describe("stats for a generic element", () => {
|
|
|
|
|
|
testInputProperty(rectangle, "angle", "A", 0, 45);
|
|
testInputProperty(rectangle, "angle", "A", 0, 45);
|
|
|
|
|
|
- let [newTopLeftX, newTopLeftY] = rotate(
|
|
|
|
- rectangle.x,
|
|
|
|
- rectangle.y,
|
|
|
|
- cx,
|
|
|
|
- cy,
|
|
|
|
|
|
+ let [newTopLeftX, newTopLeftY] = pointRotateRads(
|
|
|
|
+ pointFrom(rectangle.x, rectangle.y),
|
|
|
|
+ pointFrom(cx, cy),
|
|
rectangle.angle,
|
|
rectangle.angle,
|
|
);
|
|
);
|
|
|
|
|
|
@@ -319,11 +293,9 @@ describe("stats for a generic element", () => {
|
|
|
|
|
|
testInputProperty(rectangle, "angle", "A", 45, 66);
|
|
testInputProperty(rectangle, "angle", "A", 45, 66);
|
|
|
|
|
|
- [newTopLeftX, newTopLeftY] = rotate(
|
|
|
|
- rectangle.x,
|
|
|
|
- rectangle.y,
|
|
|
|
- cx,
|
|
|
|
- cy,
|
|
|
|
|
|
+ [newTopLeftX, newTopLeftY] = pointRotateRads(
|
|
|
|
+ pointFrom(rectangle.x, rectangle.y),
|
|
|
|
+ pointFrom(cx, cy),
|
|
rectangle.angle,
|
|
rectangle.angle,
|
|
);
|
|
);
|
|
expect(newTopLeftX.toString()).not.toEqual(xInput.value);
|
|
expect(newTopLeftX.toString()).not.toEqual(xInput.value);
|
|
@@ -338,11 +310,9 @@ describe("stats for a generic element", () => {
|
|
rectangle.x + rectangle.width / 2,
|
|
rectangle.x + rectangle.width / 2,
|
|
rectangle.y + rectangle.height / 2,
|
|
rectangle.y + rectangle.height / 2,
|
|
];
|
|
];
|
|
- const [topLeftX, topLeftY] = rotate(
|
|
|
|
- rectangle.x,
|
|
|
|
- rectangle.y,
|
|
|
|
- cx,
|
|
|
|
- cy,
|
|
|
|
|
|
+ const [topLeftX, topLeftY] = pointRotateRads(
|
|
|
|
+ pointFrom(rectangle.x, rectangle.y),
|
|
|
|
+ pointFrom(cx, cy),
|
|
rectangle.angle,
|
|
rectangle.angle,
|
|
);
|
|
);
|
|
testInputProperty(rectangle, "width", "W", rectangle.width, 400);
|
|
testInputProperty(rectangle, "width", "W", rectangle.width, 400);
|
|
@@ -350,11 +320,9 @@ describe("stats for a generic element", () => {
|
|
rectangle.x + rectangle.width / 2,
|
|
rectangle.x + rectangle.width / 2,
|
|
rectangle.y + rectangle.height / 2,
|
|
rectangle.y + rectangle.height / 2,
|
|
];
|
|
];
|
|
- let [currentTopLeftX, currentTopLeftY] = rotate(
|
|
|
|
- rectangle.x,
|
|
|
|
- rectangle.y,
|
|
|
|
- cx,
|
|
|
|
- cy,
|
|
|
|
|
|
+ let [currentTopLeftX, currentTopLeftY] = pointRotateRads(
|
|
|
|
+ pointFrom(rectangle.x, rectangle.y),
|
|
|
|
+ pointFrom(cx, cy),
|
|
rectangle.angle,
|
|
rectangle.angle,
|
|
);
|
|
);
|
|
expect(currentTopLeftX).toBeCloseTo(topLeftX, 4);
|
|
expect(currentTopLeftX).toBeCloseTo(topLeftX, 4);
|
|
@@ -365,11 +333,9 @@ describe("stats for a generic element", () => {
|
|
rectangle.x + rectangle.width / 2,
|
|
rectangle.x + rectangle.width / 2,
|
|
rectangle.y + rectangle.height / 2,
|
|
rectangle.y + rectangle.height / 2,
|
|
];
|
|
];
|
|
- [currentTopLeftX, currentTopLeftY] = rotate(
|
|
|
|
- rectangle.x,
|
|
|
|
- rectangle.y,
|
|
|
|
- cx,
|
|
|
|
- cy,
|
|
|
|
|
|
+ [currentTopLeftX, currentTopLeftY] = pointRotateRads(
|
|
|
|
+ pointFrom(rectangle.x, rectangle.y),
|
|
|
|
+ pointFrom(cx, cy),
|
|
rectangle.angle,
|
|
rectangle.angle,
|
|
);
|
|
);
|
|
|
|
|
|
@@ -387,7 +353,7 @@ describe("stats for a non-generic element", () => {
|
|
|
|
|
|
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
|
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
|
|
|
|
|
- h.elements = [];
|
|
|
|
|
|
+ API.setElements([]);
|
|
|
|
|
|
fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
|
|
fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
|
|
button: 2,
|
|
button: 2,
|
|
@@ -412,9 +378,10 @@ describe("stats for a non-generic element", () => {
|
|
mouse.clickAt(20, 30);
|
|
mouse.clickAt(20, 30);
|
|
const textEditorSelector = ".excalidraw-textEditorContainer > textarea";
|
|
const textEditorSelector = ".excalidraw-textEditorContainer > textarea";
|
|
const editor = await getTextEditor(textEditorSelector, true);
|
|
const editor = await getTextEditor(textEditorSelector, true);
|
|
- await new Promise((r) => setTimeout(r, 0));
|
|
|
|
updateTextEditor(editor, "Hello!");
|
|
updateTextEditor(editor, "Hello!");
|
|
- editor.blur();
|
|
|
|
|
|
+ act(() => {
|
|
|
|
+ editor.blur();
|
|
|
|
+ });
|
|
|
|
|
|
const text = h.elements[0] as ExcalidrawTextElement;
|
|
const text = h.elements[0] as ExcalidrawTextElement;
|
|
mouse.clickOn(text);
|
|
mouse.clickOn(text);
|
|
@@ -422,22 +389,22 @@ describe("stats for a non-generic element", () => {
|
|
elementStats = stats?.querySelector("#elementStats");
|
|
elementStats = stats?.querySelector("#elementStats");
|
|
|
|
|
|
// can change font size
|
|
// can change font size
|
|
- const input = getStatsProperty("F")?.querySelector(
|
|
|
|
|
|
+ const input = UI.queryStatsProperty("F")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(input).toBeDefined();
|
|
expect(input).toBeDefined();
|
|
expect(input.value).toBe(text.fontSize.toString());
|
|
expect(input.value).toBe(text.fontSize.toString());
|
|
- editInput(input, "36");
|
|
|
|
|
|
+ UI.updateInput(input, "36");
|
|
expect(text.fontSize).toBe(36);
|
|
expect(text.fontSize).toBe(36);
|
|
|
|
|
|
// cannot change width or height
|
|
// cannot change width or height
|
|
- const width = getStatsProperty("W")?.querySelector(".drag-input");
|
|
|
|
|
|
+ const width = UI.queryStatsProperty("W")?.querySelector(".drag-input");
|
|
expect(width).toBeUndefined();
|
|
expect(width).toBeUndefined();
|
|
- const height = getStatsProperty("H")?.querySelector(".drag-input");
|
|
|
|
|
|
+ const height = UI.queryStatsProperty("H")?.querySelector(".drag-input");
|
|
expect(height).toBeUndefined();
|
|
expect(height).toBeUndefined();
|
|
|
|
|
|
// min font size is 4
|
|
// min font size is 4
|
|
- editInput(input, "0");
|
|
|
|
|
|
+ UI.updateInput(input, "0");
|
|
expect(text.fontSize).not.toBe(0);
|
|
expect(text.fontSize).not.toBe(0);
|
|
expect(text.fontSize).toBe(4);
|
|
expect(text.fontSize).toBe(4);
|
|
});
|
|
});
|
|
@@ -449,8 +416,8 @@ describe("stats for a non-generic element", () => {
|
|
x: 150,
|
|
x: 150,
|
|
width: 150,
|
|
width: 150,
|
|
});
|
|
});
|
|
- h.elements = [frame];
|
|
|
|
- h.setState({
|
|
|
|
|
|
+ API.setElements([frame]);
|
|
|
|
+ API.setAppState({
|
|
selectedElementIds: {
|
|
selectedElementIds: {
|
|
[frame.id]: true,
|
|
[frame.id]: true,
|
|
},
|
|
},
|
|
@@ -461,7 +428,7 @@ describe("stats for a non-generic element", () => {
|
|
expect(elementStats).toBeDefined();
|
|
expect(elementStats).toBeDefined();
|
|
|
|
|
|
// cannot change angle
|
|
// cannot change angle
|
|
- const angle = getStatsProperty("A")?.querySelector(".drag-input");
|
|
|
|
|
|
+ const angle = UI.queryStatsProperty("A")?.querySelector(".drag-input");
|
|
expect(angle).toBeUndefined();
|
|
expect(angle).toBeUndefined();
|
|
|
|
|
|
// can change width or height
|
|
// can change width or height
|
|
@@ -471,9 +438,9 @@ describe("stats for a non-generic element", () => {
|
|
|
|
|
|
it("image element", () => {
|
|
it("image element", () => {
|
|
const image = API.createElement({ type: "image", width: 200, height: 100 });
|
|
const image = API.createElement({ type: "image", width: 200, height: 100 });
|
|
- h.elements = [image];
|
|
|
|
|
|
+ API.setElements([image]);
|
|
mouse.clickOn(image);
|
|
mouse.clickOn(image);
|
|
- h.setState({
|
|
|
|
|
|
+ API.setAppState({
|
|
selectedElementIds: {
|
|
selectedElementIds: {
|
|
[image.id]: true,
|
|
[image.id]: true,
|
|
},
|
|
},
|
|
@@ -508,15 +475,15 @@ describe("stats for a non-generic element", () => {
|
|
mutateElement(container, {
|
|
mutateElement(container, {
|
|
boundElements: [{ type: "text", id: text.id }],
|
|
boundElements: [{ type: "text", id: text.id }],
|
|
});
|
|
});
|
|
- h.elements = [container, text];
|
|
|
|
|
|
+ API.setElements([container, text]);
|
|
|
|
|
|
API.setSelectedElements([container]);
|
|
API.setSelectedElements([container]);
|
|
- const fontSize = getStatsProperty("F")?.querySelector(
|
|
|
|
|
|
+ const fontSize = UI.queryStatsProperty("F")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(fontSize).toBeDefined();
|
|
expect(fontSize).toBeDefined();
|
|
|
|
|
|
- editInput(fontSize, "40");
|
|
|
|
|
|
+ UI.updateInput(fontSize, "40");
|
|
|
|
|
|
expect(text.fontSize).toBe(40);
|
|
expect(text.fontSize).toBe(40);
|
|
});
|
|
});
|
|
@@ -533,7 +500,7 @@ describe("stats for multiple elements", () => {
|
|
|
|
|
|
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
|
await render(<Excalidraw handleKeyboardGlobally={true} />);
|
|
|
|
|
|
- h.elements = [];
|
|
|
|
|
|
+ API.setElements([]);
|
|
|
|
|
|
fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
|
|
fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
|
|
button: 2,
|
|
button: 2,
|
|
@@ -566,7 +533,7 @@ describe("stats for multiple elements", () => {
|
|
mouse.down(-100, -100);
|
|
mouse.down(-100, -100);
|
|
mouse.up(125, 145);
|
|
mouse.up(125, 145);
|
|
|
|
|
|
- h.setState({
|
|
|
|
|
|
+ API.setAppState({
|
|
selectedElementIds: h.elements.reduce((acc, el) => {
|
|
selectedElementIds: h.elements.reduce((acc, el) => {
|
|
acc[el.id] = true;
|
|
acc[el.id] = true;
|
|
return acc;
|
|
return acc;
|
|
@@ -575,25 +542,25 @@ describe("stats for multiple elements", () => {
|
|
|
|
|
|
elementStats = stats?.querySelector("#elementStats");
|
|
elementStats = stats?.querySelector("#elementStats");
|
|
|
|
|
|
- const width = getStatsProperty("W")?.querySelector(
|
|
|
|
|
|
+ const width = UI.queryStatsProperty("W")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(width?.value).toBe("Mixed");
|
|
expect(width?.value).toBe("Mixed");
|
|
- const height = getStatsProperty("H")?.querySelector(
|
|
|
|
|
|
+ const height = UI.queryStatsProperty("H")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(height?.value).toBe("Mixed");
|
|
expect(height?.value).toBe("Mixed");
|
|
- const angle = getStatsProperty("A")?.querySelector(
|
|
|
|
|
|
+ const angle = UI.queryStatsProperty("A")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(angle.value).toBe("0");
|
|
expect(angle.value).toBe("0");
|
|
|
|
|
|
- editInput(width, "250");
|
|
|
|
|
|
+ UI.updateInput(width, "250");
|
|
h.elements.forEach((el) => {
|
|
h.elements.forEach((el) => {
|
|
expect(el.width).toBe(250);
|
|
expect(el.width).toBe(250);
|
|
});
|
|
});
|
|
|
|
|
|
- editInput(height, "450");
|
|
|
|
|
|
+ UI.updateInput(height, "450");
|
|
h.elements.forEach((el) => {
|
|
h.elements.forEach((el) => {
|
|
expect(el.height).toBe(450);
|
|
expect(el.height).toBe(450);
|
|
});
|
|
});
|
|
@@ -605,9 +572,10 @@ describe("stats for multiple elements", () => {
|
|
mouse.clickAt(20, 30);
|
|
mouse.clickAt(20, 30);
|
|
const textEditorSelector = ".excalidraw-textEditorContainer > textarea";
|
|
const textEditorSelector = ".excalidraw-textEditorContainer > textarea";
|
|
const editor = await getTextEditor(textEditorSelector, true);
|
|
const editor = await getTextEditor(textEditorSelector, true);
|
|
- await new Promise((r) => setTimeout(r, 0));
|
|
|
|
updateTextEditor(editor, "Hello!");
|
|
updateTextEditor(editor, "Hello!");
|
|
- editor.blur();
|
|
|
|
|
|
+ act(() => {
|
|
|
|
+ editor.blur();
|
|
|
|
+ });
|
|
|
|
|
|
UI.clickTool("rectangle");
|
|
UI.clickTool("rectangle");
|
|
mouse.down();
|
|
mouse.down();
|
|
@@ -619,12 +587,12 @@ describe("stats for multiple elements", () => {
|
|
width: 150,
|
|
width: 150,
|
|
});
|
|
});
|
|
|
|
|
|
- h.elements = [...h.elements, frame];
|
|
|
|
|
|
+ API.setElements([...h.elements, frame]);
|
|
|
|
|
|
const text = h.elements.find((el) => el.type === "text");
|
|
const text = h.elements.find((el) => el.type === "text");
|
|
const rectangle = h.elements.find((el) => el.type === "rectangle");
|
|
const rectangle = h.elements.find((el) => el.type === "rectangle");
|
|
|
|
|
|
- h.setState({
|
|
|
|
|
|
+ API.setAppState({
|
|
selectedElementIds: h.elements.reduce((acc, el) => {
|
|
selectedElementIds: h.elements.reduce((acc, el) => {
|
|
acc[el.id] = true;
|
|
acc[el.id] = true;
|
|
return acc;
|
|
return acc;
|
|
@@ -633,39 +601,39 @@ describe("stats for multiple elements", () => {
|
|
|
|
|
|
elementStats = stats?.querySelector("#elementStats");
|
|
elementStats = stats?.querySelector("#elementStats");
|
|
|
|
|
|
- const width = getStatsProperty("W")?.querySelector(
|
|
|
|
|
|
+ const width = UI.queryStatsProperty("W")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(width).toBeDefined();
|
|
expect(width).toBeDefined();
|
|
expect(width.value).toBe("Mixed");
|
|
expect(width.value).toBe("Mixed");
|
|
|
|
|
|
- const height = getStatsProperty("H")?.querySelector(
|
|
|
|
|
|
+ const height = UI.queryStatsProperty("H")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(height).toBeDefined();
|
|
expect(height).toBeDefined();
|
|
expect(height.value).toBe("Mixed");
|
|
expect(height.value).toBe("Mixed");
|
|
|
|
|
|
- const angle = getStatsProperty("A")?.querySelector(
|
|
|
|
|
|
+ const angle = UI.queryStatsProperty("A")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(angle).toBeDefined();
|
|
expect(angle).toBeDefined();
|
|
expect(angle.value).toBe("0");
|
|
expect(angle.value).toBe("0");
|
|
|
|
|
|
- const fontSize = getStatsProperty("F")?.querySelector(
|
|
|
|
|
|
+ const fontSize = UI.queryStatsProperty("F")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(fontSize).toBeDefined();
|
|
expect(fontSize).toBeDefined();
|
|
|
|
|
|
// changing width does not affect text
|
|
// changing width does not affect text
|
|
- editInput(width, "200");
|
|
|
|
|
|
+ UI.updateInput(width, "200");
|
|
|
|
|
|
expect(rectangle?.width).toBe(200);
|
|
expect(rectangle?.width).toBe(200);
|
|
expect(frame.width).toBe(200);
|
|
expect(frame.width).toBe(200);
|
|
expect(text?.width).not.toBe(200);
|
|
expect(text?.width).not.toBe(200);
|
|
|
|
|
|
- editInput(angle, "40");
|
|
|
|
|
|
+ UI.updateInput(angle, "40");
|
|
|
|
|
|
- const angleInRadian = degreeToRadian(40);
|
|
|
|
|
|
+ const angleInRadian = degreesToRadians(40 as Degrees);
|
|
expect(rectangle?.angle).toBeCloseTo(angleInRadian, 4);
|
|
expect(rectangle?.angle).toBeCloseTo(angleInRadian, 4);
|
|
expect(text?.angle).toBeCloseTo(angleInRadian, 4);
|
|
expect(text?.angle).toBeCloseTo(angleInRadian, 4);
|
|
expect(frame.angle).toBe(0);
|
|
expect(frame.angle).toBe(0);
|
|
@@ -686,7 +654,7 @@ describe("stats for multiple elements", () => {
|
|
mouse.click();
|
|
mouse.click();
|
|
});
|
|
});
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionGroup);
|
|
|
|
|
|
+ API.executeAction(actionGroup);
|
|
};
|
|
};
|
|
|
|
|
|
createAndSelectGroup();
|
|
createAndSelectGroup();
|
|
@@ -696,58 +664,58 @@ describe("stats for multiple elements", () => {
|
|
|
|
|
|
elementStats = stats?.querySelector("#elementStats");
|
|
elementStats = stats?.querySelector("#elementStats");
|
|
|
|
|
|
- const x = getStatsProperty("X")?.querySelector(
|
|
|
|
|
|
+ const x = UI.queryStatsProperty("X")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
|
|
|
|
expect(x).toBeDefined();
|
|
expect(x).toBeDefined();
|
|
expect(Number(x.value)).toBe(x1);
|
|
expect(Number(x.value)).toBe(x1);
|
|
|
|
|
|
- editInput(x, "300");
|
|
|
|
|
|
+ UI.updateInput(x, "300");
|
|
|
|
|
|
expect(h.elements[0].x).toBe(300);
|
|
expect(h.elements[0].x).toBe(300);
|
|
expect(h.elements[1].x).toBe(400);
|
|
expect(h.elements[1].x).toBe(400);
|
|
expect(x.value).toBe("300");
|
|
expect(x.value).toBe("300");
|
|
|
|
|
|
- const y = getStatsProperty("Y")?.querySelector(
|
|
|
|
|
|
+ const y = UI.queryStatsProperty("Y")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
|
|
|
|
expect(y).toBeDefined();
|
|
expect(y).toBeDefined();
|
|
expect(Number(y.value)).toBe(y1);
|
|
expect(Number(y.value)).toBe(y1);
|
|
|
|
|
|
- editInput(y, "200");
|
|
|
|
|
|
+ UI.updateInput(y, "200");
|
|
|
|
|
|
expect(h.elements[0].y).toBe(200);
|
|
expect(h.elements[0].y).toBe(200);
|
|
expect(h.elements[1].y).toBe(300);
|
|
expect(h.elements[1].y).toBe(300);
|
|
expect(y.value).toBe("200");
|
|
expect(y.value).toBe("200");
|
|
|
|
|
|
- const width = getStatsProperty("W")?.querySelector(
|
|
|
|
|
|
+ const width = UI.queryStatsProperty("W")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(width).toBeDefined();
|
|
expect(width).toBeDefined();
|
|
expect(Number(width.value)).toBe(200);
|
|
expect(Number(width.value)).toBe(200);
|
|
|
|
|
|
- const height = getStatsProperty("H")?.querySelector(
|
|
|
|
|
|
+ const height = UI.queryStatsProperty("H")?.querySelector(
|
|
".drag-input",
|
|
".drag-input",
|
|
) as HTMLInputElement;
|
|
) as HTMLInputElement;
|
|
expect(height).toBeDefined();
|
|
expect(height).toBeDefined();
|
|
expect(Number(height.value)).toBe(200);
|
|
expect(Number(height.value)).toBe(200);
|
|
|
|
|
|
- editInput(width, "400");
|
|
|
|
|
|
+ UI.updateInput(width, "400");
|
|
|
|
|
|
[x1, y1, x2, y2] = getCommonBounds(elementsInGroup);
|
|
[x1, y1, x2, y2] = getCommonBounds(elementsInGroup);
|
|
let newGroupWidth = x2 - x1;
|
|
let newGroupWidth = x2 - x1;
|
|
|
|
|
|
expect(newGroupWidth).toBeCloseTo(400, 4);
|
|
expect(newGroupWidth).toBeCloseTo(400, 4);
|
|
|
|
|
|
- editInput(width, "300");
|
|
|
|
|
|
+ UI.updateInput(width, "300");
|
|
|
|
|
|
[x1, y1, x2, y2] = getCommonBounds(elementsInGroup);
|
|
[x1, y1, x2, y2] = getCommonBounds(elementsInGroup);
|
|
newGroupWidth = x2 - x1;
|
|
newGroupWidth = x2 - x1;
|
|
expect(newGroupWidth).toBeCloseTo(300, 4);
|
|
expect(newGroupWidth).toBeCloseTo(300, 4);
|
|
|
|
|
|
- editInput(height, "500");
|
|
|
|
|
|
+ UI.updateInput(height, "500");
|
|
|
|
|
|
[x1, y1, x2, y2] = getCommonBounds(elementsInGroup);
|
|
[x1, y1, x2, y2] = getCommonBounds(elementsInGroup);
|
|
const newGroupHeight = y2 - y1;
|
|
const newGroupHeight = y2 - y1;
|