restore test

This commit is contained in:
Ryan Di 2023-12-07 23:33:31 +08:00
parent d6a6c40051
commit dddb07cf57
2 changed files with 137 additions and 48 deletions

View File

@ -1,9 +1,11 @@
import { mutateElement } from "./element/mutateElement"; import { mutateElement } from "./element/mutateElement";
import { ExcalidrawElement } from "./element/types"; import { ExcalidrawElement } from "./element/types";
import { import {
generateJitteredKeyBetween, generateKeyBetween,
generateNKeysBetween,
generateNJitteredKeysBetween, generateNJitteredKeysBetween,
} from "fractional-indexing-jittered"; } from "fractional-indexing-jittered";
import { ENV } from "./constants";
type FractionalIndex = ExcalidrawElement["fractionalIndex"]; type FractionalIndex = ExcalidrawElement["fractionalIndex"];
@ -83,11 +85,21 @@ export const fixFractionalIndices = (
elements[movedIndices[movedIndices.length - 1] + 1]?.fractionalIndex || elements[movedIndices[movedIndices.length - 1] + 1]?.fractionalIndex ||
null; null;
const newKeys = generateNJitteredKeysBetween( let newKeys = [];
predecessor,
successor, if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) {
movedIndices.length, newKeys = generateNKeysBetween(
); predecessor,
successor,
movedIndices.length,
);
} else {
newKeys = generateNJitteredKeysBetween(
predecessor,
successor,
movedIndices.length,
);
}
for (let i = 0; i < movedIndices.length; i++) { for (let i = 0; i < movedIndices.length; i++) {
const element = elements[movedIndices[i]]; const element = elements[movedIndices[i]];
@ -128,33 +140,24 @@ export const orderByFractionalIndex = (allElements: ExcalidrawElement[]) => {
}; };
const restoreFractionalIndex = ( const restoreFractionalIndex = (
index: FractionalIndex,
predecessor: FractionalIndex, predecessor: FractionalIndex,
successor: FractionalIndex, successor: FractionalIndex,
) => { ) => {
if (index) { if (successor && !predecessor) {
if (!predecessor && !successor) { // first element in the array
return index; // insert before successor
} return generateKeyBetween(null, successor);
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);
}
// both predecessor and successor exist
// insert after predecessor
return generateJitteredKeyBetween(predecessor, null);
} }
return generateJitteredKeyBetween(null, null); if (predecessor && !successor) {
// last element in the array
// insert after predecessor
return generateKeyBetween(predecessor, 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 = ( export const restoreFractionalIndicies = (
allElements: readonly ExcalidrawElement[], allElements: readonly ExcalidrawElement[],
) => { ) => {
let pre = -1;
let suc = 1; let suc = 1;
const normalized: ExcalidrawElement[] = []; const normalized: ExcalidrawElement[] = [];
for (const element of allElements) { 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; const successor = allElements[suc]?.fractionalIndex || null;
if ( if (
@ -183,7 +186,6 @@ export const restoreFractionalIndicies = (
) { ) {
try { try {
const nextFractionalIndex = restoreFractionalIndex( const nextFractionalIndex = restoreFractionalIndex(
element.fractionalIndex,
predecessor, predecessor,
successor, successor,
); );
@ -198,7 +200,6 @@ export const restoreFractionalIndicies = (
} else { } else {
normalized.push(element); normalized.push(element);
} }
pre++;
suc++; suc++;
} }
@ -212,24 +213,16 @@ export const validateFractionalIndicies = (
const element = elements[i]; const element = elements[i];
const successor = elements[i + 1]; const successor = elements[i + 1];
if (successor) { if (element.fractionalIndex) {
if (element.fractionalIndex && successor.fractionalIndex) { if (
if (element.fractionalIndex >= successor.fractionalIndex) { successor &&
console.log( successor.fractionalIndex &&
"this is the case", element.fractionalIndex >= successor.fractionalIndex
element.fractionalIndex, ) {
successor.fractionalIndex,
);
return false;
}
} else {
console.log(
"this is the other case",
element.fractionalIndex,
successor.fractionalIndex,
);
return false; return false;
} }
} else {
return false;
} }
} }

View File

@ -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,
);
});
});