From dddb07cf57196e5909eaaea72f67ace0c0d35985 Mon Sep 17 00:00:00 2001 From: Ryan Di Date: Thu, 7 Dec 2023 23:33:31 +0800 Subject: [PATCH] restore test --- src/fractionalIndex.ts | 85 +++++++++++++-------------- src/tests/fractionalIndex.test.ts | 96 +++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 46 deletions(-) create mode 100644 src/tests/fractionalIndex.test.ts diff --git a/src/fractionalIndex.ts b/src/fractionalIndex.ts index 241109a2c4..ae58579799 100644 --- a/src/fractionalIndex.ts +++ b/src/fractionalIndex.ts @@ -1,9 +1,11 @@ import { mutateElement } from "./element/mutateElement"; import { ExcalidrawElement } from "./element/types"; import { - generateJitteredKeyBetween, + generateKeyBetween, + generateNKeysBetween, generateNJitteredKeysBetween, } from "fractional-indexing-jittered"; +import { ENV } from "./constants"; type FractionalIndex = ExcalidrawElement["fractionalIndex"]; @@ -83,11 +85,21 @@ export const fixFractionalIndices = ( elements[movedIndices[movedIndices.length - 1] + 1]?.fractionalIndex || null; - const newKeys = generateNJitteredKeysBetween( - predecessor, - successor, - movedIndices.length, - ); + let newKeys = []; + + if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) { + newKeys = generateNKeysBetween( + predecessor, + successor, + movedIndices.length, + ); + } else { + newKeys = generateNJitteredKeysBetween( + predecessor, + successor, + movedIndices.length, + ); + } for (let i = 0; i < movedIndices.length; i++) { const element = elements[movedIndices[i]]; @@ -128,33 +140,24 @@ export const orderByFractionalIndex = (allElements: ExcalidrawElement[]) => { }; const restoreFractionalIndex = ( - index: FractionalIndex, predecessor: FractionalIndex, successor: FractionalIndex, ) => { - if (index) { - if (!predecessor && !successor) { - return index; - } - - if (successor && !predecessor) { - // first element in the array - // insert before successor - return generateJitteredKeyBetween(null, successor); - } - - if (predecessor && !successor) { - // last element in the array - // insert after predecessor - return generateJitteredKeyBetween(predecessor, null); - } + if (successor && !predecessor) { + // first element in the array + // insert before successor + return generateKeyBetween(null, successor); + } - // both predecessor and successor exist + if (predecessor && !successor) { + // last element in the array // insert after predecessor - return generateJitteredKeyBetween(predecessor, null); + return generateKeyBetween(predecessor, null); } - return generateJitteredKeyBetween(null, null); + // both predecessor and successor exist (or both do not) + // insert after predecessor + return generateKeyBetween(predecessor, null); }; /** @@ -169,13 +172,13 @@ const restoreFractionalIndex = ( export const restoreFractionalIndicies = ( allElements: readonly ExcalidrawElement[], ) => { - let pre = -1; let suc = 1; const normalized: ExcalidrawElement[] = []; for (const element of allElements) { - const predecessor = allElements[pre]?.fractionalIndex || null; + const predecessor = + normalized[normalized.length - 1]?.fractionalIndex || null; const successor = allElements[suc]?.fractionalIndex || null; if ( @@ -183,7 +186,6 @@ export const restoreFractionalIndicies = ( ) { try { const nextFractionalIndex = restoreFractionalIndex( - element.fractionalIndex, predecessor, successor, ); @@ -198,7 +200,6 @@ export const restoreFractionalIndicies = ( } else { normalized.push(element); } - pre++; suc++; } @@ -212,24 +213,16 @@ export const validateFractionalIndicies = ( const element = elements[i]; const successor = elements[i + 1]; - if (successor) { - if (element.fractionalIndex && successor.fractionalIndex) { - if (element.fractionalIndex >= successor.fractionalIndex) { - console.log( - "this is the case", - element.fractionalIndex, - successor.fractionalIndex, - ); - return false; - } - } else { - console.log( - "this is the other case", - element.fractionalIndex, - successor.fractionalIndex, - ); + if (element.fractionalIndex) { + if ( + successor && + successor.fractionalIndex && + element.fractionalIndex >= successor.fractionalIndex + ) { return false; } + } else { + return false; } } diff --git a/src/tests/fractionalIndex.test.ts b/src/tests/fractionalIndex.test.ts new file mode 100644 index 0000000000..20dc96fec3 --- /dev/null +++ b/src/tests/fractionalIndex.test.ts @@ -0,0 +1,96 @@ +import { nanoid } from "nanoid"; +import { + restoreFractionalIndicies, + validateFractionalIndicies, +} from "../fractionalIndex"; +import { ExcalidrawElement } from "../element/types"; +import { API } from "./helpers/api"; + +const createElementWithIndex = ( + fractionalIndex: string | null = null, +): ExcalidrawElement => { + return API.createElement({ + type: "rectangle", + fractionalIndex, + }); +}; + +describe("restoring fractional indicies", () => { + it("restore all null fractional indices", () => { + const randomNumOfElements = Math.floor(Math.random() * 100); + + const elements: ExcalidrawElement[] = []; + + let i = 0; + + while (i < randomNumOfElements) { + elements.push(createElementWithIndex()); + i++; + } + + 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); + }); + + it("restore out of order fractional indices", () => { + const elements = [ + createElementWithIndex("a0"), + createElementWithIndex("c0"), + createElementWithIndex("b0"), + createElementWithIndex("d0"), + ]; + + 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); + // should only fix the second element's fractional index + expect(elements[1].fractionalIndex).not.toEqual( + restoredElements[1].fractionalIndex, + ); + expect(elements.filter((value, index) => index !== 1)).deep.equal( + restoredElements.filter((value, index) => index !== 1), + ); + }); + + it("restore same fractional indices", () => { + const randomNumOfElements = Math.floor(Math.random() * 100); + + const elements: ExcalidrawElement[] = []; + + let i = 0; + + while (i < randomNumOfElements) { + elements.push(createElementWithIndex("a0")); + i++; + } + + 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); + expect(new Set(restoredElements.map((e) => e.fractionalIndex)).size).toBe( + randomNumOfElements, + ); + }); +});