Parcourir la source

test the fixing of fractional indices

Ryan Di il y a 1 an
Parent
commit
5e98047267
3 fichiers modifiés avec 240 ajouts et 35 suppressions
  1. 1 1
      src/scene/export.ts
  2. 239 33
      src/tests/fractionalIndex.test.ts
  3. 0 1
      src/zindex.ts

+ 1 - 1
src/scene/export.ts

@@ -59,7 +59,7 @@ const __createSceneForElementsHack__ = (
   // ids to Scene instances so that we don't override the editor elements
   // ids to Scene instances so that we don't override the editor elements
   // mapping.
   // mapping.
   // We still need to clone the objects themselves to regen references.
   // We still need to clone the objects themselves to regen references.
-  scene.replaceAllElements(cloneJSON(elements), false);
+  scene.replaceAllElements(cloneJSON(elements));
   return scene;
   return scene;
 };
 };
 
 

+ 239 - 33
src/tests/fractionalIndex.test.ts

@@ -1,10 +1,13 @@
-import { nanoid } from "nanoid";
 import {
 import {
+  fixFractionalIndices,
   restoreFractionalIndicies,
   restoreFractionalIndicies,
   validateFractionalIndicies,
   validateFractionalIndicies,
 } from "../fractionalIndex";
 } from "../fractionalIndex";
 import { ExcalidrawElement } from "../element/types";
 import { ExcalidrawElement } from "../element/types";
 import { API } from "./helpers/api";
 import { API } from "./helpers/api";
+import { arrayToMap } from "../utils";
+import { moveAllLeft, moveOneLeft, moveOneRight } from "../zindex";
+import { AppState } from "../types";
 
 
 const createElementWithIndex = (
 const createElementWithIndex = (
   fractionalIndex: string | null = null,
   fractionalIndex: string | null = null,
@@ -15,6 +18,30 @@ const createElementWithIndex = (
   });
   });
 };
 };
 
 
+const testLengthAndOrder = (
+  before: ExcalidrawElement[],
+  after: ExcalidrawElement[],
+) => {
+  // length is not changed
+  expect(after.length).toBe(before.length);
+  // order is not changed
+  expect(after.map((e) => e.id)).deep.equal(before.map((e) => e.id));
+};
+
+const testValidity = (elements: ExcalidrawElement[]) => {
+  expect(validateFractionalIndicies(elements)).toBe(true);
+};
+
+const genrateElementsAtLength = (length: number) => {
+  const elements: ExcalidrawElement[] = [];
+
+  for (let i = 0; i < length; i++) {
+    elements.push(createElementWithIndex());
+  }
+
+  return elements;
+};
+
 describe("restoring fractional indicies", () => {
 describe("restoring fractional indicies", () => {
   it("restore all null fractional indices", () => {
   it("restore all null fractional indices", () => {
     const randomNumOfElements = Math.floor(Math.random() * 100);
     const randomNumOfElements = Math.floor(Math.random() * 100);
@@ -30,14 +57,8 @@ describe("restoring fractional indicies", () => {
 
 
     const restoredElements = restoreFractionalIndicies(elements);
     const restoredElements = restoreFractionalIndicies(elements);
 
 
-    // length is not changed
-    expect(restoredElements.length).toBe(randomNumOfElements);
-    // order is not changed
-    expect(restoredElements.map((e) => e.id)).deep.equal(
-      elements.map((e) => e.id),
-    );
-    // fractional indices are valid
-    expect(validateFractionalIndicies(restoredElements)).toBe(true);
+    testLengthAndOrder(elements, restoredElements);
+    testValidity(restoredElements);
   });
   });
 
 
   it("restore out of order fractional indices", () => {
   it("restore out of order fractional indices", () => {
@@ -50,14 +71,8 @@ describe("restoring fractional indicies", () => {
 
 
     const restoredElements = restoreFractionalIndicies(elements);
     const restoredElements = restoreFractionalIndicies(elements);
 
 
-    // length is not changed
-    expect(restoredElements.length).toBe(4);
-    // order is not changed
-    expect(restoredElements.map((e) => e.id)).deep.equal(
-      elements.map((e) => e.id),
-    );
-    // fractional indices are valid
-    expect(validateFractionalIndicies(restoredElements)).toBe(true);
+    testLengthAndOrder(elements, restoredElements);
+    testValidity(restoredElements);
     // should only fix the second element's fractional index
     // should only fix the second element's fractional index
     expect(elements[1].fractionalIndex).not.toEqual(
     expect(elements[1].fractionalIndex).not.toEqual(
       restoredElements[1].fractionalIndex,
       restoredElements[1].fractionalIndex,
@@ -81,14 +96,8 @@ describe("restoring fractional indicies", () => {
 
 
     const restoredElements = restoreFractionalIndicies(elements);
     const restoredElements = restoreFractionalIndicies(elements);
 
 
-    // length is not changed
-    expect(restoredElements.length).toBe(randomNumOfElements);
-    // order is not changed
-    expect(restoredElements.map((e) => e.id)).deep.equal(
-      elements.map((e) => e.id),
-    );
-    // should've restored fractional indices properly
-    expect(validateFractionalIndicies(restoredElements)).toBe(true);
+    testLengthAndOrder(elements, restoredElements);
+    testValidity(restoredElements);
     expect(new Set(restoredElements.map((e) => e.fractionalIndex)).size).toBe(
     expect(new Set(restoredElements.map((e) => e.fractionalIndex)).size).toBe(
       randomNumOfElements,
       randomNumOfElements,
     );
     );
@@ -108,16 +117,213 @@ describe("restoring fractional indicies", () => {
 
 
     const restoredElements = restoreFractionalIndicies(elements);
     const restoredElements = restoreFractionalIndicies(elements);
 
 
-    // length is not changed
-    expect(restoredElements.length).toBe(elements.length);
-    // order is not changed
-    expect(restoredElements.map((e) => e.id)).deep.equal(
-      elements.map((e) => e.id),
-    );
-    // should've restored fractional indices properly
-    expect(validateFractionalIndicies(restoredElements)).toBe(true);
+    testLengthAndOrder(elements, restoredElements);
+    testValidity(restoredElements);
     expect(new Set(restoredElements.map((e) => e.fractionalIndex)).size).toBe(
     expect(new Set(restoredElements.map((e) => e.fractionalIndex)).size).toBe(
       elements.length,
       elements.length,
     );
     );
   });
   });
 });
 });
+
+describe("fix fractional indices", () => {
+  it("add each new element properly", () => {
+    const elements = [
+      createElementWithIndex(),
+      createElementWithIndex(),
+      createElementWithIndex(),
+      createElementWithIndex(),
+    ];
+
+    const fixedElements = elements.reduce((acc, el) => {
+      return fixFractionalIndices([...acc, el], arrayToMap([el]));
+    }, [] as ExcalidrawElement[]);
+
+    testLengthAndOrder(elements, fixedElements);
+    testValidity(fixedElements);
+  });
+
+  it("add multiple new elements properly", () => {
+    const elements = genrateElementsAtLength(Math.floor(Math.random() * 100));
+
+    const fixedElements = fixFractionalIndices(elements, arrayToMap(elements));
+
+    testLengthAndOrder(elements, fixedElements);
+    testValidity(fixedElements);
+
+    const elements2 = genrateElementsAtLength(Math.floor(Math.random() * 100));
+
+    const allElements2 = [...elements, ...elements2];
+
+    const fixedElements2 = fixFractionalIndices(
+      allElements2,
+      arrayToMap(elements2),
+    );
+
+    testLengthAndOrder(allElements2, fixedElements2);
+    testValidity(fixedElements2);
+  });
+
+  it("fix properly after z-index changes", () => {
+    const elements = genrateElementsAtLength(Math.random() * 100);
+
+    const fixedElements = fixFractionalIndices(elements, arrayToMap(elements));
+
+    let randomlySelected = [
+      ...new Set([
+        fixedElements[Math.floor(Math.random() * fixedElements.length)],
+        fixedElements[Math.floor(Math.random() * fixedElements.length)],
+        fixedElements[Math.floor(Math.random() * fixedElements.length)],
+        fixedElements[Math.floor(Math.random() * fixedElements.length)],
+        fixedElements[Math.floor(Math.random() * fixedElements.length)],
+        fixedElements[Math.floor(Math.random() * fixedElements.length)],
+        fixedElements[Math.floor(Math.random() * fixedElements.length)],
+      ]),
+    ];
+
+    const movedOneLeftFixedElements = moveOneLeft(
+      fixedElements,
+      randomlySelected.reduce(
+        (acc, el) => {
+          acc.selectedElementIds[el.id] = true;
+          return acc;
+        },
+        {
+          selectedElementIds: {},
+        } as {
+          selectedElementIds: Record<string, boolean>;
+        },
+      ) as any as AppState,
+    );
+
+    testValidity(movedOneLeftFixedElements);
+
+    randomlySelected = [
+      ...new Set([
+        movedOneLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+      ]),
+    ];
+
+    const movedOneRightFixedElements = moveOneRight(
+      movedOneLeftFixedElements,
+      randomlySelected.reduce(
+        (acc, el) => {
+          acc.selectedElementIds[el.id] = true;
+          return acc;
+        },
+        {
+          selectedElementIds: {},
+        } as {
+          selectedElementIds: Record<string, boolean>;
+        },
+      ) as any as AppState,
+    );
+
+    testValidity(movedOneRightFixedElements);
+
+    randomlySelected = [
+      ...new Set([
+        movedOneRightFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneRightFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneRightFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneRightFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneRightFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneRightFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedOneRightFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+      ]),
+    ];
+
+    const movedAllLeftFixedElements = moveAllLeft(
+      movedOneRightFixedElements,
+      randomlySelected.reduce(
+        (acc, el) => {
+          acc.selectedElementIds[el.id] = true;
+          return acc;
+        },
+        {
+          selectedElementIds: {},
+        } as {
+          selectedElementIds: Record<string, boolean>;
+        },
+      ) as any as AppState,
+    ) as ExcalidrawElement[];
+
+    testValidity(movedAllLeftFixedElements);
+
+    randomlySelected = [
+      ...new Set([
+        movedAllLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedAllLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedAllLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedAllLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedAllLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedAllLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+        movedAllLeftFixedElements[
+          Math.floor(Math.random() * fixedElements.length)
+        ],
+      ]),
+    ];
+
+    const movedAllRightFixedElements = moveAllLeft(
+      movedAllLeftFixedElements,
+      randomlySelected.reduce(
+        (acc, el) => {
+          acc.selectedElementIds[el.id] = true;
+          return acc;
+        },
+        {
+          selectedElementIds: {},
+        } as {
+          selectedElementIds: Record<string, boolean>;
+        },
+      ) as any as AppState,
+    ) as ExcalidrawElement[];
+
+    testValidity(movedAllRightFixedElements);
+  });
+});

+ 0 - 1
src/zindex.ts

@@ -1,4 +1,3 @@
-import { bumpVersion } from "./element/mutateElement";
 import { isFrameLikeElement } from "./element/typeChecks";
 import { isFrameLikeElement } from "./element/typeChecks";
 import { ExcalidrawElement, ExcalidrawFrameLikeElement } from "./element/types";
 import { ExcalidrawElement, ExcalidrawFrameLikeElement } from "./element/types";
 import { fixFractionalIndices } from "./fractionalIndex";
 import { fixFractionalIndices } from "./fractionalIndex";