dragCreate.test.tsx 9.5 KB

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