Quellcode durchsuchen

expose a few state props for debugging (#1008)

* expose a few state props for debugging

* rename h.appState & add h.setState

* support setting elements
David Luzar vor 5 Jahren
Ursprung
Commit
ff033640e4

+ 54 - 33
src/components/App.tsx

@@ -64,7 +64,7 @@ import {
 import { KEYS, isArrowKey } from "../keys";
 
 import { findShapeByKey, shapesShortcutKeys } from "../shapes";
-import { createHistory } from "../history";
+import { createHistory, SceneHistory } from "../history";
 
 import ContextMenu from "./ContextMenu";
 
@@ -113,33 +113,6 @@ function withBatchedUpdates<
   }) as TFunction;
 }
 
-// -----------------------------------------------------------------------------
-// TEST HOOKS
-// -----------------------------------------------------------------------------
-
-declare global {
-  interface Window {
-    __TEST__: {
-      elements: readonly ExcalidrawElement[];
-      appState: AppState;
-    };
-  }
-}
-
-if (process.env.NODE_ENV === "test") {
-  window.__TEST__ = {} as Window["__TEST__"];
-}
-
-// -----------------------------------------------------------------------------
-
-if (process.env.NODE_ENV === "test") {
-  Object.defineProperty(window.__TEST__, "elements", {
-    get() {
-      return globalSceneState.getAllElements();
-    },
-  });
-}
-
 const { history } = createHistory();
 
 let cursorX = 0;
@@ -476,11 +449,23 @@ export class App extends React.Component<any, AppState> {
 
   private unmounted = false;
   public async componentDidMount() {
-    if (process.env.NODE_ENV === "test") {
-      Object.defineProperty(window.__TEST__, "appState", {
-        configurable: true,
-        get: () => {
-          return this.state;
+    if (
+      process.env.NODE_ENV === "test" ||
+      process.env.NODE_ENV === "development"
+    ) {
+      const setState = this.setState.bind(this);
+      Object.defineProperties(window.h, {
+        state: {
+          configurable: true,
+          get: () => {
+            return this.state;
+          },
+        },
+        setState: {
+          configurable: true,
+          value: (...args: Parameters<typeof setState>) => {
+            return this.setState(...args);
+          },
         },
       });
     }
@@ -2447,3 +2432,39 @@ export class App extends React.Component<any, AppState> {
     }
   }
 }
+
+// -----------------------------------------------------------------------------
+// TEST HOOKS
+// -----------------------------------------------------------------------------
+
+declare global {
+  interface Window {
+    h: {
+      elements: readonly ExcalidrawElement[];
+      state: AppState;
+      history: SceneHistory;
+    };
+  }
+}
+
+if (process.env.NODE_ENV === "test" || process.env.NODE_ENV === "development") {
+  window.h = {} as Window["h"];
+
+  Object.defineProperties(window.h, {
+    elements: {
+      get() {
+        return globalSceneState.getAllElements();
+      },
+      set(elements: ExcalidrawElement[]) {
+        return globalSceneState.replaceAllElements(elements);
+      },
+    },
+    history: {
+      get() {
+        return history;
+      },
+    },
+  });
+}
+
+// -----------------------------------------------------------------------------

+ 11 - 11
src/tests/dragCreate.test.tsx

@@ -15,7 +15,7 @@ beforeEach(() => {
   renderScene.mockClear();
 });
 
-const { __TEST__: h } = window;
+const { h } = window;
 
 describe("add element to the scene when pointer dragging long enough", () => {
   it("rectangle", () => {
@@ -36,7 +36,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(4);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
 
     expect(h.elements.length).toEqual(1);
     expect(h.elements[0].type).toEqual("rectangle");
@@ -64,7 +64,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(4);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
 
     expect(h.elements.length).toEqual(1);
     expect(h.elements[0].type).toEqual("ellipse");
@@ -92,7 +92,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(4);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
 
     expect(h.elements.length).toEqual(1);
     expect(h.elements[0].type).toEqual("diamond");
@@ -120,7 +120,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(4);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
 
     expect(h.elements.length).toEqual(1);
 
@@ -152,7 +152,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(4);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
 
     expect(h.elements.length).toEqual(1);
 
@@ -183,7 +183,7 @@ describe("do not add element to the scene if size is too small", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(3);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(0);
   });
 
@@ -202,7 +202,7 @@ describe("do not add element to the scene if size is too small", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(3);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(0);
   });
 
@@ -221,7 +221,7 @@ describe("do not add element to the scene if size is too small", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(3);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(0);
   });
 
@@ -243,7 +243,7 @@ describe("do not add element to the scene if size is too small", () => {
     fireEvent.keyDown(document, { key: KEYS.ENTER });
 
     expect(renderScene).toHaveBeenCalledTimes(4);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(0);
   });
 
@@ -265,7 +265,7 @@ describe("do not add element to the scene if size is too small", () => {
     fireEvent.keyDown(document, { key: KEYS.ENTER });
 
     expect(renderScene).toHaveBeenCalledTimes(4);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(0);
   });
 });

+ 7 - 7
src/tests/move.test.tsx

@@ -13,7 +13,7 @@ beforeEach(() => {
   renderScene.mockClear();
 });
 
-const { __TEST__: h } = window;
+const { h } = window;
 
 describe("move element", () => {
   it("rectangle", () => {
@@ -29,9 +29,9 @@ describe("move element", () => {
       fireEvent.pointerUp(canvas);
 
       expect(renderScene).toHaveBeenCalledTimes(4);
-      expect(h.appState.selectionElement).toBeNull();
+      expect(h.state.selectionElement).toBeNull();
       expect(h.elements.length).toEqual(1);
-      expect(h.appState.selectedElementIds[h.elements[0].id]).toBeTruthy();
+      expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
       expect([h.elements[0].x, h.elements[0].y]).toEqual([30, 20]);
 
       renderScene.mockClear();
@@ -42,7 +42,7 @@ describe("move element", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(3);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(1);
     expect([h.elements[0].x, h.elements[0].y]).toEqual([0, 40]);
   });
@@ -62,9 +62,9 @@ describe("duplicate element on move when ALT is clicked", () => {
       fireEvent.pointerUp(canvas);
 
       expect(renderScene).toHaveBeenCalledTimes(4);
-      expect(h.appState.selectionElement).toBeNull();
+      expect(h.state.selectionElement).toBeNull();
       expect(h.elements.length).toEqual(1);
-      expect(h.appState.selectedElementIds[h.elements[0].id]).toBeTruthy();
+      expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
       expect([h.elements[0].x, h.elements[0].y]).toEqual([30, 20]);
 
       renderScene.mockClear();
@@ -75,7 +75,7 @@ describe("duplicate element on move when ALT is clicked", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(3);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(2);
 
     // previous element should stay intact

+ 1 - 1
src/tests/multiPointCreate.test.tsx

@@ -15,7 +15,7 @@ beforeEach(() => {
   renderScene.mockClear();
 });
 
-const { __TEST__: h } = window;
+const { h } = window;
 
 describe("remove shape in non linear elements", () => {
   it("rectangle", () => {

+ 7 - 7
src/tests/resize.test.tsx

@@ -13,7 +13,7 @@ beforeEach(() => {
   renderScene.mockClear();
 });
 
-const { __TEST__: h } = window;
+const { h } = window;
 
 describe("resize element", () => {
   it("rectangle", () => {
@@ -29,9 +29,9 @@ describe("resize element", () => {
       fireEvent.pointerUp(canvas);
 
       expect(renderScene).toHaveBeenCalledTimes(4);
-      expect(h.appState.selectionElement).toBeNull();
+      expect(h.state.selectionElement).toBeNull();
       expect(h.elements.length).toEqual(1);
-      expect(h.appState.selectedElementIds[h.elements[0].id]).toBeTruthy();
+      expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
       expect([h.elements[0].x, h.elements[0].y]).toEqual([30, 20]);
 
       expect([h.elements[0].width, h.elements[0].height]).toEqual([30, 50]);
@@ -49,7 +49,7 @@ describe("resize element", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(5);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(1);
     expect([h.elements[0].x, h.elements[0].y]).toEqual([29, 47]);
     expect([h.elements[0].width, h.elements[0].height]).toEqual([30, 50]);
@@ -70,9 +70,9 @@ describe("resize element with aspect ratio when SHIFT is clicked", () => {
       fireEvent.pointerUp(canvas);
 
       expect(renderScene).toHaveBeenCalledTimes(4);
-      expect(h.appState.selectionElement).toBeNull();
+      expect(h.state.selectionElement).toBeNull();
       expect(h.elements.length).toEqual(1);
-      expect(h.appState.selectedElementIds[h.elements[0].id]).toBeTruthy();
+      expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
       expect([h.elements[0].x, h.elements[0].y]).toEqual([30, 20]);
       expect([h.elements[0].x, h.elements[0].y]).toEqual([30, 20]);
       expect([h.elements[0].width, h.elements[0].height]).toEqual([30, 50]);
@@ -90,7 +90,7 @@ describe("resize element with aspect ratio when SHIFT is clicked", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(5);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(1);
     expect([h.elements[0].x, h.elements[0].y]).toEqual([29, 47]);
     expect([h.elements[0].width, h.elements[0].height]).toEqual([30, 50]);

+ 14 - 14
src/tests/selection.test.tsx

@@ -14,7 +14,7 @@ beforeEach(() => {
   renderScene.mockClear();
 });
 
-const { __TEST__: h } = window;
+const { h } = window;
 
 describe("selection element", () => {
   it("create selection element on pointer down", () => {
@@ -27,7 +27,7 @@ describe("selection element", () => {
     fireEvent.pointerDown(canvas, { clientX: 60, clientY: 100 });
 
     expect(renderScene).toHaveBeenCalledTimes(1);
-    const selectionElement = h.appState.selectionElement!;
+    const selectionElement = h.state.selectionElement!;
     expect(selectionElement).not.toBeNull();
     expect(selectionElement.type).toEqual("selection");
     expect([selectionElement.x, selectionElement.y]).toEqual([60, 100]);
@@ -48,7 +48,7 @@ describe("selection element", () => {
     fireEvent.pointerMove(canvas, { clientX: 150, clientY: 30 });
 
     expect(renderScene).toHaveBeenCalledTimes(2);
-    const selectionElement = h.appState.selectionElement!;
+    const selectionElement = h.state.selectionElement!;
     expect(selectionElement).not.toBeNull();
     expect(selectionElement.type).toEqual("selection");
     expect([selectionElement.x, selectionElement.y]).toEqual([60, 30]);
@@ -70,7 +70,7 @@ describe("selection element", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(3);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
   });
 });
 
@@ -95,9 +95,9 @@ describe("select single element on the scene", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(7);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(1);
-    expect(h.appState.selectedElementIds[h.elements[0].id]).toBeTruthy();
+    expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
   });
 
   it("diamond", () => {
@@ -120,9 +120,9 @@ describe("select single element on the scene", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(7);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(1);
-    expect(h.appState.selectedElementIds[h.elements[0].id]).toBeTruthy();
+    expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
   });
 
   it("ellipse", () => {
@@ -145,9 +145,9 @@ describe("select single element on the scene", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(7);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(1);
-    expect(h.appState.selectedElementIds[h.elements[0].id]).toBeTruthy();
+    expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
   });
 
   it("arrow", () => {
@@ -183,9 +183,9 @@ describe("select single element on the scene", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(7);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(1);
-    expect(h.appState.selectedElementIds[h.elements[0].id]).toBeTruthy();
+    expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
   });
 
   it("arrow escape", () => {
@@ -221,8 +221,8 @@ describe("select single element on the scene", () => {
     fireEvent.pointerUp(canvas);
 
     expect(renderScene).toHaveBeenCalledTimes(7);
-    expect(h.appState.selectionElement).toBeNull();
+    expect(h.state.selectionElement).toBeNull();
     expect(h.elements.length).toEqual(1);
-    expect(h.appState.selectedElementIds[h.elements[0].id]).toBeTruthy();
+    expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
   });
 });