summaryrefslogtreecommitdiffstats
path: root/packages/excalidraw/actions/actionFlip.test.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/excalidraw/actions/actionFlip.test.tsx')
-rw-r--r--packages/excalidraw/actions/actionFlip.test.tsx212
1 files changed, 212 insertions, 0 deletions
diff --git a/packages/excalidraw/actions/actionFlip.test.tsx b/packages/excalidraw/actions/actionFlip.test.tsx
new file mode 100644
index 0000000..94e4721
--- /dev/null
+++ b/packages/excalidraw/actions/actionFlip.test.tsx
@@ -0,0 +1,212 @@
+import React from "react";
+import { Excalidraw } from "../index";
+import { render } from "../tests/test-utils";
+import { API } from "../tests/helpers/api";
+import { pointFrom } from "@excalidraw/math";
+import { actionFlipHorizontal, actionFlipVertical } from "./actionFlip";
+
+const { h } = window;
+
+describe("flipping re-centers selection", () => {
+ it("elbow arrow touches group selection side yet it remains in place after multiple moves", async () => {
+ const elements = [
+ API.createElement({
+ type: "rectangle",
+ id: "rec1",
+ x: 100,
+ y: 100,
+ width: 100,
+ height: 100,
+ boundElements: [{ id: "arr", type: "arrow" }],
+ }),
+ API.createElement({
+ type: "rectangle",
+ id: "rec2",
+ x: 220,
+ y: 250,
+ width: 100,
+ height: 100,
+ boundElements: [{ id: "arr", type: "arrow" }],
+ }),
+ API.createElement({
+ type: "arrow",
+ id: "arr",
+ x: 149.9,
+ y: 95,
+ width: 156,
+ height: 239.9,
+ startBinding: {
+ elementId: "rec1",
+ focus: 0,
+ gap: 5,
+ fixedPoint: [0.49, -0.05],
+ },
+ endBinding: {
+ elementId: "rec2",
+ focus: 0,
+ gap: 5,
+ fixedPoint: [-0.05, 0.49],
+ },
+ startArrowhead: null,
+ endArrowhead: "arrow",
+ fixedSegments: null,
+ points: [
+ pointFrom(0, 0),
+ pointFrom(0, -35),
+ pointFrom(-90, -35),
+ pointFrom(-90, 204),
+ pointFrom(66, 204),
+ ],
+ elbowed: true,
+ }),
+ ];
+ await render(<Excalidraw initialData={{ elements }} />);
+
+ API.setSelectedElements(elements);
+
+ expect(Object.keys(h.state.selectedElementIds).length).toBe(3);
+
+ API.executeAction(actionFlipHorizontal);
+ API.executeAction(actionFlipHorizontal);
+ API.executeAction(actionFlipHorizontal);
+ API.executeAction(actionFlipHorizontal);
+
+ const rec1 = h.elements.find((el) => el.id === "rec1")!;
+ expect(rec1.x).toBeCloseTo(100, 0);
+ expect(rec1.y).toBeCloseTo(100, 0);
+
+ const rec2 = h.elements.find((el) => el.id === "rec2")!;
+ expect(rec2.x).toBeCloseTo(220, 0);
+ expect(rec2.y).toBeCloseTo(250, 0);
+ });
+});
+
+describe("flipping arrowheads", () => {
+ beforeEach(async () => {
+ await render(<Excalidraw />);
+ });
+
+ it("flipping bound arrow should flip arrowheads only", () => {
+ const rect = API.createElement({
+ type: "rectangle",
+ boundElements: [{ type: "arrow", id: "arrow1" }],
+ });
+ const arrow = API.createElement({
+ type: "arrow",
+ id: "arrow1",
+ startArrowhead: "arrow",
+ endArrowhead: null,
+ endBinding: {
+ elementId: rect.id,
+ focus: 0.5,
+ gap: 5,
+ },
+ });
+
+ API.setElements([rect, arrow]);
+ API.setSelectedElements([arrow]);
+
+ expect(API.getElement(arrow).startArrowhead).toBe("arrow");
+ expect(API.getElement(arrow).endArrowhead).toBe(null);
+
+ API.executeAction(actionFlipHorizontal);
+ expect(API.getElement(arrow).startArrowhead).toBe(null);
+ expect(API.getElement(arrow).endArrowhead).toBe("arrow");
+
+ API.executeAction(actionFlipHorizontal);
+ expect(API.getElement(arrow).startArrowhead).toBe("arrow");
+ expect(API.getElement(arrow).endArrowhead).toBe(null);
+
+ API.executeAction(actionFlipVertical);
+ expect(API.getElement(arrow).startArrowhead).toBe(null);
+ expect(API.getElement(arrow).endArrowhead).toBe("arrow");
+ });
+
+ it("flipping bound arrow should flip arrowheads only 2", () => {
+ const rect = API.createElement({
+ type: "rectangle",
+ boundElements: [{ type: "arrow", id: "arrow1" }],
+ });
+ const rect2 = API.createElement({
+ type: "rectangle",
+ boundElements: [{ type: "arrow", id: "arrow1" }],
+ });
+ const arrow = API.createElement({
+ type: "arrow",
+ id: "arrow1",
+ startArrowhead: "arrow",
+ endArrowhead: "circle",
+ startBinding: {
+ elementId: rect.id,
+ focus: 0.5,
+ gap: 5,
+ },
+ endBinding: {
+ elementId: rect2.id,
+ focus: 0.5,
+ gap: 5,
+ },
+ });
+
+ API.setElements([rect, rect2, arrow]);
+ API.setSelectedElements([arrow]);
+
+ expect(API.getElement(arrow).startArrowhead).toBe("arrow");
+ expect(API.getElement(arrow).endArrowhead).toBe("circle");
+
+ API.executeAction(actionFlipHorizontal);
+ expect(API.getElement(arrow).startArrowhead).toBe("circle");
+ expect(API.getElement(arrow).endArrowhead).toBe("arrow");
+
+ API.executeAction(actionFlipVertical);
+ expect(API.getElement(arrow).startArrowhead).toBe("arrow");
+ expect(API.getElement(arrow).endArrowhead).toBe("circle");
+ });
+
+ it("flipping unbound arrow shouldn't flip arrowheads", () => {
+ const arrow = API.createElement({
+ type: "arrow",
+ id: "arrow1",
+ startArrowhead: "arrow",
+ endArrowhead: "circle",
+ });
+
+ API.setElements([arrow]);
+ API.setSelectedElements([arrow]);
+
+ expect(API.getElement(arrow).startArrowhead).toBe("arrow");
+ expect(API.getElement(arrow).endArrowhead).toBe("circle");
+
+ API.executeAction(actionFlipHorizontal);
+ expect(API.getElement(arrow).startArrowhead).toBe("arrow");
+ expect(API.getElement(arrow).endArrowhead).toBe("circle");
+ });
+
+ it("flipping bound arrow shouldn't flip arrowheads if selected alongside non-arrow eleemnt", () => {
+ const rect = API.createElement({
+ type: "rectangle",
+ boundElements: [{ type: "arrow", id: "arrow1" }],
+ });
+ const arrow = API.createElement({
+ type: "arrow",
+ id: "arrow1",
+ startArrowhead: "arrow",
+ endArrowhead: null,
+ endBinding: {
+ elementId: rect.id,
+ focus: 0.5,
+ gap: 5,
+ },
+ });
+
+ API.setElements([rect, arrow]);
+ API.setSelectedElements([rect, arrow]);
+
+ expect(API.getElement(arrow).startArrowhead).toBe("arrow");
+ expect(API.getElement(arrow).endArrowhead).toBe(null);
+
+ API.executeAction(actionFlipHorizontal);
+ expect(API.getElement(arrow).startArrowhead).toBe("arrow");
+ expect(API.getElement(arrow).endArrowhead).toBe(null);
+ });
+});