binding.test.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import React from "react";
  2. import { render } from "./test-utils";
  3. import ExcalidrawApp from "../excalidraw-app";
  4. import { UI, Pointer, Keyboard } from "./helpers/ui";
  5. import { getTransformHandles } from "../element/transformHandles";
  6. import { API } from "./helpers/api";
  7. import { KEYS } from "../keys";
  8. const { h } = window;
  9. const mouse = new Pointer("mouse");
  10. describe("element binding", () => {
  11. beforeEach(async () => {
  12. await render(<ExcalidrawApp />);
  13. });
  14. it("rotation of arrow should rebind both ends", () => {
  15. const rectLeft = UI.createElement("rectangle", {
  16. x: 0,
  17. width: 200,
  18. height: 500,
  19. });
  20. const rectRight = UI.createElement("rectangle", {
  21. x: 400,
  22. width: 200,
  23. height: 500,
  24. });
  25. const arrow = UI.createElement("arrow", {
  26. x: 210,
  27. y: 250,
  28. width: 180,
  29. height: 1,
  30. });
  31. expect(arrow.startBinding?.elementId).toBe(rectLeft.id);
  32. expect(arrow.endBinding?.elementId).toBe(rectRight.id);
  33. const rotation = getTransformHandles(arrow, h.state.zoom, "mouse")
  34. .rotation!;
  35. const rotationHandleX = rotation[0] + rotation[2] / 2;
  36. const rotationHandleY = rotation[1] + rotation[3] / 2;
  37. mouse.down(rotationHandleX, rotationHandleY);
  38. mouse.move(300, 400);
  39. mouse.up();
  40. expect(arrow.angle).toBeGreaterThan(0.7 * Math.PI);
  41. expect(arrow.angle).toBeLessThan(1.3 * Math.PI);
  42. expect(arrow.startBinding?.elementId).toBe(rectRight.id);
  43. expect(arrow.endBinding?.elementId).toBe(rectLeft.id);
  44. });
  45. it(
  46. "editing arrow and moving its head to bind it to element A, finalizing the" +
  47. "editing by clicking on element A should end up selecting A",
  48. async () => {
  49. UI.createElement("rectangle", {
  50. y: 0,
  51. size: 100,
  52. });
  53. // Create arrow bound to rectangle
  54. UI.clickTool("arrow");
  55. mouse.down(50, -100);
  56. mouse.up(0, 80);
  57. // Edit arrow with multi-point
  58. mouse.doubleClick();
  59. // move arrow head
  60. mouse.down();
  61. mouse.up(0, 10);
  62. expect(API.getSelectedElement().type).toBe("arrow");
  63. // NOTE this mouse down/up + await needs to be done in order to repro
  64. // the issue, due to https://github.com/excalidraw/excalidraw/blob/46bff3daceb602accf60c40a84610797260fca94/src/components/App.tsx#L740
  65. mouse.reset();
  66. expect(h.state.editingLinearElement).not.toBe(null);
  67. mouse.down(0, 0);
  68. await new Promise((r) => setTimeout(r, 100));
  69. expect(h.state.editingLinearElement).toBe(null);
  70. expect(API.getSelectedElement().type).toBe("rectangle");
  71. mouse.up();
  72. expect(API.getSelectedElement().type).toBe("rectangle");
  73. },
  74. );
  75. it("should bind/unbind arrow when moving it with keyboard", () => {
  76. const rectangle = UI.createElement("rectangle", {
  77. x: 75,
  78. y: 0,
  79. size: 100,
  80. });
  81. // Creates arrow 1px away from bidding with rectangle
  82. const arrow = UI.createElement("arrow", {
  83. x: 0,
  84. y: 0,
  85. size: 50,
  86. });
  87. expect(arrow.endBinding).toBe(null);
  88. expect(API.getSelectedElement().type).toBe("arrow");
  89. Keyboard.keyPress(KEYS.ARROW_RIGHT);
  90. expect(arrow.endBinding?.elementId).toBe(rectangle.id);
  91. Keyboard.keyPress(KEYS.ARROW_LEFT);
  92. expect(arrow.endBinding).toBe(null);
  93. });
  94. });