Skip to content

Commit 6d0b6f9

Browse files
committed
test: add regression tests for parent pointer invariant after tree building
Add tests to verify that pulled-up directory children are correctly re-parented to the container node, not the phantom root. This ensures processCheckboxUpdates can walk ancestors and find visible tree nodes for refresh() calls. Tests cover: - getParent() correctly returns undefined after re-parenting - ancestor walk stops at topmost visible directory, not phantom root
1 parent 2660f43 commit 6d0b6f9

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

src/test/view/treeNodes/directoryTreeNode.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,57 @@ describe('DirectoryTreeNode', function () {
206206
assert.strictEqual(rootDir.checkboxState?.state, vscode.TreeItemCheckboxState.Unchecked);
207207
});
208208
});
209+
210+
describe('parent pointer after phantom-root pull-up', function () {
211+
// When a tree has multiple top-level directories, a temporary DirectoryTreeNode
212+
// with label='' (phantom root) is used to build the tree, then its children are
213+
// pulled up to the actual container. If children are not re-parented, getParent()
214+
// still returns the phantom DirectoryTreeNode and processCheckboxUpdates fires
215+
// refresh() on an invisible node, so checkbox state never updates visually.
216+
217+
it('getParent() returns undefined after child is re-parented to the container', function () {
218+
const container = createMockParent();
219+
const phantomRoot = new DirectoryTreeNode(container, '');
220+
const subDir = new DirectoryTreeNode(phantomRoot, 'src');
221+
222+
// Before re-parenting: parent is the phantom root DirectoryTreeNode
223+
assert.ok(subDir.getParent() instanceof DirectoryTreeNode, 'sanity: should point to phantom root before re-parenting');
224+
225+
// Simulate the pull-up re-parenting fix applied in filesCategoryNode / pullRequestNode / commitNode
226+
subDir.parent = container;
227+
228+
// After re-parenting: container is not a TreeNode, so getParent() returns undefined.
229+
// This means the ancestor walk in processCheckboxUpdates stops here and refresh()
230+
// is called on the visible subDir node, not the invisible phantom root.
231+
assert.strictEqual(subDir.getParent(), undefined, 'after re-parenting, getParent() should not return the phantom root');
232+
});
233+
234+
it('ancestor walk stops at the topmost visible directory after re-parenting', function () {
235+
const container = createMockParent();
236+
const phantomRoot = new DirectoryTreeNode(container, '');
237+
const topDir = new DirectoryTreeNode(phantomRoot, 'cloud');
238+
const subDir = new DirectoryTreeNode(topDir, 'helm');
239+
const file = new MockFileNode(subDir);
240+
file.checkboxState = { state: vscode.TreeItemCheckboxState.Checked };
241+
242+
(subDir._children as any[]).push(file);
243+
topDir._children.push(subDir);
244+
245+
// Re-parent: simulate fix
246+
topDir.parent = container;
247+
248+
// Walk ancestors from file, mimicking processCheckboxUpdates
249+
const ancestors: TreeNode[] = [];
250+
let current = file.getParent();
251+
while (current instanceof DirectoryTreeNode) {
252+
ancestors.push(current);
253+
current = current.getParent();
254+
}
255+
256+
// Should find subDir and topDir, but NOT the phantom root
257+
assert.strictEqual(ancestors.length, 2);
258+
assert.strictEqual(ancestors[0], subDir);
259+
assert.strictEqual(ancestors[1], topDir);
260+
});
261+
});
209262
});

0 commit comments

Comments
 (0)