Files
android_development/tools/winscope/spec/DiffSpec.js
Pablo Gamito 2eddd105b2 Add tests for DiffGenerator class
Test: N/A
Change-Id: Ifa4103c37960af20248d4b3ce39b2a823d227518
(cherry picked from commit 12150c59585f490398f09e8e56a0a46c500a8e05)
2020-06-30 12:59:02 +01:00

302 lines
9.5 KiB
JavaScript

import { DiffGenerator, DiffType } from "../src/utils/diff.js";
class Node {
constructor(nodeDef, children) {
this.children = children;
const { id, data } = nodeDef;
this.id = id;
if (data) {
this.data = data;
}
}
}
class DiffNode extends Node {
constructor(nodeDef, diffType, children) {
super(nodeDef, children);
this.diff = { type: diffType };
}
}
function checkDiffTreeWithNoModifiedCheck(oldTree, newTree, expectedDiffTree) {
const diffTree = new DiffGenerator(newTree)
.compareWith(oldTree)
.withUniqueNodeId(node => node.id)
.generateDiffTree();
expect(diffTree).toEqual(expectedDiffTree);
}
function isPrimitive(test) {
return test !== Object(test);
};
function toPlainObject(theClass) {
if (isPrimitive(theClass)) {
return theClass;
} else if (Array.isArray(theClass)) {
return theClass.map(item => toPlainObject(item));
} else {
const keys = Object.getOwnPropertyNames(Object.assign({}, theClass));
return keys.reduce((classAsObj, key) => {
classAsObj[key] = toPlainObject(theClass[key]);
return classAsObj;
}, {});
}
}
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);
});
});