test(stammbaum): cross-level marriage records a distinct cross-link (#724)
When the two spouses' parents sit at different structural levels, the structural owner keeps its hierarchy edge and the other parent->spouse edge is recorded in layout.crossLinks (rendered with a distinct dash). The couple still sits exactly adjacent in the owner's run and B keeps a real position. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -364,3 +364,44 @@ describe('buildLayout — multi-spouse ordering (#361)', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildLayout — cross-level marriage fallback (#724)', () => {
|
||||
// A bond is cross-level when the two spouses' parents sit at different
|
||||
// structural levels. Adjacency cannot keep both connectors short, so the
|
||||
// structural owner keeps its hierarchy edge and the other parent → spouse
|
||||
// edge becomes a distinct cross-link.
|
||||
const GP = '00000000-0000-0000-0000-0000000000e1'; // G0, deep branch ancestor
|
||||
const P = '00000000-0000-0000-0000-0000000000e2'; // G1, child of GP
|
||||
const A = '00000000-0000-0000-0000-0000000000e3'; // G2, child of P (nested deep)
|
||||
const R = '00000000-0000-0000-0000-0000000000e4'; // G1 root
|
||||
const B = '00000000-0000-0000-0000-0000000000e5'; // G2, child of R
|
||||
|
||||
it('records the displaced parent edge as a cross-link and keeps the couple adjacent', () => {
|
||||
const layout = buildLayout(
|
||||
[
|
||||
node(GP, 'GP', 0),
|
||||
node(P, 'P', 1),
|
||||
{ ...node(A, 'A', 2), birthYear: 1900 }, // earlier birth → A is structural owner
|
||||
node(R, 'R', 1),
|
||||
{ ...node(B, 'B', 2), birthYear: 1910 }
|
||||
],
|
||||
[
|
||||
parentEdge(GP, P, 'g1'),
|
||||
parentEdge(P, A, 'g2'),
|
||||
parentEdge(R, B, 'g3'),
|
||||
spouseEdge(A, B, 'sp')
|
||||
]
|
||||
);
|
||||
|
||||
// A owns; B is absorbed into A's run → couple is exactly adjacent.
|
||||
const posA = layout.positions.get(A)!;
|
||||
const posB = layout.positions.get(B)!;
|
||||
expect(posA.y).toBe(posB.y);
|
||||
expect(Math.abs(posA.x - posB.x)).toBe(NODE_W + COL_GAP);
|
||||
|
||||
// R → B is cross-level: it surfaces as a distinct cross-link, and the
|
||||
// geometry still lands on B's real position (carried redundantly).
|
||||
expect(layout.crossLinks).toEqual([{ parentId: R, childId: B }]);
|
||||
expect(layout.positions.get(B)).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user