test the fixing of fractional indices
This commit is contained in:
parent
741380bd43
commit
5e98047267
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
testLengthAndOrder(elements, restoredElements);
|
||||||
expect(restoredElements.length).toBe(randomNumOfElements);
|
testValidity(restoredElements);
|
||||||
// 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", () => {
|
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
|
testLengthAndOrder(elements, restoredElements);
|
||||||
expect(restoredElements.length).toBe(4);
|
testValidity(restoredElements);
|
||||||
// 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
|
// 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
|
testLengthAndOrder(elements, restoredElements);
|
||||||
expect(restoredElements.length).toBe(randomNumOfElements);
|
testValidity(restoredElements);
|
||||||
// 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(
|
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
|
testLengthAndOrder(elements, restoredElements);
|
||||||
expect(restoredElements.length).toBe(elements.length);
|
testValidity(restoredElements);
|
||||||
// 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(
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -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";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user