restore test
This commit is contained in:
parent
d6a6c40051
commit
dddb07cf57
@ -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);
|
||||
}
|
||||
|
||||
// both predecessor and successor exist
|
||||
// insert after predecessor
|
||||
return generateJitteredKeyBetween(predecessor, null);
|
||||
if (successor && !predecessor) {
|
||||
// first element in the array
|
||||
// insert before successor
|
||||
return generateKeyBetween(null, successor);
|
||||
}
|
||||
|
||||
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 = (
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
96
src/tests/fractionalIndex.test.ts
Normal file
96
src/tests/fractionalIndex.test.ts
Normal 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,
|
||||
);
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user