From 26ef23501988105eb8a20d759625c1b5764e8906 Mon Sep 17 00:00:00 2001 From: David Luzar Date: Sat, 29 Aug 2020 14:16:40 +0200 Subject: [PATCH] rebind arrow on rotation (#2096) --- src/components/App.tsx | 12 ++-- .../regressionTests.test.tsx.snap | 56 +++++++++---------- src/tests/binding.test.tsx | 49 ++++++++++++++++ src/tests/helpers/ui.ts | 26 ++++++--- 4 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 src/tests/binding.test.tsx diff --git a/src/components/App.tsx b/src/components/App.tsx index 6762a70c..11b0b235 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -143,7 +143,6 @@ import { isLinearElementType, isBindingElement, isBindingElementType, - isBindableElement, } from "../element/typeChecks"; import { actionFinalize, actionDeleteSelected } from "../actions"; import { loadLibrary } from "../data/localStorage"; @@ -168,7 +167,6 @@ import { bindOrUnbindSelectedElements, unbindLinearElements, fixBindingsAfterDuplication, - maybeBindBindableElement, getElligibleElementForBindingElementAtCoors, fixBindingsAfterDeletion, isLinearElementSimpleAndAlreadyBound, @@ -2946,6 +2944,7 @@ class App extends React.Component { ) ) { this.maybeSuggestBindingForAll(selectedElements); + bindOrUnbindSelectedElements(selectedElements); return; } } @@ -3339,11 +3338,10 @@ class App extends React.Component { getNormalizedDimensions(draggingElement), ); - if ( - isBindingEnabled(this.state) && - isBindableElement(draggingElement) - ) { - maybeBindBindableElement(draggingElement); + if (isBindingEnabled(this.state)) { + bindOrUnbindSelectedElements( + getSelectedElements(this.scene.getElements(), this.state), + ); } } diff --git a/src/tests/__snapshots__/regressionTests.test.tsx.snap b/src/tests/__snapshots__/regressionTests.test.tsx.snap index a59f63c7..63b98010 100644 --- a/src/tests/__snapshots__/regressionTests.test.tsx.snap +++ b/src/tests/__snapshots__/regressionTests.test.tsx.snap @@ -997,7 +997,7 @@ Object { "versionNonce": 915032327, "width": 10, "x": 30, - "y": 30, + "y": 0, } `; @@ -1025,7 +1025,7 @@ Object { "versionNonce": 81784553, "width": 10, "x": 60, - "y": 60, + "y": 0, } `; @@ -1125,7 +1125,7 @@ Object { "versionNonce": 453191, "width": 10, "x": 30, - "y": 30, + "y": 0, }, ], }, @@ -1191,7 +1191,7 @@ Object { "versionNonce": 1116226695, "width": 10, "x": 30, - "y": 30, + "y": 0, }, ], }, @@ -1255,7 +1255,7 @@ Object { "versionNonce": 1116226695, "width": 10, "x": 30, - "y": 30, + "y": 0, }, ], }, @@ -1318,7 +1318,7 @@ Object { "versionNonce": 1116226695, "width": 10, "x": 30, - "y": 30, + "y": 0, }, Object { "angle": 0, @@ -1341,7 +1341,7 @@ Object { "versionNonce": 1604849351, "width": 10, "x": 60, - "y": 60, + "y": 0, }, ], }, @@ -1410,7 +1410,7 @@ Object { "versionNonce": 915032327, "width": 10, "x": 30, - "y": 30, + "y": 0, }, Object { "angle": 0, @@ -1435,7 +1435,7 @@ Object { "versionNonce": 81784553, "width": 10, "x": 60, - "y": 60, + "y": 0, }, ], }, @@ -1501,7 +1501,7 @@ Object { "versionNonce": 915032327, "width": 10, "x": 30, - "y": 30, + "y": 0, }, Object { "angle": 0, @@ -1526,7 +1526,7 @@ Object { "versionNonce": 81784553, "width": 10, "x": 60, - "y": 60, + "y": 0, }, ], }, @@ -1592,7 +1592,7 @@ Object { "versionNonce": 915032327, "width": 10, "x": 30, - "y": 30, + "y": 0, }, Object { "angle": 0, @@ -1617,7 +1617,7 @@ Object { "versionNonce": 81784553, "width": 10, "x": 60, - "y": 60, + "y": 0, }, ], }, @@ -25348,7 +25348,7 @@ Object { "versionNonce": 81784553, "width": 10, "x": 10, - "y": 10, + "y": 0, } `; @@ -25377,7 +25377,7 @@ Object { "versionNonce": 747212839, "width": 10, "x": 50, - "y": 50, + "y": 0, } `; @@ -25476,7 +25476,7 @@ Object { "versionNonce": 1278240551, "width": 10, "x": 10, - "y": 10, + "y": 0, }, ], }, @@ -25512,7 +25512,7 @@ Object { "versionNonce": 1278240551, "width": 10, "x": 10, - "y": 10, + "y": 0, }, Object { "angle": 0, @@ -25535,7 +25535,7 @@ Object { "versionNonce": 453191, "width": 10, "x": 50, - "y": 50, + "y": 0, }, ], }, @@ -25576,7 +25576,7 @@ Object { "versionNonce": 1150084233, "width": 10, "x": 10, - "y": 10, + "y": 0, }, Object { "angle": 0, @@ -25601,7 +25601,7 @@ Object { "versionNonce": 1116226695, "width": 10, "x": 50, - "y": 50, + "y": 0, }, ], }, @@ -25639,7 +25639,7 @@ Object { "versionNonce": 1150084233, "width": 10, "x": 10, - "y": 10, + "y": 0, }, Object { "angle": 0, @@ -25664,7 +25664,7 @@ Object { "versionNonce": 1116226695, "width": 10, "x": 50, - "y": 50, + "y": 0, }, Object { "angle": 0, @@ -25725,7 +25725,7 @@ Object { "versionNonce": 1150084233, "width": 10, "x": 10, - "y": 10, + "y": 0, }, Object { "angle": 0, @@ -25750,7 +25750,7 @@ Object { "versionNonce": 1116226695, "width": 10, "x": 50, - "y": 50, + "y": 0, }, Object { "angle": 0, @@ -25837,7 +25837,7 @@ Object { "versionNonce": 1150084233, "width": 10, "x": 10, - "y": 10, + "y": 0, }, Object { "angle": 0, @@ -25862,7 +25862,7 @@ Object { "versionNonce": 1116226695, "width": 10, "x": 50, - "y": 50, + "y": 0, }, Object { "angle": 0, @@ -25954,7 +25954,7 @@ Object { "versionNonce": 81784553, "width": 10, "x": 10, - "y": 10, + "y": 0, }, Object { "angle": 0, @@ -25980,7 +25980,7 @@ Object { "versionNonce": 747212839, "width": 10, "x": 50, - "y": 50, + "y": 0, }, Object { "angle": 0, diff --git a/src/tests/binding.test.tsx b/src/tests/binding.test.tsx new file mode 100644 index 00000000..b4204640 --- /dev/null +++ b/src/tests/binding.test.tsx @@ -0,0 +1,49 @@ +import React from "react"; +import { render } from "./test-utils"; +import App from "../components/App"; +import { UI, Pointer } from "./helpers/ui"; +import { getTransformHandles } from "../element/transformHandles"; + +const { h } = window; + +const mouse = new Pointer("mouse"); + +describe("element binding", () => { + beforeEach(() => { + render(); + }); + + // NOTE if this tests fails, skip it -- it was really flaky at one point + it("rotation of arrow should rebind both ends", () => { + const rect1 = UI.createElement("rectangle", { + x: 0, + width: 100, + height: 1000, + }); + const rect2 = UI.createElement("rectangle", { + x: 200, + width: 100, + height: 1000, + }); + const arrow = UI.createElement("arrow", { + x: 110, + y: 50, + width: 80, + height: 1, + }); + expect(arrow.startBinding?.elementId).toBe(rect1.id); + expect(arrow.endBinding?.elementId).toBe(rect2.id); + + const { rotation } = getTransformHandles(arrow, h.state.zoom, "mouse"); + if (rotation) { + const rotationHandleX = rotation[0] + rotation[2] / 2; + const rotationHandleY = rotation[1] + rotation[3] / 2; + mouse.down(rotationHandleX, rotationHandleY); + mouse.move(0, 1000); + mouse.up(); + } + expect(arrow.angle).toBeGreaterThan(3); + expect(arrow.startBinding?.elementId).toBe(rect2.id); + expect(arrow.endBinding?.elementId).toBe(rect1.id); + }); +}); diff --git a/src/tests/helpers/ui.ts b/src/tests/helpers/ui.ts index 7baadd18..b3c466c6 100644 --- a/src/tests/helpers/ui.ts +++ b/src/tests/helpers/ui.ts @@ -1,7 +1,11 @@ import { ToolName } from "../queries/toolQueries"; import { fireEvent, GlobalTestState } from "../test-utils"; import { KEYS, Key } from "../../keys"; -import { ExcalidrawElement } from "../../element/types"; +import { + ExcalidrawElement, + ExcalidrawLinearElement, + ExcalidrawTextElement, +} from "../../element/types"; import { API } from "./api"; const { h } = window; @@ -174,24 +178,32 @@ export class UI { fireEvent.click(GlobalTestState.renderResult.getByToolName(toolName)); }; - static createElement( - type: ToolName, + static createElement( + type: T, { x = 0, - y = x, + y = 0, size = 10, + width = size, + height = width, }: { x?: number; y?: number; size?: number; + width?: number; + height?: number; }, - ) { + ): T extends "arrow" | "line" | "draw" + ? ExcalidrawLinearElement + : T extends "text" + ? ExcalidrawTextElement + : ExcalidrawElement { UI.clickTool(type); mouse.reset(); mouse.down(x, y); mouse.reset(); - mouse.up(x + size, y + size); - return h.elements[h.elements.length - 1]; + mouse.up(x + (width ?? height ?? size), y + (height ?? size)); + return h.elements[h.elements.length - 1] as any; } static group(elements: ExcalidrawElement[]) {