dragCreate.test.tsx 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. import React from "react";
  2. import ReactDOM from "react-dom";
  3. import ExcalidrawApp from "../excalidraw-app";
  4. import * as Renderer from "../renderer/renderScene";
  5. import { KEYS } from "../keys";
  6. import {
  7. render,
  8. fireEvent,
  9. mockBoundingClientRect,
  10. restoreOriginalGetBoundingClientRect,
  11. } from "./test-utils";
  12. import { ExcalidrawLinearElement } from "../element/types";
  13. import { reseed } from "../random";
  14. // Unmount ReactDOM from root
  15. ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
  16. const renderScene = jest.spyOn(Renderer, "renderScene");
  17. beforeEach(() => {
  18. localStorage.clear();
  19. renderScene.mockClear();
  20. reseed(7);
  21. });
  22. const { h } = window;
  23. describe("add element to the scene when pointer dragging long enough", () => {
  24. it("rectangle", async () => {
  25. const { getByToolName, container } = await render(<ExcalidrawApp />);
  26. // select tool
  27. const tool = getByToolName("rectangle");
  28. fireEvent.click(tool);
  29. const canvas = container.querySelector("canvas")!;
  30. // start from (30, 20)
  31. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  32. // move to (60,70)
  33. fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
  34. // finish (position does not matter)
  35. fireEvent.pointerUp(canvas);
  36. expect(renderScene).toHaveBeenCalledTimes(8);
  37. expect(h.state.selectionElement).toBeNull();
  38. expect(h.elements.length).toEqual(1);
  39. expect(h.elements[0].type).toEqual("rectangle");
  40. expect(h.elements[0].x).toEqual(30);
  41. expect(h.elements[0].y).toEqual(20);
  42. expect(h.elements[0].width).toEqual(30); // 60 - 30
  43. expect(h.elements[0].height).toEqual(50); // 70 - 20
  44. expect(h.elements.length).toMatchSnapshot();
  45. h.elements.forEach((element) => expect(element).toMatchSnapshot());
  46. });
  47. it("ellipse", async () => {
  48. const { getByToolName, container } = await render(<ExcalidrawApp />);
  49. // select tool
  50. const tool = getByToolName("ellipse");
  51. fireEvent.click(tool);
  52. const canvas = container.querySelector("canvas")!;
  53. // start from (30, 20)
  54. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  55. // move to (60,70)
  56. fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
  57. // finish (position does not matter)
  58. fireEvent.pointerUp(canvas);
  59. expect(renderScene).toHaveBeenCalledTimes(8);
  60. expect(h.state.selectionElement).toBeNull();
  61. expect(h.elements.length).toEqual(1);
  62. expect(h.elements[0].type).toEqual("ellipse");
  63. expect(h.elements[0].x).toEqual(30);
  64. expect(h.elements[0].y).toEqual(20);
  65. expect(h.elements[0].width).toEqual(30); // 60 - 30
  66. expect(h.elements[0].height).toEqual(50); // 70 - 20
  67. expect(h.elements.length).toMatchSnapshot();
  68. h.elements.forEach((element) => expect(element).toMatchSnapshot());
  69. });
  70. it("diamond", async () => {
  71. const { getByToolName, container } = await render(<ExcalidrawApp />);
  72. // select tool
  73. const tool = getByToolName("diamond");
  74. fireEvent.click(tool);
  75. const canvas = container.querySelector("canvas")!;
  76. // start from (30, 20)
  77. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  78. // move to (60,70)
  79. fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
  80. // finish (position does not matter)
  81. fireEvent.pointerUp(canvas);
  82. expect(renderScene).toHaveBeenCalledTimes(8);
  83. expect(h.state.selectionElement).toBeNull();
  84. expect(h.elements.length).toEqual(1);
  85. expect(h.elements[0].type).toEqual("diamond");
  86. expect(h.elements[0].x).toEqual(30);
  87. expect(h.elements[0].y).toEqual(20);
  88. expect(h.elements[0].width).toEqual(30); // 60 - 30
  89. expect(h.elements[0].height).toEqual(50); // 70 - 20
  90. expect(h.elements.length).toMatchSnapshot();
  91. h.elements.forEach((element) => expect(element).toMatchSnapshot());
  92. });
  93. it("arrow", async () => {
  94. const { getByToolName, container } = await render(<ExcalidrawApp />);
  95. // select tool
  96. const tool = getByToolName("arrow");
  97. fireEvent.click(tool);
  98. const canvas = container.querySelector("canvas")!;
  99. // start from (30, 20)
  100. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  101. // move to (60,70)
  102. fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
  103. // finish (position does not matter)
  104. fireEvent.pointerUp(canvas);
  105. expect(renderScene).toHaveBeenCalledTimes(8);
  106. expect(h.state.selectionElement).toBeNull();
  107. expect(h.elements.length).toEqual(1);
  108. const element = h.elements[0] as ExcalidrawLinearElement;
  109. expect(element.type).toEqual("arrow");
  110. expect(element.x).toEqual(30);
  111. expect(element.y).toEqual(20);
  112. expect(element.points.length).toEqual(2);
  113. expect(element.points[0]).toEqual([0, 0]);
  114. expect(element.points[1]).toEqual([30, 50]); // (60 - 30, 70 - 20)
  115. expect(h.elements.length).toMatchSnapshot();
  116. h.elements.forEach((element) => expect(element).toMatchSnapshot());
  117. });
  118. it("line", async () => {
  119. const { getByToolName, container } = await render(<ExcalidrawApp />);
  120. // select tool
  121. const tool = getByToolName("line");
  122. fireEvent.click(tool);
  123. const canvas = container.querySelector("canvas")!;
  124. // start from (30, 20)
  125. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  126. // move to (60,70)
  127. fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
  128. // finish (position does not matter)
  129. fireEvent.pointerUp(canvas);
  130. expect(renderScene).toHaveBeenCalledTimes(8);
  131. expect(h.state.selectionElement).toBeNull();
  132. expect(h.elements.length).toEqual(1);
  133. const element = h.elements[0] as ExcalidrawLinearElement;
  134. expect(element.type).toEqual("line");
  135. expect(element.x).toEqual(30);
  136. expect(element.y).toEqual(20);
  137. expect(element.points.length).toEqual(2);
  138. expect(element.points[0]).toEqual([0, 0]);
  139. expect(element.points[1]).toEqual([30, 50]); // (60 - 30, 70 - 20)
  140. h.elements.forEach((element) => expect(element).toMatchSnapshot());
  141. });
  142. });
  143. describe("do not add element to the scene if size is too small", () => {
  144. beforeAll(() => {
  145. mockBoundingClientRect();
  146. });
  147. afterAll(() => {
  148. restoreOriginalGetBoundingClientRect();
  149. });
  150. it("rectangle", async () => {
  151. const { getByToolName, container } = await render(<ExcalidrawApp />);
  152. // select tool
  153. const tool = getByToolName("rectangle");
  154. fireEvent.click(tool);
  155. const canvas = container.querySelector("canvas")!;
  156. // start from (30, 20)
  157. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  158. // finish (position does not matter)
  159. fireEvent.pointerUp(canvas);
  160. expect(renderScene).toHaveBeenCalledTimes(6);
  161. expect(h.state.selectionElement).toBeNull();
  162. expect(h.elements.length).toEqual(0);
  163. });
  164. it("ellipse", async () => {
  165. const { getByToolName, container } = await render(<ExcalidrawApp />);
  166. // select tool
  167. const tool = getByToolName("ellipse");
  168. fireEvent.click(tool);
  169. const canvas = container.querySelector("canvas")!;
  170. // start from (30, 20)
  171. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  172. // finish (position does not matter)
  173. fireEvent.pointerUp(canvas);
  174. expect(renderScene).toHaveBeenCalledTimes(6);
  175. expect(h.state.selectionElement).toBeNull();
  176. expect(h.elements.length).toEqual(0);
  177. });
  178. it("diamond", async () => {
  179. const { getByToolName, container } = await render(<ExcalidrawApp />);
  180. // select tool
  181. const tool = getByToolName("diamond");
  182. fireEvent.click(tool);
  183. const canvas = container.querySelector("canvas")!;
  184. // start from (30, 20)
  185. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  186. // finish (position does not matter)
  187. fireEvent.pointerUp(canvas);
  188. expect(renderScene).toHaveBeenCalledTimes(6);
  189. expect(h.state.selectionElement).toBeNull();
  190. expect(h.elements.length).toEqual(0);
  191. });
  192. it("arrow", async () => {
  193. const { getByToolName, container } = await render(<ExcalidrawApp />);
  194. // select tool
  195. const tool = getByToolName("arrow");
  196. fireEvent.click(tool);
  197. const canvas = container.querySelector("canvas")!;
  198. // start from (30, 20)
  199. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  200. // finish (position does not matter)
  201. fireEvent.pointerUp(canvas);
  202. // we need to finalize it because arrows and lines enter multi-mode
  203. fireEvent.keyDown(document, { key: KEYS.ENTER });
  204. expect(renderScene).toHaveBeenCalledTimes(7);
  205. expect(h.state.selectionElement).toBeNull();
  206. expect(h.elements.length).toEqual(0);
  207. });
  208. it("line", async () => {
  209. const { getByToolName, container } = await render(<ExcalidrawApp />);
  210. // select tool
  211. const tool = getByToolName("line");
  212. fireEvent.click(tool);
  213. const canvas = container.querySelector("canvas")!;
  214. // start from (30, 20)
  215. fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
  216. // finish (position does not matter)
  217. fireEvent.pointerUp(canvas);
  218. // we need to finalize it because arrows and lines enter multi-mode
  219. fireEvent.keyDown(document, { key: KEYS.ENTER });
  220. expect(renderScene).toHaveBeenCalledTimes(7);
  221. expect(h.state.selectionElement).toBeNull();
  222. expect(h.elements.length).toEqual(0);
  223. });
  224. });