restore test
This commit is contained in:
parent
d6a6c40051
commit
dddb07cf57
@ -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 = [];
|
||||||
|
|
||||||
|
if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) {
|
||||||
|
newKeys = generateNKeysBetween(
|
||||||
predecessor,
|
predecessor,
|
||||||
successor,
|
successor,
|
||||||
movedIndices.length,
|
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 (!predecessor && !successor) {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (successor && !predecessor) {
|
if (successor && !predecessor) {
|
||||||
// first element in the array
|
// first element in the array
|
||||||
// insert before successor
|
// insert before successor
|
||||||
return generateJitteredKeyBetween(null, successor);
|
return generateKeyBetween(null, successor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (predecessor && !successor) {
|
if (predecessor && !successor) {
|
||||||
// last element in the array
|
// last element in the array
|
||||||
// insert after predecessor
|
// insert after predecessor
|
||||||
return generateJitteredKeyBetween(predecessor, null);
|
return generateKeyBetween(predecessor, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// both predecessor and successor exist
|
// both predecessor and successor exist (or both do not)
|
||||||
// insert after predecessor
|
// insert after predecessor
|
||||||
return generateJitteredKeyBetween(predecessor, null);
|
return generateKeyBetween(predecessor, null);
|
||||||
}
|
|
||||||
|
|
||||||
return generateJitteredKeyBetween(null, 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,26 +213,18 @@ 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;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
|
||||||
"this is the other case",
|
|
||||||
element.fractionalIndex,
|
|
||||||
successor.fractionalIndex,
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
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