You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
267 lines
8.7 KiB
267 lines
8.7 KiB
import { DiffGenerator, DiffType } from "../src/utils/diff.js";
|
|
import { Node, DiffNode, toPlainObject } from "./utils/tree.js";
|
|
|
|
function checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree) {
|
|
const diffTree = new DiffGenerator(newTree)
|
|
.compareWith(oldTree)
|
|
.withUniqueNodeId(node => node.id)
|
|
.generateDiffTree();
|
|
|
|
expect(diffTree).toEqual(expectedDiffTree);
|
|
}
|
|
|
|
describe("DiffGenerator", () => {
|
|
it("can generate a simple add diff", () => {
|
|
const oldTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, []),
|
|
new Node({ id: 4 }, []),
|
|
]);
|
|
|
|
const newTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, [
|
|
new Node({ id: 5 }, []),
|
|
]),
|
|
new Node({ id: 4 }, []),
|
|
]);
|
|
|
|
const diffTree = new DiffGenerator(newTree)
|
|
.compareWith(oldTree)
|
|
.withUniqueNodeId(node => node.id)
|
|
.withModifiedCheck(() => false)
|
|
.generateDiffTree();
|
|
|
|
const expectedDiffTree = toPlainObject(
|
|
new DiffNode({ id: 1 }, DiffType.NONE, [
|
|
new DiffNode({ id: 2 }, DiffType.NONE, []),
|
|
new DiffNode({ id: 3 }, DiffType.NONE, [
|
|
new DiffNode({ id: 5 }, DiffType.ADDED, []),
|
|
]),
|
|
new DiffNode({ id: 4 }, DiffType.NONE, []),
|
|
])
|
|
);
|
|
|
|
checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree);
|
|
});
|
|
|
|
it("can generate a simple delete diff", () => {
|
|
const oldTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, [
|
|
new Node({ id: 5 }, []),
|
|
]),
|
|
new Node({ id: 4 }, []),
|
|
]);
|
|
|
|
const newTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, []),
|
|
new Node({ id: 4 }, []),
|
|
]);
|
|
|
|
const expectedDiffTree = toPlainObject(
|
|
new DiffNode({ id: 1 }, DiffType.NONE, [
|
|
new DiffNode({ id: 2 }, DiffType.NONE, []),
|
|
new DiffNode({ id: 3 }, DiffType.NONE, [
|
|
new DiffNode({ id: 5 }, DiffType.DELETED, []),
|
|
]),
|
|
new DiffNode({ id: 4 }, DiffType.NONE, []),
|
|
])
|
|
);
|
|
|
|
checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree);
|
|
});
|
|
|
|
it("can generate a simple move diff", () => {
|
|
const oldTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, [
|
|
new Node({ id: 5 }, []),
|
|
]),
|
|
new Node({ id: 4 }, []),
|
|
]);
|
|
|
|
const newTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, []),
|
|
new Node({ id: 4 }, [
|
|
new Node({ id: 5 }, []),
|
|
]),
|
|
]);
|
|
|
|
const expectedDiffTree = toPlainObject(
|
|
new DiffNode({ id: 1 }, DiffType.NONE, [
|
|
new DiffNode({ id: 2 }, DiffType.NONE, []),
|
|
new DiffNode({ id: 3 }, DiffType.NONE, [
|
|
new DiffNode({ id: 5 }, DiffType.DELETED_MOVE, []),
|
|
]),
|
|
new DiffNode({ id: 4 }, DiffType.NONE, [
|
|
new DiffNode({ id: 5 }, DiffType.ADDED_MOVE, []),
|
|
]),
|
|
])
|
|
);
|
|
|
|
checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree);
|
|
});
|
|
|
|
it("can generate a simple modified diff", () => {
|
|
const oldTree = new Node({ id: 1, data: "xyz" }, [
|
|
new Node({ id: 2, data: "abc" }, []),
|
|
new Node({ id: 3, data: "123" }, []),
|
|
]);
|
|
|
|
const newTree = new Node({ id: 1, data: "xyz" }, [
|
|
new Node({ id: 2, data: "def" }, []),
|
|
new Node({ id: 3, data: "123" }, []),
|
|
]);
|
|
|
|
const expectedDiffTree = toPlainObject(
|
|
new DiffNode({ id: 1, data: "xyz" }, DiffType.NONE, [
|
|
new DiffNode({ id: 2, data: "def" }, DiffType.MODIFIED, []),
|
|
new DiffNode({ id: 3, data: "123" }, DiffType.NONE, []),
|
|
])
|
|
);
|
|
|
|
const diffTree = new DiffGenerator(newTree)
|
|
.compareWith(oldTree)
|
|
.withUniqueNodeId(node => node.id)
|
|
.withModifiedCheck(
|
|
(newNode, oldNode) => newNode.data != oldNode.data)
|
|
.generateDiffTree();
|
|
|
|
expect(diffTree).toEqual(expectedDiffTree);
|
|
});
|
|
|
|
it("can handle move and inner addition diff", () => {
|
|
const oldTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, [
|
|
new Node({ id: 4 }, []),
|
|
]),
|
|
]);
|
|
|
|
const newTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, [
|
|
new Node({ id: 4 }, [
|
|
new Node({ id: 5 }, []),
|
|
]),
|
|
]),
|
|
new Node({ id: 3 }, []),
|
|
]);
|
|
|
|
const expectedDiffTree = toPlainObject(
|
|
new DiffNode({ id: 1 }, DiffType.NONE, [
|
|
new DiffNode({ id: 2 }, DiffType.NONE, [
|
|
new DiffNode({ id: 4 }, DiffType.ADDED_MOVE, [
|
|
new DiffNode({ id: 5 }, DiffType.ADDED, []),
|
|
]),
|
|
]),
|
|
new DiffNode({ id: 3 }, DiffType.NONE, [
|
|
new DiffNode({ id: 4 }, DiffType.DELETED_MOVE, []),
|
|
]),
|
|
])
|
|
);
|
|
|
|
checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree);
|
|
});
|
|
|
|
it("can handle move within same level", () => {
|
|
const oldTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, []),
|
|
]);
|
|
|
|
const newTree = new Node({ id: 1 }, [
|
|
new Node({ id: 3 }, []),
|
|
new Node({ id: 2 }, []),
|
|
]);
|
|
|
|
const expectedDiffTree = toPlainObject(
|
|
new DiffNode({ id: 1 }, DiffType.NONE, [
|
|
new DiffNode({ id: 3 }, DiffType.NONE, []),
|
|
new DiffNode({ id: 2 }, DiffType.NONE, []),
|
|
])
|
|
);
|
|
|
|
checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree);
|
|
});
|
|
|
|
it("can handle addition within middle of level", () => {
|
|
const oldTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, []),
|
|
]);
|
|
|
|
const newTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 4 }, []),
|
|
new Node({ id: 3 }, []),
|
|
]);
|
|
|
|
const expectedDiffTree = toPlainObject(
|
|
new DiffNode({ id: 1 }, DiffType.NONE, [
|
|
new DiffNode({ id: 2 }, DiffType.NONE, []),
|
|
new DiffNode({ id: 4 }, DiffType.ADDED, []),
|
|
new DiffNode({ id: 3 }, DiffType.NONE, []),
|
|
])
|
|
);
|
|
|
|
checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree);
|
|
});
|
|
|
|
it("can handle deletion within middle of level", () => {
|
|
const oldTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, []),
|
|
new Node({ id: 4 }, []),
|
|
]);
|
|
|
|
const newTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 4 }, []),
|
|
]);
|
|
|
|
const expectedDiffTree = toPlainObject(
|
|
new DiffNode({ id: 1 }, DiffType.NONE, [
|
|
new DiffNode({ id: 2 }, DiffType.NONE, []),
|
|
new DiffNode({ id: 3 }, DiffType.DELETED, []),
|
|
new DiffNode({ id: 4 }, DiffType.NONE, []),
|
|
])
|
|
);
|
|
|
|
checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree);
|
|
});
|
|
|
|
it("fully visits deletes nodes", () => {
|
|
const oldTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, [
|
|
new Node({ id: 3 }, [
|
|
new Node({ id: 4 }, []),
|
|
]),
|
|
]),
|
|
]);
|
|
|
|
const newTree = new Node({ id: 1 }, [
|
|
new Node({ id: 2 }, []),
|
|
new Node({ id: 3 }, [
|
|
new Node({ id: 4 }, []),
|
|
]),
|
|
]);
|
|
|
|
const expectedDiffTree = toPlainObject(
|
|
new DiffNode({ id: 1 }, DiffType.NONE, [
|
|
new DiffNode({ id: 2 }, DiffType.NONE, [
|
|
new DiffNode({ id: 3 }, DiffType.DELETED_MOVE, [
|
|
new DiffNode({ id: 4 }, DiffType.DELETED_MOVE, []),
|
|
]),
|
|
]),
|
|
new DiffNode({ id: 3 }, DiffType.ADDED_MOVE, [
|
|
new DiffNode({ id: 4 }, DiffType.NONE, []),
|
|
]),
|
|
])
|
|
);
|
|
|
|
checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree);
|
|
});
|
|
}); |