diff --git a/packages/element/tests/__snapshots__/linearElementEditor.test.tsx.snap b/packages/element/tests/__snapshots__/linearElementEditor.test.tsx.snap index 35e940d32e..67639e5bde 100644 --- a/packages/element/tests/__snapshots__/linearElementEditor.test.tsx.snap +++ b/packages/element/tests/__snapshots__/linearElementEditor.test.tsx.snap @@ -44,3 +44,14 @@ exports[`Test Linear Elements > Test bound text element > should resize and posi "Online whiteboard collaboration made easy" `; + +exports[`Test Linear Elements > Test bound text element > should wrap the bound text when arrow bound container moves 1`] = ` +"Online whiteboard +collaboration made easy" +`; + +exports[`Test Linear Elements > Test bound text element > should wrap the bound text when arrow bound container moves 2`] = ` +"Online whiteboard +collaboration made +easy" +`; diff --git a/packages/element/tests/linearElementEditor.test.tsx b/packages/element/tests/linearElementEditor.test.tsx index de6085866e..d53492541e 100644 --- a/packages/element/tests/linearElementEditor.test.tsx +++ b/packages/element/tests/linearElementEditor.test.tsx @@ -1316,7 +1316,7 @@ describe("Test Linear Elements", () => { const textElement = h.elements[2] as ExcalidrawTextElementWithContainer; expect(arrow.endBinding?.elementId).toBe(rect.id); - expect(arrow.width).toBe(400); + expect(arrow.width).toBeCloseTo(405); expect(rect.x).toBe(400); expect(rect.y).toBe(0); expect( @@ -1335,7 +1335,7 @@ describe("Test Linear Elements", () => { mouse.downAt(rect.x, rect.y); mouse.moveTo(200, 0); mouse.upAt(200, 0); - expect(arrow.width).toBeCloseTo(200, 0); + expect(arrow.width).toBeCloseTo(205); expect(rect.x).toBe(200); expect(rect.y).toBe(0); expect(handleBindTextResizeSpy).toHaveBeenCalledWith( diff --git a/packages/element/tests/resize.test.tsx b/packages/element/tests/resize.test.tsx index b3feb47c49..1ab1fafcec 100644 --- a/packages/element/tests/resize.test.tsx +++ b/packages/element/tests/resize.test.tsx @@ -1350,8 +1350,8 @@ describe("multiple selection", () => { expect(boundArrow.x).toBeCloseTo(380 * scaleX); expect(boundArrow.y).toBeCloseTo(240 * scaleY); - expect(boundArrow.points[1][0]).toBeCloseTo(-60 * scaleX); - expect(boundArrow.points[1][1]).toBeCloseTo(-80 * scaleY); + expect(boundArrow.points[1][0]).toBeCloseTo(64.1246); + expect(boundArrow.points[1][1]).toBeCloseTo(-85.4995); expect(arrowLabelPos.x + arrowLabel.width / 2).toBeCloseTo( boundArrow.x + boundArrow.points[1][0] / 2, diff --git a/packages/excalidraw/global.d.ts b/packages/excalidraw/global.d.ts index e9b6c3f96c..4d6bbbb6c6 100644 --- a/packages/excalidraw/global.d.ts +++ b/packages/excalidraw/global.d.ts @@ -101,7 +101,10 @@ declare module "image-blob-reduce" { interface CustomMatchers { toBeNonNaNNumber(): void; - toCloselyEqualPoints(points: readonly [number, number][]): void; + toCloselyEqualPoints( + points: readonly [number, number][], + precision?: number, + ): void; } declare namespace jest { diff --git a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap index 556a41c35b..e47ba06fff 100644 --- a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap @@ -95,3 +95,142 @@ exports[`move element > rectangle 5`] = ` "y": 40, } `; + +exports[`move element > rectangles with binding arrow 5`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": [ + { + "id": "id6", + "type": "arrow", + }, + ], + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "id": "id0", + "index": "a0", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": null, + "seed": 1278240551, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "updated": 1, + "version": 4, + "versionNonce": 760410951, + "width": 100, + "x": 0, + "y": 0, +} +`; + +exports[`move element > rectangles with binding arrow 6`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": [ + { + "id": "id6", + "type": "arrow", + }, + ], + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 300, + "id": "id3", + "index": "a1", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": null, + "seed": 1116226695, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "updated": 1, + "version": 7, + "versionNonce": 271613161, + "width": 300, + "x": 201, + "y": 2, +} +`; + +exports[`move element > rectangles with binding arrow 7`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "elbowed": false, + "endArrowhead": "arrow", + "endBinding": { + "elementId": "id3", + "fixedPoint": [ + "-0.01667", + "0.45000", + ], + "mode": "orbit", + }, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": "91.98875", + "id": "id6", + "index": "a2", + "isDeleted": false, + "lastCommittedPoint": null, + "link": null, + "locked": false, + "moveMidPointsWithElement": false, + "opacity": 100, + "points": [ + [ + 0, + 0, + ], + [ + 91, + "91.98875", + ], + ], + "roughness": 1, + "roundness": { + "type": 2, + }, + "seed": 23633383, + "startArrowhead": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.05000", + "0.45011", + ], + "mode": "orbit", + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "arrow", + "updated": 1, + "version": 14, + "versionNonce": 651223591, + "width": 91, + "x": 105, + "y": "45.01062", +} +`; diff --git a/packages/excalidraw/tests/move.test.tsx b/packages/excalidraw/tests/move.test.tsx index b2a7d15695..bb30525747 100644 --- a/packages/excalidraw/tests/move.test.tsx +++ b/packages/excalidraw/tests/move.test.tsx @@ -79,6 +79,7 @@ describe("move element", () => { const rectA = UI.createElement("rectangle", { size: 100 }); const rectB = UI.createElement("rectangle", { x: 200, y: 0, size: 300 }); const arrow = UI.createElement("arrow", { x: 110, y: 50, size: 80 }); + act(() => { // bind line to two rectangles bindBindingElement( @@ -92,7 +93,7 @@ describe("move element", () => { arrow.get() as NonDeleted, rectB.get(), "orbit", - "start", + "end", h.app.scene, ); }); @@ -109,8 +110,8 @@ describe("move element", () => { expect(h.state.selectedElementIds[rectB.id]).toBeTruthy(); expect([rectA.x, rectA.y]).toEqual([0, 0]); expect([rectB.x, rectB.y]).toEqual([200, 0]); - expect([arrow.x, arrow.y]).toEqual([110, 50]); - expect([arrow.width, arrow.height]).toEqual([80, 80]); + expect([[arrow.x, arrow.y]]).toCloselyEqualPoints([[105, 45]], 0); + expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([[90, 90]], 0); renderInteractiveScene.mockClear(); renderStaticScene.mockClear(); @@ -128,10 +129,8 @@ describe("move element", () => { expect(h.state.selectedElementIds[rectB.id]).toBeTruthy(); expect([rectA.x, rectA.y]).toEqual([0, 0]); expect([rectB.x, rectB.y]).toEqual([201, 2]); - expect([[arrow.x, arrow.y]]).toCloselyEqualPoints([[50, 50]]); - expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([ - [301.02, 102.02], - ]); + expect([[arrow.x, arrow.y]]).toCloselyEqualPoints([[105, 45]], 0); + expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([[91, 91]], 0); h.elements.forEach((element) => expect(element).toMatchSnapshot()); }); diff --git a/packages/excalidraw/tests/rotate.test.tsx b/packages/excalidraw/tests/rotate.test.tsx index 38079db8f3..dfd20767f0 100644 --- a/packages/excalidraw/tests/rotate.test.tsx +++ b/packages/excalidraw/tests/rotate.test.tsx @@ -35,8 +35,8 @@ test("unselected bound arrow updates when rotating its target element", async () expect(arrow.endBinding?.elementId).toEqual(rectangle.id); expect(arrow.x).toBeCloseTo(-80); expect(arrow.y).toBeCloseTo(50); - expect(arrow.width).toBeCloseTo(110.7, 1); - expect(arrow.height).toBeCloseTo(0); + expect(arrow.width).toBeCloseTo(81.75, 1); + expect(arrow.height).toBeCloseTo(62.3, 1); }); test("unselected bound arrows update when rotating their target elements", async () => { @@ -72,13 +72,13 @@ test("unselected bound arrows update when rotating their target elements", async expect(ellipseArrow.x).toEqual(0); expect(ellipseArrow.y).toEqual(0); expect(ellipseArrow.points[0]).toEqual([0, 0]); - expect(ellipseArrow.points[1][0]).toBeCloseTo(48.98, 1); - expect(ellipseArrow.points[1][1]).toBeCloseTo(125.79, 1); + expect(ellipseArrow.points[1][0]).toBeCloseTo(16.52, 1); + expect(ellipseArrow.points[1][1]).toBeCloseTo(216.57, 1); expect(textArrow.endBinding?.elementId).toEqual(text.id); expect(textArrow.x).toEqual(360); expect(textArrow.y).toEqual(300); expect(textArrow.points[0]).toEqual([0, 0]); - expect(textArrow.points[1][0]).toBeCloseTo(-94, 0); - expect(textArrow.points[1][1]).toBeCloseTo(-116.1, 0); + expect(textArrow.points[1][0]).toBeCloseTo(-63, 0); + expect(textArrow.points[1][1]).toBeCloseTo(-146, 0); }); diff --git a/packages/utils/src/test-utils.ts b/packages/utils/src/test-utils.ts index 1dfd14cacb..966a589ab9 100644 --- a/packages/utils/src/test-utils.ts +++ b/packages/utils/src/test-utils.ts @@ -6,11 +6,11 @@ expect.extend({ throw new Error("expected and received are not point arrays"); } - const COMPARE = 1 / Math.pow(10, precision || 2); + const COMPARE = 1 / precision === 0 ? 1 : Math.pow(10, precision ?? 2); const pass = expected.every( (point, idx) => - Math.abs(received[idx]?.[0] - point[0]) < COMPARE && - Math.abs(received[idx]?.[1] - point[1]) < COMPARE, + Math.abs(received[idx][0] - point[0]) < COMPARE && + Math.abs(received[idx][1] - point[1]) < COMPARE, ); if (!pass) {