|
@@ -1,22 +1,53 @@
|
|
import ReactDOM from "react-dom";
|
|
import ReactDOM from "react-dom";
|
|
-import { render } from "./test-utils";
|
|
|
|
-import App from "../components/App";
|
|
|
|
-import { defaultLang, setLanguage } from "../i18n";
|
|
|
|
|
|
+import { GlobalTestState, render, waitFor } from "./test-utils";
|
|
import { UI, Pointer } from "./helpers/ui";
|
|
import { UI, Pointer } from "./helpers/ui";
|
|
import { API } from "./helpers/api";
|
|
import { API } from "./helpers/api";
|
|
import { actionFlipHorizontal, actionFlipVertical } from "../actions";
|
|
import { actionFlipHorizontal, actionFlipVertical } from "../actions";
|
|
|
|
+import { getElementAbsoluteCoords } from "../element";
|
|
|
|
+import {
|
|
|
|
+ ExcalidrawElement,
|
|
|
|
+ ExcalidrawImageElement,
|
|
|
|
+ ExcalidrawLinearElement,
|
|
|
|
+ FileId,
|
|
|
|
+} from "../element/types";
|
|
|
|
+import { newLinearElement } from "../element";
|
|
|
|
+import ExcalidrawApp from "../excalidraw-app";
|
|
|
|
+import { mutateElement } from "../element/mutateElement";
|
|
|
|
+import { NormalizedZoomValue } from "../types";
|
|
|
|
+import { ROUNDNESS } from "../constants";
|
|
|
|
|
|
const { h } = window;
|
|
const { h } = window;
|
|
|
|
|
|
const mouse = new Pointer("mouse");
|
|
const mouse = new Pointer("mouse");
|
|
-
|
|
|
|
|
|
+jest.mock("../data/blob", () => {
|
|
|
|
+ const originalModule = jest.requireActual("../data/blob");
|
|
|
|
+
|
|
|
|
+ //Prevent Node.js modules errors (document is not defined etc...)
|
|
|
|
+ return {
|
|
|
|
+ __esModule: true,
|
|
|
|
+ ...originalModule,
|
|
|
|
+ resizeImageFile: (imageFile: File) => imageFile,
|
|
|
|
+ generateIdFromFile: () => "fileId" as FileId,
|
|
|
|
+ };
|
|
|
|
+});
|
|
beforeEach(async () => {
|
|
beforeEach(async () => {
|
|
// Unmount ReactDOM from root
|
|
// Unmount ReactDOM from root
|
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
|
|
|
+
|
|
mouse.reset();
|
|
mouse.reset();
|
|
|
|
+ localStorage.clear();
|
|
|
|
+ sessionStorage.clear();
|
|
|
|
+ jest.clearAllMocks();
|
|
|
|
|
|
- await setLanguage(defaultLang);
|
|
|
|
- await render(<App />);
|
|
|
|
|
|
+ Object.assign(document, {
|
|
|
|
+ elementFromPoint: () => GlobalTestState.canvas,
|
|
|
|
+ });
|
|
|
|
+ await render(<ExcalidrawApp />);
|
|
|
|
+ h.setState({
|
|
|
|
+ zoom: {
|
|
|
|
+ value: 1 as NormalizedZoomValue,
|
|
|
|
+ },
|
|
|
|
+ });
|
|
});
|
|
});
|
|
|
|
|
|
const createAndSelectOneRectangle = (angle: number = 0) => {
|
|
const createAndSelectOneRectangle = (angle: number = 0) => {
|
|
@@ -79,593 +110,676 @@ const createAndReturnOneDraw = (angle: number = 0) => {
|
|
});
|
|
});
|
|
};
|
|
};
|
|
|
|
|
|
-const FLIP_PRECISION_DECIMALS = 7;
|
|
|
|
-
|
|
|
|
-// Rectangle element
|
|
|
|
-
|
|
|
|
-it("flips an unrotated rectangle horizontally correctly", () => {
|
|
|
|
- createAndSelectOneRectangle();
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
|
|
+const createLinearElementWithCurveInsideMinMaxPoints = (
|
|
|
|
+ type: "line" | "arrow",
|
|
|
|
+ extraProps: any = {},
|
|
|
|
+) => {
|
|
|
|
+ return newLinearElement({
|
|
|
|
+ type,
|
|
|
|
+ x: 2256.910668124894,
|
|
|
|
+ y: -2412.5069664197654,
|
|
|
|
+ width: 1750.4888916015625,
|
|
|
|
+ height: 410.51605224609375,
|
|
|
|
+ angle: 0,
|
|
|
|
+ strokeColor: "#000000",
|
|
|
|
+ backgroundColor: "#fa5252",
|
|
|
|
+ fillStyle: "hachure",
|
|
|
|
+ strokeWidth: 1,
|
|
|
|
+ strokeStyle: "solid",
|
|
|
|
+ roughness: 1,
|
|
|
|
+ opacity: 100,
|
|
|
|
+ groupIds: [],
|
|
|
|
+ roundness: { type: ROUNDNESS.PROPORTIONAL_RADIUS },
|
|
|
|
+ boundElements: null,
|
|
|
|
+ link: null,
|
|
|
|
+ locked: false,
|
|
|
|
+ points: [
|
|
|
|
+ [0, 0],
|
|
|
|
+ [-922.4761962890625, 300.3277587890625],
|
|
|
|
+ [828.0126953125, 410.51605224609375],
|
|
|
|
+ ],
|
|
|
|
+ startArrowhead: null,
|
|
|
|
+ endArrowhead: null,
|
|
|
|
+ });
|
|
|
|
+};
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
|
|
+const createLinearElementsWithCurveOutsideMinMaxPoints = (
|
|
|
|
+ type: "line" | "arrow",
|
|
|
|
+ extraProps: any = {},
|
|
|
|
+) => {
|
|
|
|
+ return newLinearElement({
|
|
|
|
+ type,
|
|
|
|
+ x: -1388.6555370382996,
|
|
|
|
+ y: 1037.698247710191,
|
|
|
|
+ width: 591.2804897585779,
|
|
|
|
+ height: 69.32871961377737,
|
|
|
|
+ angle: 0,
|
|
|
|
+ strokeColor: "#000000",
|
|
|
|
+ backgroundColor: "transparent",
|
|
|
|
+ fillStyle: "hachure",
|
|
|
|
+ strokeWidth: 1,
|
|
|
|
+ strokeStyle: "solid",
|
|
|
|
+ roughness: 1,
|
|
|
|
+ opacity: 100,
|
|
|
|
+ groupIds: [],
|
|
|
|
+ roundness: { type: ROUNDNESS.PROPORTIONAL_RADIUS },
|
|
|
|
+ boundElements: null,
|
|
|
|
+ link: null,
|
|
|
|
+ locked: false,
|
|
|
|
+ points: [
|
|
|
|
+ [0, 0],
|
|
|
|
+ [-584.1485186423079, -15.365636022723947],
|
|
|
|
+ [-591.2804897585779, 36.09360810181511],
|
|
|
|
+ [-148.56510566829502, 53.96308359105342],
|
|
|
|
+ ],
|
|
|
|
+ startArrowhead: null,
|
|
|
|
+ endArrowhead: null,
|
|
|
|
+ ...extraProps,
|
|
|
|
+ });
|
|
|
|
+};
|
|
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+const checkElementsBoundingBox = async (
|
|
|
|
+ element1: ExcalidrawElement,
|
|
|
|
+ element2: ExcalidrawElement,
|
|
|
|
+ toleranceInPx: number = 0,
|
|
|
|
+) => {
|
|
|
|
+ const [x1, y1, x2, y2] = getElementAbsoluteCoords(element1);
|
|
|
|
+
|
|
|
|
+ const [x12, y12, x22, y22] = getElementAbsoluteCoords(element2);
|
|
|
|
+
|
|
|
|
+ debugger;
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ // Check if width and height did not change
|
|
|
|
+ expect(x1 - toleranceInPx <= x12 && x12 <= x1 + toleranceInPx).toBeTruthy();
|
|
|
|
+ expect(y1 - toleranceInPx <= y12 && y12 <= y1 + toleranceInPx).toBeTruthy();
|
|
|
|
+ expect(x2 - toleranceInPx <= x22 && x22 <= x2 + toleranceInPx).toBeTruthy();
|
|
|
|
+ expect(y2 - toleranceInPx <= y22 && y22 <= y2 + toleranceInPx).toBeTruthy();
|
|
|
|
+ });
|
|
|
|
+};
|
|
|
|
|
|
|
|
+const checkHorizontalFlip = async (toleranceInPx: number = 0.00001) => {
|
|
|
|
+ const originalElement = JSON.parse(JSON.stringify(h.elements[0]));
|
|
h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
+ const newElement = h.elements[0];
|
|
|
|
+ await checkElementsBoundingBox(originalElement, newElement, toleranceInPx);
|
|
|
|
+};
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips an unrotated rectangle vertically correctly", () => {
|
|
|
|
- createAndSelectOneRectangle();
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
-
|
|
|
|
- h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
-
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips a rotated rectangle horizontally correctly", () => {
|
|
|
|
- const originalAngle = (3 * Math.PI) / 4;
|
|
|
|
- const expectedAngle = (5 * Math.PI) / 4;
|
|
|
|
-
|
|
|
|
- createAndSelectOneRectangle(originalAngle);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
-
|
|
|
|
|
|
+const checkTwoPointsLineHorizontalFlip = async () => {
|
|
|
|
+ const originalElement = JSON.parse(
|
|
|
|
+ JSON.stringify(h.elements[0]),
|
|
|
|
+ ) as ExcalidrawLinearElement;
|
|
h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
+ const newElement = h.elements[0] as ExcalidrawLinearElement;
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ expect(originalElement.points[0][0]).toEqual(
|
|
|
|
+ newElement.points[0][0] !== 0 ? -newElement.points[0][0] : 0,
|
|
|
|
+ );
|
|
|
|
+ expect(originalElement.points[0][1]).toEqual(newElement.points[0][1]);
|
|
|
|
+ expect(originalElement.points[1][0]).toEqual(
|
|
|
|
+ newElement.points[1][0] !== 0 ? -newElement.points[1][0] : 0,
|
|
|
|
+ );
|
|
|
|
+ expect(originalElement.points[1][1]).toEqual(newElement.points[1][1]);
|
|
|
|
+ });
|
|
|
|
+};
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
-
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips a rotated rectangle vertically correctly", () => {
|
|
|
|
- const originalAngle = (3 * Math.PI) / 4;
|
|
|
|
- const expectedAgnle = Math.PI / 4;
|
|
|
|
-
|
|
|
|
- createAndSelectOneRectangle(originalAngle);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
-
|
|
|
|
|
|
+const checkTwoPointsLineVerticalFlip = async () => {
|
|
|
|
+ const originalElement = JSON.parse(
|
|
|
|
+ JSON.stringify(h.elements[0]),
|
|
|
|
+ ) as ExcalidrawLinearElement;
|
|
h.app.actionManager.executeAction(actionFlipVertical);
|
|
h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
+ const newElement = h.elements[0] as ExcalidrawLinearElement;
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ expect(originalElement.points[0][0]).toEqual(
|
|
|
|
+ newElement.points[0][0] !== 0 ? -newElement.points[0][0] : 0,
|
|
|
|
+ );
|
|
|
|
+ expect(originalElement.points[0][1]).toEqual(newElement.points[0][1]);
|
|
|
|
+ expect(originalElement.points[1][0]).toEqual(
|
|
|
|
+ newElement.points[1][0] !== 0 ? -newElement.points[1][0] : 0,
|
|
|
|
+ );
|
|
|
|
+ expect(originalElement.points[1][1]).toEqual(newElement.points[1][1]);
|
|
|
|
+ });
|
|
|
|
+};
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
-
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAgnle);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-// Diamond element
|
|
|
|
-
|
|
|
|
-it("flips an unrotated diamond horizontally correctly", () => {
|
|
|
|
- createAndSelectOneDiamond();
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
-
|
|
|
|
|
|
+const checkRotatedHorizontalFlip = async (
|
|
|
|
+ expectedAngle: number,
|
|
|
|
+ toleranceInPx: number = 0.00001,
|
|
|
|
+) => {
|
|
|
|
+ const originalElement = JSON.parse(JSON.stringify(h.elements[0]));
|
|
h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
+ const newElement = h.elements[0];
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ expect(newElement.angle).toBeCloseTo(expectedAngle);
|
|
|
|
+ });
|
|
|
|
+ await checkElementsBoundingBox(originalElement, newElement, toleranceInPx);
|
|
|
|
+};
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips an unrotated diamond vertically correctly", () => {
|
|
|
|
- createAndSelectOneDiamond();
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
-
|
|
|
|
|
|
+const checkRotatedVerticalFlip = async (
|
|
|
|
+ expectedAngle: number,
|
|
|
|
+ toleranceInPx: number = 0.00001,
|
|
|
|
+) => {
|
|
|
|
+ const originalElement = JSON.parse(JSON.stringify(h.elements[0]));
|
|
h.app.actionManager.executeAction(actionFlipVertical);
|
|
h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
+ const newElement = h.elements[0];
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ expect(newElement.angle).toBeCloseTo(expectedAngle);
|
|
|
|
+ });
|
|
|
|
+ await checkElementsBoundingBox(originalElement, newElement, toleranceInPx);
|
|
|
|
+};
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips a rotated diamond horizontally correctly", () => {
|
|
|
|
- const originalAngle = (5 * Math.PI) / 4;
|
|
|
|
- const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
-
|
|
|
|
- createAndSelectOneDiamond(originalAngle);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
-
|
|
|
|
- h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
-
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
-
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips a rotated diamond vertically correctly", () => {
|
|
|
|
- const originalAngle = (5 * Math.PI) / 4;
|
|
|
|
- const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
-
|
|
|
|
- createAndSelectOneDiamond(originalAngle);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+const checkVerticalFlip = async (toleranceInPx: number = 0.00001) => {
|
|
|
|
+ const originalElement = JSON.parse(JSON.stringify(h.elements[0]));
|
|
|
|
|
|
h.app.actionManager.executeAction(actionFlipVertical);
|
|
h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
-
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-// Ellipse element
|
|
|
|
-
|
|
|
|
-it("flips an unrotated ellipse horizontally correctly", () => {
|
|
|
|
- createAndSelectOneEllipse();
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
|
|
+ const newElement = h.elements[0];
|
|
|
|
+ await checkElementsBoundingBox(originalElement, newElement, toleranceInPx);
|
|
|
|
+};
|
|
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+const checkVerticalHorizontalFlip = async (toleranceInPx: number = 0.00001) => {
|
|
|
|
+ const originalElement = JSON.parse(JSON.stringify(h.elements[0]));
|
|
|
|
|
|
h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
+ h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
|
|
+ const newElement = h.elements[0];
|
|
|
|
+ await checkElementsBoundingBox(originalElement, newElement, toleranceInPx);
|
|
|
|
+};
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
|
|
+const TWO_POINTS_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS = 5;
|
|
|
|
+const MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS = 20;
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
-});
|
|
|
|
|
|
+// Rectangle element
|
|
|
|
+describe("rectangle", () => {
|
|
|
|
+ it("flips an unrotated rectangle horizontally correctly", async () => {
|
|
|
|
+ createAndSelectOneRectangle();
|
|
|
|
|
|
-it("flips an unrotated ellipse vertically correctly", () => {
|
|
|
|
- createAndSelectOneEllipse();
|
|
|
|
|
|
+ await checkHorizontalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
|
|
+ it("flips an unrotated rectangle vertically correctly", async () => {
|
|
|
|
+ createAndSelectOneRectangle();
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
|
|
+ await checkVerticalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+ it("flips a rotated rectangle horizontally correctly", async () => {
|
|
|
|
+ const originalAngle = (3 * Math.PI) / 4;
|
|
|
|
+ const expectedAngle = (5 * Math.PI) / 4;
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
|
|
+ createAndSelectOneRectangle(originalAngle);
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
|
|
+ await checkRotatedHorizontalFlip(expectedAngle);
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
|
|
+ it("flips a rotated rectangle vertically correctly", async () => {
|
|
|
|
+ const originalAngle = (3 * Math.PI) / 4;
|
|
|
|
+ const expectedAgnle = Math.PI / 4;
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
|
|
+ createAndSelectOneRectangle(originalAngle);
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
|
|
+ await checkRotatedVerticalFlip(expectedAgnle);
|
|
|
|
+ });
|
|
});
|
|
});
|
|
|
|
|
|
-it("flips a rotated ellipse horizontally correctly", () => {
|
|
|
|
- const originalAngle = (7 * Math.PI) / 4;
|
|
|
|
- const expectedAngle = Math.PI / 4;
|
|
|
|
-
|
|
|
|
- createAndSelectOneEllipse(originalAngle);
|
|
|
|
|
|
+// Diamond element
|
|
|
|
+describe("diamond", () => {
|
|
|
|
+ it("flips an unrotated diamond horizontally correctly", async () => {
|
|
|
|
+ createAndSelectOneDiamond();
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
|
|
+ await checkHorizontalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
|
|
+ it("flips an unrotated diamond vertically correctly", async () => {
|
|
|
|
+ createAndSelectOneDiamond();
|
|
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+ await checkVerticalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
|
|
+ it("flips a rotated diamond horizontally correctly", async () => {
|
|
|
|
+ const originalAngle = (5 * Math.PI) / 4;
|
|
|
|
+ const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
|
|
+ createAndSelectOneDiamond(originalAngle);
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
|
|
+ await checkRotatedHorizontalFlip(expectedAngle);
|
|
|
|
+ });
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
|
|
+ it("flips a rotated diamond vertically correctly", async () => {
|
|
|
|
+ const originalAngle = (5 * Math.PI) / 4;
|
|
|
|
+ const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
|
|
+ createAndSelectOneDiamond(originalAngle);
|
|
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
|
|
+ await checkRotatedVerticalFlip(expectedAngle);
|
|
|
|
+ });
|
|
});
|
|
});
|
|
|
|
|
|
-it("flips a rotated ellipse vertically correctly", () => {
|
|
|
|
- const originalAngle = (7 * Math.PI) / 4;
|
|
|
|
- const expectedAngle = (5 * Math.PI) / 4;
|
|
|
|
-
|
|
|
|
- createAndSelectOneEllipse(originalAngle);
|
|
|
|
|
|
+// Ellipse element
|
|
|
|
+describe("ellipse", () => {
|
|
|
|
+ it("flips an unrotated ellipse horizontally correctly", async () => {
|
|
|
|
+ createAndSelectOneEllipse();
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
|
|
+ await checkHorizontalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
|
|
+ it("flips an unrotated ellipse vertically correctly", async () => {
|
|
|
|
+ createAndSelectOneEllipse();
|
|
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+ await checkVerticalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
|
|
+ it("flips a rotated ellipse horizontally correctly", async () => {
|
|
|
|
+ const originalAngle = (7 * Math.PI) / 4;
|
|
|
|
+ const expectedAngle = Math.PI / 4;
|
|
|
|
|
|
- // Check if x position did not change
|
|
|
|
- expect(API.getSelectedElements()[0].x).toEqual(0);
|
|
|
|
|
|
+ createAndSelectOneEllipse(originalAngle);
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].y).toEqual(0);
|
|
|
|
|
|
+ await checkRotatedHorizontalFlip(expectedAngle);
|
|
|
|
+ });
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toEqual(originalWidth);
|
|
|
|
|
|
+ it("flips a rotated ellipse vertically correctly", async () => {
|
|
|
|
+ const originalAngle = (7 * Math.PI) / 4;
|
|
|
|
+ const expectedAngle = (5 * Math.PI) / 4;
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].height).toEqual(originalHeight);
|
|
|
|
|
|
+ createAndSelectOneEllipse(originalAngle);
|
|
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
|
|
+ await checkRotatedVerticalFlip(expectedAngle);
|
|
|
|
+ });
|
|
});
|
|
});
|
|
|
|
|
|
// Arrow element
|
|
// Arrow element
|
|
|
|
+describe("arrow", () => {
|
|
|
|
+ it("flips an unrotated arrow horizontally with line inside min/max points bounds", async () => {
|
|
|
|
+ const arrow = createLinearElementWithCurveInsideMinMaxPoints("arrow");
|
|
|
|
+ h.app.scene.replaceAllElements([arrow]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [arrow.id]: true } });
|
|
|
|
+ await checkHorizontalFlip(
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
-it("flips an unrotated arrow horizontally correctly", () => {
|
|
|
|
- createAndSelectOneArrow();
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
-
|
|
|
|
- h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toBeCloseTo(
|
|
|
|
- originalWidth,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toBeCloseTo(
|
|
|
|
- originalHeight,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips an unrotated arrow vertically correctly", () => {
|
|
|
|
- createAndSelectOneArrow();
|
|
|
|
|
|
+ it("flips an unrotated arrow vertically with line inside min/max points bounds", async () => {
|
|
|
|
+ const arrow = createLinearElementWithCurveInsideMinMaxPoints("arrow");
|
|
|
|
+ h.app.scene.replaceAllElements([arrow]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [arrow.id]: true } });
|
|
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+ await checkVerticalFlip(50);
|
|
|
|
+ });
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
|
|
+ it("flips a rotated arrow horizontally with line inside min/max points bounds", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
+ const line = createLinearElementWithCurveInsideMinMaxPoints("arrow");
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.state.selectedElementIds[line.id] = true;
|
|
|
|
+ mutateElement(line, {
|
|
|
|
+ angle: originalAngle,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ await checkRotatedHorizontalFlip(
|
|
|
|
+ expectedAngle,
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toBeCloseTo(
|
|
|
|
- originalWidth,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
|
|
+ it("flips a rotated arrow vertically with line inside min/max points bounds", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
+ const line = createLinearElementWithCurveInsideMinMaxPoints("arrow");
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.state.selectedElementIds[line.id] = true;
|
|
|
|
+ mutateElement(line, {
|
|
|
|
+ angle: originalAngle,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ await checkRotatedVerticalFlip(
|
|
|
|
+ expectedAngle,
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].height).toBeCloseTo(
|
|
|
|
- originalHeight,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
-});
|
|
|
|
|
|
+ //TODO: elements with curve outside minMax points have a wrong bounding box!!!
|
|
|
|
+ it.skip("flips an unrotated arrow horizontally with line outside min/max points bounds", async () => {
|
|
|
|
+ const arrow = createLinearElementsWithCurveOutsideMinMaxPoints("arrow");
|
|
|
|
+ h.app.scene.replaceAllElements([arrow]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [arrow.id]: true } });
|
|
|
|
|
|
-//@TODO fix the tests with rotation
|
|
|
|
-it.skip("flips a rotated arrow horizontally correctly", () => {
|
|
|
|
- const originalAngle = Math.PI / 4;
|
|
|
|
- const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
- createAndSelectOneArrow(originalAngle);
|
|
|
|
|
|
+ await checkHorizontalFlip(
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+ //TODO: elements with curve outside minMax points have a wrong bounding box!!!
|
|
|
|
+ it.skip("flips a rotated arrow horizontally with line outside min/max points bounds", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
+ const line = createLinearElementsWithCurveOutsideMinMaxPoints("arrow");
|
|
|
|
+ mutateElement(line, { angle: originalAngle });
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [line.id]: true } });
|
|
|
|
+
|
|
|
|
+ await checkRotatedVerticalFlip(
|
|
|
|
+ expectedAngle,
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
|
|
+ //TODO: elements with curve outside minMax points have a wrong bounding box!!!
|
|
|
|
+ it.skip("flips an unrotated arrow vertically with line outside min/max points bounds", async () => {
|
|
|
|
+ const arrow = createLinearElementsWithCurveOutsideMinMaxPoints("arrow");
|
|
|
|
+ h.app.scene.replaceAllElements([arrow]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [arrow.id]: true } });
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toBeCloseTo(
|
|
|
|
- originalWidth,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toBeCloseTo(
|
|
|
|
- originalHeight,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
-});
|
|
|
|
|
|
+ await checkVerticalFlip(MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS);
|
|
|
|
+ });
|
|
|
|
|
|
-it.skip("flips a rotated arrow vertically correctly", () => {
|
|
|
|
- const originalAngle = Math.PI / 4;
|
|
|
|
- const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
- createAndSelectOneArrow(originalAngle);
|
|
|
|
|
|
+ //TODO: elements with curve outside minMax points have a wrong bounding box!!!
|
|
|
|
+ it.skip("flips a rotated arrow vertically with line outside min/max points bounds", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
+ const line = createLinearElementsWithCurveOutsideMinMaxPoints("arrow");
|
|
|
|
+ mutateElement(line, { angle: originalAngle });
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [line.id]: true } });
|
|
|
|
+
|
|
|
|
+ await checkRotatedVerticalFlip(
|
|
|
|
+ expectedAngle,
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+ it("flips an unrotated arrow horizontally correctly", async () => {
|
|
|
|
+ createAndSelectOneArrow();
|
|
|
|
+ await checkHorizontalFlip(
|
|
|
|
+ TWO_POINTS_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
|
|
+ it("flips an unrotated arrow vertically correctly", async () => {
|
|
|
|
+ createAndSelectOneArrow();
|
|
|
|
+ await checkVerticalFlip(TWO_POINTS_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS);
|
|
|
|
+ });
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toBeCloseTo(
|
|
|
|
- originalWidth,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
|
|
+ it("flips a two points arrow horizontally correctly", async () => {
|
|
|
|
+ createAndSelectOneArrow();
|
|
|
|
+ await checkTwoPointsLineHorizontalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].height).toBeCloseTo(
|
|
|
|
- originalHeight,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
|
|
+ it("flips a two points arrow vertically correctly", async () => {
|
|
|
|
+ createAndSelectOneArrow();
|
|
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
|
|
+ await checkTwoPointsLineVerticalFlip();
|
|
|
|
+ });
|
|
});
|
|
});
|
|
|
|
|
|
// Line element
|
|
// Line element
|
|
|
|
+describe("line", () => {
|
|
|
|
+ it("flips an unrotated line horizontally with line inside min/max points bounds", async () => {
|
|
|
|
+ const line = createLinearElementWithCurveInsideMinMaxPoints("line");
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [line.id]: true } });
|
|
|
|
+
|
|
|
|
+ await checkHorizontalFlip(
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
-it("flips an unrotated line horizontally correctly", () => {
|
|
|
|
- createAndSelectOneLine();
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
-
|
|
|
|
- h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toBeCloseTo(
|
|
|
|
- originalWidth,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toBeCloseTo(
|
|
|
|
- originalHeight,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips an unrotated line vertically correctly", () => {
|
|
|
|
- createAndSelectOneLine();
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
-
|
|
|
|
- h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toBeCloseTo(
|
|
|
|
- originalWidth,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- expect(API.getSelectedElements()[0].height).toBeCloseTo(
|
|
|
|
- originalHeight,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it.skip("flips a rotated line horizontally correctly", () => {
|
|
|
|
- const originalAngle = Math.PI / 4;
|
|
|
|
- const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
-
|
|
|
|
- createAndSelectOneLine(originalAngle);
|
|
|
|
-
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+ it("flips an unrotated line vertically with line inside min/max points bounds", async () => {
|
|
|
|
+ const line = createLinearElementWithCurveInsideMinMaxPoints("line");
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [line.id]: true } });
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
|
|
+ await checkVerticalFlip(MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS);
|
|
|
|
+ });
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toBeCloseTo(
|
|
|
|
- originalWidth,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
|
|
+ it("flips an unrotated line horizontally correctly", async () => {
|
|
|
|
+ createAndSelectOneLine();
|
|
|
|
+ await checkHorizontalFlip(
|
|
|
|
+ TWO_POINTS_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
+ //TODO: elements with curve outside minMax points have a wrong bounding box
|
|
|
|
+ it.skip("flips an unrotated line horizontally with line outside min/max points bounds", async () => {
|
|
|
|
+ const line = createLinearElementsWithCurveOutsideMinMaxPoints("line");
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [line.id]: true } });
|
|
|
|
+
|
|
|
|
+ await checkHorizontalFlip(
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].height).toBeCloseTo(
|
|
|
|
- originalHeight,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
|
|
+ //TODO: elements with curve outside minMax points have a wrong bounding box
|
|
|
|
+ it.skip("flips an unrotated line vertically with line outside min/max points bounds", async () => {
|
|
|
|
+ const line = createLinearElementsWithCurveOutsideMinMaxPoints("line");
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [line.id]: true } });
|
|
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
-});
|
|
|
|
|
|
+ await checkVerticalFlip(MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS);
|
|
|
|
+ });
|
|
|
|
|
|
-it.skip("flips a rotated line vertically correctly", () => {
|
|
|
|
- const originalAngle = Math.PI / 4;
|
|
|
|
- const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
|
|
+ //TODO: elements with curve outside minMax points have a wrong bounding box
|
|
|
|
+ it.skip("flips a rotated line horizontally with line outside min/max points bounds", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
+ const line = createLinearElementsWithCurveOutsideMinMaxPoints("line");
|
|
|
|
+ mutateElement(line, { angle: originalAngle });
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [line.id]: true } });
|
|
|
|
+
|
|
|
|
+ await checkRotatedHorizontalFlip(
|
|
|
|
+ expectedAngle,
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- createAndSelectOneLine(originalAngle);
|
|
|
|
|
|
+ //TODO: elements with curve outside minMax points have a wrong bounding box
|
|
|
|
+ it.skip("flips a rotated line vertically with line outside min/max points bounds", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
+ const line = createLinearElementsWithCurveOutsideMinMaxPoints("line");
|
|
|
|
+ mutateElement(line, { angle: originalAngle });
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.setState({ selectedElementIds: { [line.id]: true } });
|
|
|
|
+
|
|
|
|
+ await checkRotatedVerticalFlip(
|
|
|
|
+ expectedAngle,
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- const originalWidth = API.getSelectedElements()[0].width;
|
|
|
|
- const originalHeight = API.getSelectedElements()[0].height;
|
|
|
|
|
|
+ it("flips an unrotated line vertically correctly", async () => {
|
|
|
|
+ createAndSelectOneLine();
|
|
|
|
+ await checkVerticalFlip(TWO_POINTS_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS);
|
|
|
|
+ });
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
|
|
+ it("flips a rotated line horizontally with line inside min/max points bounds", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
+ const line = createLinearElementWithCurveInsideMinMaxPoints("line");
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.state.selectedElementIds[line.id] = true;
|
|
|
|
+ mutateElement(line, {
|
|
|
|
+ angle: originalAngle,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ await checkRotatedHorizontalFlip(
|
|
|
|
+ expectedAngle,
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(API.getSelectedElements()[0].width).toBeCloseTo(
|
|
|
|
- originalWidth,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
|
|
+ it("flips a rotated line vertically with line inside min/max points bounds", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
+ const line = createLinearElementWithCurveInsideMinMaxPoints("line");
|
|
|
|
+ h.app.scene.replaceAllElements([line]);
|
|
|
|
+ h.app.state.selectedElementIds[line.id] = true;
|
|
|
|
+ mutateElement(line, {
|
|
|
|
+ angle: originalAngle,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ await checkRotatedVerticalFlip(
|
|
|
|
+ expectedAngle,
|
|
|
|
+ MULTIPOINT_LINEAR_ELEMENT_FLIP_TOLERANCE_IN_PIXELS,
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElements()[0].height).toBeCloseTo(
|
|
|
|
- originalHeight,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
|
|
+ it("flips a two points line horizontally correctly", async () => {
|
|
|
|
+ createAndSelectOneLine();
|
|
|
|
+ await checkTwoPointsLineHorizontalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElements()[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
|
|
+ it("flips a two points line vertically correctly", async () => {
|
|
|
|
+ createAndSelectOneLine();
|
|
|
|
+ await checkTwoPointsLineVerticalFlip();
|
|
|
|
+ });
|
|
});
|
|
});
|
|
|
|
|
|
// Draw element
|
|
// Draw element
|
|
|
|
+describe("freedraw", () => {
|
|
|
|
+ it("flips an unrotated drawing horizontally correctly", async () => {
|
|
|
|
+ const draw = createAndReturnOneDraw();
|
|
|
|
+ // select draw, since not done automatically
|
|
|
|
+ h.state.selectedElementIds[draw.id] = true;
|
|
|
|
+ await checkHorizontalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
-it("flips an unrotated drawing horizontally correctly", () => {
|
|
|
|
- const draw = createAndReturnOneDraw();
|
|
|
|
- // select draw, since not done automatically
|
|
|
|
- h.state.selectedElementIds[draw.id] = true;
|
|
|
|
-
|
|
|
|
- const originalWidth = draw.width;
|
|
|
|
- const originalHeight = draw.height;
|
|
|
|
-
|
|
|
|
- h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(draw.width).toBeCloseTo(originalWidth, FLIP_PRECISION_DECIMALS);
|
|
|
|
-
|
|
|
|
- expect(draw.height).toBeCloseTo(originalHeight, FLIP_PRECISION_DECIMALS);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips an unrotated drawing vertically correctly", () => {
|
|
|
|
- const draw = createAndReturnOneDraw();
|
|
|
|
- // select draw, since not done automatically
|
|
|
|
- h.state.selectedElementIds[draw.id] = true;
|
|
|
|
-
|
|
|
|
- const originalWidth = draw.width;
|
|
|
|
- const originalHeight = draw.height;
|
|
|
|
-
|
|
|
|
- h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
-
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(draw.width).toBeCloseTo(originalWidth, FLIP_PRECISION_DECIMALS);
|
|
|
|
-
|
|
|
|
- expect(draw.height).toBeCloseTo(originalHeight, FLIP_PRECISION_DECIMALS);
|
|
|
|
-});
|
|
|
|
-
|
|
|
|
-it("flips a rotated drawing horizontally correctly", () => {
|
|
|
|
- const originalAngle = Math.PI / 4;
|
|
|
|
- const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
|
|
+ it("flips an unrotated drawing vertically correctly", async () => {
|
|
|
|
+ const draw = createAndReturnOneDraw();
|
|
|
|
+ // select draw, since not done automatically
|
|
|
|
+ h.state.selectedElementIds[draw.id] = true;
|
|
|
|
+ await checkVerticalFlip();
|
|
|
|
+ });
|
|
|
|
|
|
- const draw = createAndReturnOneDraw(originalAngle);
|
|
|
|
- // select draw, since not done automatically
|
|
|
|
- h.state.selectedElementIds[draw.id] = true;
|
|
|
|
|
|
+ it("flips a rotated drawing horizontally correctly", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
|
|
- const originalWidth = draw.width;
|
|
|
|
- const originalHeight = draw.height;
|
|
|
|
|
|
+ const draw = createAndReturnOneDraw(originalAngle);
|
|
|
|
+ // select draw, since not done automatically
|
|
|
|
+ h.state.selectedElementIds[draw.id] = true;
|
|
|
|
|
|
- h.app.actionManager.executeAction(actionFlipHorizontal);
|
|
|
|
|
|
+ await checkRotatedHorizontalFlip(expectedAngle);
|
|
|
|
+ });
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
- expect(draw.width).toBeCloseTo(originalWidth, FLIP_PRECISION_DECIMALS);
|
|
|
|
|
|
+ it("flips a rotated drawing vertically correctly", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
|
|
- expect(draw.height).toBeCloseTo(originalHeight, FLIP_PRECISION_DECIMALS);
|
|
|
|
|
|
+ const draw = createAndReturnOneDraw(originalAngle);
|
|
|
|
+ // select draw, since not done automatically
|
|
|
|
+ h.state.selectedElementIds[draw.id] = true;
|
|
|
|
|
|
- // Check angle
|
|
|
|
- expect(draw.angle).toBeCloseTo(expectedAngle);
|
|
|
|
|
|
+ await checkRotatedVerticalFlip(expectedAngle);
|
|
|
|
+ });
|
|
});
|
|
});
|
|
|
|
|
|
-it("flips a rotated drawing vertically correctly", () => {
|
|
|
|
- const originalAngle = Math.PI / 4;
|
|
|
|
- const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
-
|
|
|
|
- const draw = createAndReturnOneDraw(originalAngle);
|
|
|
|
- // select draw, since not done automatically
|
|
|
|
- h.state.selectedElementIds[draw.id] = true;
|
|
|
|
-
|
|
|
|
- const originalWidth = draw.width;
|
|
|
|
- const originalHeight = draw.height;
|
|
|
|
-
|
|
|
|
- h.app.actionManager.executeAction(actionFlipVertical);
|
|
|
|
|
|
+//image
|
|
|
|
+//TODO: currently there is no test for pixel colors at flipped positions.
|
|
|
|
+describe("image", () => {
|
|
|
|
+ const createImage = async () => {
|
|
|
|
+ const sendPasteEvent = (file?: File) => {
|
|
|
|
+ const clipboardEvent = new Event("paste", {
|
|
|
|
+ bubbles: true,
|
|
|
|
+ cancelable: true,
|
|
|
|
+ composed: true,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // set `clipboardData` properties.
|
|
|
|
+ // @ts-ignore
|
|
|
|
+ clipboardEvent.clipboardData = {
|
|
|
|
+ getData: () => window.navigator.clipboard.readText(),
|
|
|
|
+ files: [file],
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ document.dispatchEvent(clipboardEvent);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ sendPasteEvent(await API.loadFile("./fixtures/smiley_embedded_v2.png"));
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ it("flips an unrotated image horizontally correctly", async () => {
|
|
|
|
+ //paste image
|
|
|
|
+ await createImage();
|
|
|
|
+
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([1, 1]);
|
|
|
|
+ expect(API.getSelectedElements().length).toBeGreaterThan(0);
|
|
|
|
+ expect(API.getSelectedElements()[0].type).toEqual("image");
|
|
|
|
+ expect(h.app.files.fileId).toBeDefined();
|
|
|
|
+ });
|
|
|
|
+ await checkHorizontalFlip();
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([-1, 1]);
|
|
|
|
+ expect(h.elements[0].angle).toBeCloseTo(0);
|
|
|
|
+ });
|
|
|
|
|
|
- // Check if width and height did not change
|
|
|
|
|
|
+ it("flips an unrotated image vertically correctly", async () => {
|
|
|
|
+ //paste image
|
|
|
|
+ await createImage();
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([1, 1]);
|
|
|
|
+ expect(API.getSelectedElements().length).toBeGreaterThan(0);
|
|
|
|
+ expect(API.getSelectedElements()[0].type).toEqual("image");
|
|
|
|
+ expect(h.app.files.fileId).toBeDefined();
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ await checkVerticalFlip();
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([-1, 1]);
|
|
|
|
+ expect(h.elements[0].angle).toBeCloseTo(Math.PI);
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElement().width).toBeCloseTo(
|
|
|
|
- originalWidth,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
|
|
+ it("flips an rotated image horizontally correctly", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (7 * Math.PI) / 4;
|
|
|
|
+ //paste image
|
|
|
|
+ await createImage();
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([1, 1]);
|
|
|
|
+ expect(API.getSelectedElements().length).toBeGreaterThan(0);
|
|
|
|
+ expect(API.getSelectedElements()[0].type).toEqual("image");
|
|
|
|
+ expect(h.app.files.fileId).toBeDefined();
|
|
|
|
+ });
|
|
|
|
+ mutateElement(h.elements[0], {
|
|
|
|
+ angle: originalAngle,
|
|
|
|
+ });
|
|
|
|
+ await checkRotatedHorizontalFlip(expectedAngle);
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([-1, 1]);
|
|
|
|
+ });
|
|
|
|
|
|
- expect(API.getSelectedElement().height).toBeCloseTo(
|
|
|
|
- originalHeight,
|
|
|
|
- FLIP_PRECISION_DECIMALS,
|
|
|
|
- );
|
|
|
|
|
|
+ it("flips an rotated image vertically correctly", async () => {
|
|
|
|
+ const originalAngle = Math.PI / 4;
|
|
|
|
+ const expectedAngle = (3 * Math.PI) / 4;
|
|
|
|
+ //paste image
|
|
|
|
+ await createImage();
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([1, 1]);
|
|
|
|
+ expect(h.elements[0].angle).toEqual(0);
|
|
|
|
+ expect(API.getSelectedElements().length).toBeGreaterThan(0);
|
|
|
|
+ expect(API.getSelectedElements()[0].type).toEqual("image");
|
|
|
|
+ expect(h.app.files.fileId).toBeDefined();
|
|
|
|
+ });
|
|
|
|
+ mutateElement(h.elements[0], {
|
|
|
|
+ angle: originalAngle,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ await checkRotatedVerticalFlip(expectedAngle);
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([-1, 1]);
|
|
|
|
+ expect(h.elements[0].angle).toBeCloseTo(expectedAngle);
|
|
|
|
+ });
|
|
|
|
|
|
- // Check angle
|
|
|
|
- expect(API.getSelectedElement().angle).toBeCloseTo(expectedAngle);
|
|
|
|
|
|
+ it("flips an image both vertically & horizontally", async () => {
|
|
|
|
+ //paste image
|
|
|
|
+ await createImage();
|
|
|
|
+ await waitFor(() => {
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([1, 1]);
|
|
|
|
+ expect(API.getSelectedElements().length).toBeGreaterThan(0);
|
|
|
|
+ expect(API.getSelectedElements()[0].type).toEqual("image");
|
|
|
|
+ expect(h.app.files.fileId).toBeDefined();
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ await checkVerticalHorizontalFlip();
|
|
|
|
+ expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([1, 1]);
|
|
|
|
+ expect(h.elements[0].angle).toBeCloseTo(Math.PI);
|
|
|
|
+ });
|
|
});
|
|
});
|