Skip to content

Commit b47ea7e

Browse files
Merge pull request #16048 from KAPUIST/test/tree-node-coverage
test(core): Add comprehensive tests for TreeNode class
2 parents 3817c50 + e8df30c commit b47ea7e

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import { expect } from 'chai';
2+
import { TreeNode } from '../../../injector/topology-tree/tree-node';
3+
4+
describe('TreeNode', () => {
5+
describe('constructor', () => {
6+
it('should create a node with the given value', () => {
7+
const node = new TreeNode({ value: 'test', parent: null });
8+
expect(node.value).to.equal('test');
9+
});
10+
11+
it('should create a node with null parent', () => {
12+
const node = new TreeNode({ value: 'test', parent: null });
13+
expect(node.children.size).to.equal(0);
14+
});
15+
16+
it('should create a node with a parent', () => {
17+
const parent = new TreeNode({ value: 'parent', parent: null });
18+
const child = new TreeNode({ value: 'child', parent });
19+
expect(child.value).to.equal('child');
20+
});
21+
});
22+
23+
describe('addChild', () => {
24+
it('should add a child to the node', () => {
25+
const parent = new TreeNode({ value: 'parent', parent: null });
26+
const child = new TreeNode({ value: 'child', parent: null });
27+
28+
parent.addChild(child);
29+
30+
expect(parent.children.has(child)).to.be.true;
31+
expect(parent.children.size).to.equal(1);
32+
});
33+
34+
it('should add multiple children', () => {
35+
const parent = new TreeNode({ value: 'parent', parent: null });
36+
const child1 = new TreeNode({ value: 'child1', parent: null });
37+
const child2 = new TreeNode({ value: 'child2', parent: null });
38+
39+
parent.addChild(child1);
40+
parent.addChild(child2);
41+
42+
expect(parent.children.size).to.equal(2);
43+
});
44+
});
45+
46+
describe('removeChild', () => {
47+
it('should remove a child from the node', () => {
48+
const parent = new TreeNode({ value: 'parent', parent: null });
49+
const child = new TreeNode({ value: 'child', parent: null });
50+
51+
parent.addChild(child);
52+
parent.removeChild(child);
53+
54+
expect(parent.children.has(child)).to.be.false;
55+
expect(parent.children.size).to.equal(0);
56+
});
57+
58+
it('should do nothing when removing a non-existent child', () => {
59+
const parent = new TreeNode({ value: 'parent', parent: null });
60+
const child = new TreeNode({ value: 'child', parent: null });
61+
62+
parent.removeChild(child);
63+
64+
expect(parent.children.size).to.equal(0);
65+
});
66+
});
67+
68+
describe('relink', () => {
69+
it('should change the parent of a node', () => {
70+
const oldParent = new TreeNode({ value: 'oldParent', parent: null });
71+
const newParent = new TreeNode({ value: 'newParent', parent: null });
72+
const child = new TreeNode({ value: 'child', parent: oldParent });
73+
74+
oldParent.addChild(child);
75+
child.relink(newParent);
76+
77+
expect(oldParent.children.has(child)).to.be.false;
78+
expect(newParent.children.has(child)).to.be.true;
79+
});
80+
81+
it('should work when node has no previous parent', () => {
82+
const newParent = new TreeNode({ value: 'newParent', parent: null });
83+
const child = new TreeNode({ value: 'child', parent: null });
84+
85+
child.relink(newParent);
86+
87+
expect(newParent.children.has(child)).to.be.true;
88+
});
89+
});
90+
91+
describe('getDepth', () => {
92+
it('should return 1 for a root node', () => {
93+
const root = new TreeNode({ value: 'root', parent: null });
94+
expect(root.getDepth()).to.equal(1);
95+
});
96+
97+
it('should return 2 for a child of root', () => {
98+
const root = new TreeNode({ value: 'root', parent: null });
99+
const child = new TreeNode({ value: 'child', parent: root });
100+
expect(child.getDepth()).to.equal(2);
101+
});
102+
103+
it('should return correct depth for deeply nested nodes', () => {
104+
const root = new TreeNode({ value: 'root', parent: null });
105+
const level1 = new TreeNode({ value: 'level1', parent: root });
106+
const level2 = new TreeNode({ value: 'level2', parent: level1 });
107+
const level3 = new TreeNode({ value: 'level3', parent: level2 });
108+
109+
expect(level3.getDepth()).to.equal(4);
110+
});
111+
112+
it('should return -1 when a cycle is detected', () => {
113+
const nodeA = new TreeNode({ value: 'a', parent: null });
114+
const nodeB = new TreeNode({ value: 'b', parent: nodeA });
115+
const nodeC = new TreeNode({ value: 'c', parent: nodeB });
116+
117+
// Create cycle: A -> B -> C -> A
118+
nodeA.relink(nodeC);
119+
120+
expect(nodeA.getDepth()).to.equal(-1);
121+
});
122+
});
123+
124+
describe('hasCycleWith', () => {
125+
it('should return false when there is no cycle', () => {
126+
const root = new TreeNode({ value: 'root', parent: null });
127+
const child = new TreeNode({ value: 'child', parent: root });
128+
129+
expect(child.hasCycleWith('nonexistent')).to.be.false;
130+
});
131+
132+
it('should return true when the target value exists in the parent chain', () => {
133+
const root = new TreeNode({ value: 'root', parent: null });
134+
const child = new TreeNode({ value: 'child', parent: root });
135+
136+
expect(child.hasCycleWith('root')).to.be.true;
137+
});
138+
139+
it('should return true when checking against own value', () => {
140+
const node = new TreeNode({ value: 'self', parent: null });
141+
expect(node.hasCycleWith('self')).to.be.true;
142+
});
143+
144+
it('should return false for root node with non-matching value', () => {
145+
const root = new TreeNode({ value: 'root', parent: null });
146+
expect(root.hasCycleWith('other')).to.be.false;
147+
});
148+
149+
it('should return false when cycle exists but target not in chain', () => {
150+
const nodeA = new TreeNode({ value: 'a', parent: null });
151+
const nodeB = new TreeNode({ value: 'b', parent: nodeA });
152+
const nodeC = new TreeNode({ value: 'c', parent: nodeB });
153+
154+
// Create cycle: A -> B -> C -> A
155+
nodeA.relink(nodeC);
156+
157+
expect(nodeA.hasCycleWith('nonexistent')).to.be.false;
158+
});
159+
});
160+
});

0 commit comments

Comments
 (0)