clarity-pattern-parser
Version:
Parsing Library for Typescript and Javascript.
480 lines (381 loc) • 15.6 kB
text/typescript
import { Node } from "./Node";
describe("Node", () => {
test("Create", () => {
const node = new Node("type", "name", 0, 0, [], "value");
expect(node.type).toBe("type");
expect(node.name).toBe("name");
expect(node.value).toBe("value");
expect(node.firstIndex).toBe(0);
expect(node.lastIndex).toBe(0);
expect(node.startIndex).toBe(0);
expect(node.endIndex).toBe(1);
expect(node.parent).toBeNull();
expect(node.children.length).toBe(0);
});
test("Properties", () => {
const child = new Node("child", "child", 0, 0, undefined, "Content");
const parent = new Node("parent", "parent", 0, 0, [
child,
]);
expect(parent.hasChildren).toBeTruthy();
expect(child.parent).toBe(parent);
expect(parent.children[0]).toBe(child);
expect(child.type).toBe("child");
expect(parent.value).toBe("Content");
expect(child.value).toBe("Content");
expect(child.name).toBe("child");
expect(child.firstIndex).toBe(0);
expect(child.lastIndex).toBe(0);
expect(child.startIndex).toBe(0);
expect(child.endIndex).toBe(1);
});
test("Create Tree", () => {
const child = new Node("child", "child", 0, 0, [], "Child");
const parent = new Node("parent", "parent", 0, 0, [child]);
expect(parent.value).toBe(child.value);
});
test("Remove Child", () => {
const child = new Node("child", "child", 0, 0, [], "Child");
const parent = new Node("parent", "parent", 0, 0, [child]);
parent.removeChild(child);
expect(parent.children.length).toBe(0);
expect(child.parent).toBeNull();
expect(parent.value).toBe("");
expect(child.value).toBe("Child");
});
test("Remove all Child", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a, b], "Fallback Value");
expect(parent.children.length).toBe(2);
expect(a.parent).toBe(parent);
expect(b.parent).toBe(parent);
expect(parent.value).toBe("AB");
expect(a.value).toBe("A");
expect(b.value).toBe("B");
parent.removeAllChildren();
expect(parent.children.length).toBe(0);
expect(a.parent).toBeNull();
expect(b.parent).toBeNull();
expect(parent.value).toBe("Fallback Value");
expect(a.value).toBe("A");
expect(b.value).toBe("B");
});
test("Replace Child", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a]);
parent.replaceChild(b, a);
expect(parent.children.length).toBe(1);
expect(a.parent).toBeNull();
expect(b.parent).toBe(parent);
expect(a.value).toBe("A");
expect(b.value).toBe("B");
});
test("Insert Child", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a]);
expect(parent.value).toBe("A");
parent.insertBefore(b, a);
expect(parent.children.length).toBe(2);
expect(parent.value).toBe("BA");
expect(parent.children[0]).toBe(b);
expect(parent.children[1]).toBe(a);
expect(a.parent).toBe(parent);
expect(b.parent).toBe(parent);
expect(a.value).toBe("A");
expect(b.value).toBe("B");
});
test("Insert Child With Null Reference", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a]);
expect(parent.value).toBe("A");
parent.insertBefore(b, null);
expect(parent.children.length).toBe(2);
expect(parent.value).toBe("AB");
expect(parent.children[0]).toBe(a);
expect(parent.children[1]).toBe(b);
expect(a.parent).toBe(parent);
expect(b.parent).toBe(parent);
expect(a.value).toBe("A");
expect(b.value).toBe("B");
});
test("Append Child", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a]);
expect(parent.value).toBe("A");
parent.appendChild(b);
expect(parent.children.length).toBe(2);
expect(parent.value).toBe("AB");
expect(parent.children[0]).toBe(a);
expect(parent.children[1]).toBe(b);
expect(a.parent).toBe(parent);
expect(b.parent).toBe(parent);
expect(a.value).toBe("A");
expect(b.value).toBe("B");
});
test("Splice Children", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a]);
expect(parent.value).toBe("A");
parent.spliceChildren(0, 0, b);
expect(parent.children.length).toBe(2);
expect(parent.value).toBe("BA");
expect(parent.children[0]).toBe(b);
expect(parent.children[1]).toBe(a);
expect(a.parent).toBe(parent);
expect(b.parent).toBe(parent);
expect(a.value).toBe("A");
expect(b.value).toBe("B");
});
test("Splice Children (Replace)", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a]);
expect(parent.value).toBe("A");
parent.spliceChildren(0, 1, b);
expect(parent.children.length).toBe(1);
expect(parent.value).toBe("B");
expect(parent.children[0]).toBe(b);
expect(a.parent).toBeNull();
expect(b.parent).toBe(parent);
expect(a.value).toBe("A");
expect(b.value).toBe("B");
});
test("Remove", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a, b]);
parent.find(p => p.name === "b")?.remove();
expect(parent.children.length).toBe(1);
expect(parent.value).toBe("A");
expect(parent.children[0]).toBe(a);
expect(a.parent).toBe(parent);
expect(b.parent).toBeNull();
expect(a.value).toBe("A");
});
test("Next Sibling", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
new Node("parent", "parent", 0, 0, [a, b]);
const nextSibling = a.nextSibling();
expect(nextSibling).toBe(b);
});
test("Next Sibling (No Parent)", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const nextSibling = a.nextSibling();
expect(nextSibling).toBeNull;
});
test("Next Sibling (Last Child)", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
new Node("parent", "parent", 0, 0, [a, b]);
const nextSibling = b.nextSibling();
expect(nextSibling).toBeNull;
});
test("Previous Sibling", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
new Node("parent", "parent", 0, 0, [a, b]);
const previousSibling = b.previousSibling();
expect(previousSibling).toBe(a);
});
test("Previous Sibling (No Parent)", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const previousSibling = a.previousSibling();
expect(previousSibling).toBeNull();
});
test("Previous Sibling (First Child)", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
new Node("parent", "parent", 0, 0, [a, b]);
const previousSibling = a.previousSibling();
expect(previousSibling).toBeNull;
});
test("Find", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a, b]);
const result = parent.find(n => n.name === "a");
expect(result).toBe(a);
});
test("Walk Down", () => {
const result: Node[] = [];
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a, b]);
parent.walkDown((n) => {
result.push(n);
});
const expected = [parent, a, b];
expect(result).toEqual(expected);
});
test("Walk Up", () => {
const result: Node[] = [];
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a, b]);
parent.walkUp((n) => {
result.push(n);
});
const expected = [a, b, parent];
expect(result).toEqual(expected);
});
test("Clone", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a, b]);
const clone = parent.clone();
expect(clone.isEqual(parent)).toBeTruthy();
});
test("Turn Into JSON", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 0, 0, [], "B");
const parent = new Node("parent", "parent", 0, 0, [a, b]);
const result = parent.toJson();
const expected = JSON.stringify({
id: parent.id,
type: "parent",
name: "parent",
value: "AB",
startIndex: 0,
endIndex: 1,
children: [{
id: parent.children[0].id,
type: "a",
name: "a",
value: "A",
startIndex: 0,
endIndex: 1,
children: [],
}, {
id: parent.children[1].id,
type: "b",
name: "b",
value: "B",
startIndex: 0,
endIndex: 1,
children: [],
}],
});
expect(result).toEqual(expected);
});
test("Compact", () => {
const parent = new Node("parent", "parent", 0, 6, [
new Node("child", "child", 0, 6, undefined, "Content")
]);
parent.compact();
expect(parent.hasChildren).toBeFalsy();
expect(parent.value).toBe("Content");
});
test("Flatten", () => {
const a = new Node("a", "a", 0, 0, [], "A");
const b = new Node("b", "b", 1, 1, [], "B");
const c = new Node("c", "c", 2, 2, [], "C");
const parent = new Node("parent", "parent", 0, 1, [
a,
b,
]);
const grandParent = new Node("grand-parent", "grand-parent", 0, 2, [
parent,
c,
]);
const nodes = grandParent.flatten();
const expected = [a, b, c];
expect(nodes).toEqual(expected);
});
test("Find Ancester", () => {
const child = new Node("child", "child", 0, 0, []);
const parent = new Node("parent", "parent", 0, 0, [child]);
const grandParent = new Node("grand-parent", "grand-parent", 0, 0, [parent]);
const result = child.findAncestor(p => p.name === "grand-parent");
expect(result).toBe(grandParent);
});
test("Find Ancester Without Parent", () => {
const child = new Node("child", "child", 0, 0, []);
const result = child.findAncestor(p => p.name === "parent");
expect(result).toBeNull();
});
test("Normalize values and index", () => {
const firstChild = new Node("literal", "first", 0, 0, [], "first");
const secondChild = new Node("literal", "second", 0, 0, [], "second");
const parent = new Node("literal", "parent", 0, 0);
parent.appendChild(firstChild);
parent.appendChild(secondChild);
parent.normalize();
expect(parent.startIndex).toBe(0);
expect(parent.firstIndex).toBe(0);
expect(parent.lastIndex).toBe(10);
expect(parent.endIndex).toBe(11);
});
test("Normalize values and index deep", () => {
const firstChild = new Node("literal", "first", 0, 0, [], "first");
const secondChild = new Node("literal", "second", 0, 0, [], "second");
const grandChild = new Node("literal", "three", 0, 0, [], "three");
const parent = new Node("literal", "parent", 0, 0);
parent.appendChild(firstChild);
parent.appendChild(secondChild);
parent.normalize();
secondChild.appendChild(grandChild);
parent.normalize();
expect(parent.startIndex).toBe(0);
expect(parent.firstIndex).toBe(0);
expect(parent.lastIndex).toBe(9);
expect(parent.endIndex).toBe(10);
});
test("Normalize values with no values", () => {
const node = new Node("literal", "node", 0, 0, [], "");
node.normalize();
expect(node.startIndex).toBe(0);
expect(node.firstIndex).toBe(0);
expect(node.lastIndex).toBe(0);
expect(node.endIndex).toBe(1);
});
test("ReplaceWith", () => {
const parent = new Node("node", "parent", 0, 0, [
new Node("node", "first", 0, 0, [], "first"),
new Node("node", "second", 0, 0, [], "second"),
]);
const first = parent.find(n => n.name === "first") as Node;
const newNode = new Node("node", "new", 0, 0, [], "new");
first.replaceWith(newNode);
const result = parent.find(n => n.name === "new") as Node;
expect(result).toBe(newNode);
expect(first.parent).toBeNull();
expect(result.parent).toBe(parent);
});
test("Transform", () => {
const node = Node.createNode("family", "grandparent", [
Node.createNode("family", "parent", [
Node.createValueNode("family", "child", "John"),
Node.createValueNode("family", "child", "Jane"),
Node.createValueNode("family", "child", "Jack")
]),
Node.createValueNode("family", "aunt", "aunt")
]);
const result = node.transform({
"child": (node: Node) => {
return Node.createValueNode("family", "adopted-child", node.value);
},
"parent": (node) => {
return Node.createNode("family", "adopted-parent", node.children.slice());
},
"grandparent": (node) => {
return Node.createNode("family", "adopted-grandparent", node.children.slice());
}
});
const expected = Node.createNode("family", "adopted-grandparent", [
Node.createNode("family", "adopted-parent", [
Node.createValueNode("family", "adopted-child", "John"),
Node.createValueNode("family", "adopted-child", "Jane"),
Node.createValueNode("family", "adopted-child", "Jack")
]),
Node.createValueNode("family", "aunt", "aunt")
]);
expect(result.isEqual(expected)).toBeTruthy();
});
});