test(stammbaum): a bloodline occupies one contiguous band (#724)

No node outside a root's structural subtree may intrude into that bloodline's
[minX, maxX] horizontal span — the contiguity guarantee that fixes the smeared
bloodline symptom.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-06-04 13:38:40 +02:00
committed by marcel
parent 0cd4882ef4
commit 1d55901388

View File

@@ -539,4 +539,46 @@ describe('buildLayout — ancestor centring invariant (#724)', () => {
}
}
});
it('a bloodline occupies one contiguous band — no foreign node interleaved', () => {
// Two roots, each its own bloodline. The first fans out two generations
// deep; the contour pack must keep it as one band with nothing from the
// other bloodline wedged inside its horizontal span.
const nodes = [
node('R1', 'R1', 0),
node('a', 'a', 1),
node('b', 'b', 1),
node('a1', 'a1', 2),
node('R2', 'R2', 0),
node('c', 'c', 1)
];
const edges = [
parentEdge('R1', 'a'),
parentEdge('R1', 'b'),
parentEdge('a', 'a1'),
parentEdge('R2', 'c')
];
const layout = buildLayout(nodes, edges);
const forest = buildFamilyForest(nodes, edges);
// Collect the R1 bloodline: every member of its unit subtree.
const r1 = forest.roots.find((u) => u.id === 'R1')!;
const bloodline = new Set<string>();
const collect = (u: Unit) => {
u.members.forEach((m) => bloodline.add(m));
u.children.forEach(collect);
};
collect(r1);
const bandXs = [...bloodline].map((id) => layout.positions.get(id)!.x);
const minX = Math.min(...bandXs);
const maxX = Math.max(...bandXs) + NODE_W;
// No node outside the bloodline may intrude into its [minX, maxX] band.
for (const [id, p] of layout.positions) {
if (bloodline.has(id)) continue;
const intrudes = p.x < maxX && p.x + NODE_W > minX;
expect(intrudes, `foreign node ${id} interleaved into the R1 band`).toBe(false);
}
});
});