/
nek5132
/
Genius
Обзор
Документация
Войти
/
nek5132
/
Genius
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tests/verticalLayout.test.js
218 строк
11 KB
Peter Kosov
fix(rotation): stabilize safe branch turning and hub routing
15 апр 2026, 06:33
15 апр 2026, 06:33
1afa792
Код
Авторство
О чём код?
import { describe, it, expect } from '@jest/globals'; import { LayoutEngine } from '../src/core/LayoutEngine.js'; describe('LayoutEngine - Vertical Orientation', () => { const engine = new LayoutEngine(); it('ancestors should be BELOW root (lower Y)', () => { const state = { config: { modelProfile: 'genealogy', layoutVersion: 'ortho-tree-v1', styleVersion: 'white-gray-v1' }, entities: [ { id: 'p1', kind: 'person', attrs: { gender: 'male', birthYear: 1940 } }, { id: 'p2', kind: 'person', attrs: { gender: 'female', birthYear: 1945 } }, { id: 'p3', kind: 'person', attrs: { gender: 'male', birthYear: 1870 } }, { id: 'p4', kind: 'person', attrs: { gender: 'female', birthYear: 1875 } } ], groups: [ { id: 'f1', kind: 'family', memberIds: ['p1', 'p2'], attrs: { husbandId: 'p1', wifeId: 'p2', childrenIds: [] } }, { id: 'f2', kind: 'family', memberIds: ['p3', 'p4', 'p1'], attrs: { husbandId: 'p3', wifeId: 'p4', childrenIds: ['p1'] } } ], relations: [ { id: 'r1', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f2', childFamilyId: 'f1', childPersonId: 'p1' } } ] }; const scene = engine.compute(state, '3d', 'vertical-3d'); const rootHub = scene.nodes.find(n => n.role === 'family_hub' && n.groupId === 'f1'); const ancestorHub = scene.nodes.find(n => n.role === 'family_hub' && n.groupId === 'f2'); expect(ancestorHub.position.y).toBeLessThan(rootHub.position.y); }); it('descendants should be ABOVE root (higher Y)', () => { const state = { config: { modelProfile: 'genealogy', layoutVersion: 'ortho-tree-v1', styleVersion: 'white-gray-v1' }, entities: [ { id: 'p1', kind: 'person', attrs: { gender: 'male', birthYear: 1940 } }, { id: 'p2', kind: 'person', attrs: { gender: 'female', birthYear: 1945 } }, { id: 'p3', kind: 'person', attrs: { gender: 'male', birthYear: 1970 } } ], groups: [ { id: 'f1', kind: 'family', memberIds: ['p1', 'p2'], attrs: { husbandId: 'p1', wifeId: 'p2', childrenIds: [] } }, { id: 'f2', kind: 'family', memberIds: ['p3'], attrs: { husbandId: 'p3', wifeId: null, childrenIds: [] } } ], relations: [ { id: 'r1', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f1', childFamilyId: 'f2', childPersonId: 'p3' } } ] }; const scene = engine.compute(state, '3d', 'vertical-3d'); const rootHub = scene.nodes.find(n => n.role === 'family_hub' && n.groupId === 'f1'); const descendantHub = scene.nodes.find(n => n.role === 'family_hub' && n.groupId === 'f2'); expect(descendantHub.position.y).toBeGreaterThan(rootHub.position.y); }); it('three-generation tree: ancestors below root, descendants above', () => { const state = { config: { modelProfile: 'genealogy', layoutVersion: 'ortho-tree-v1', styleVersion: 'white-gray-v1' }, entities: [ { id: 'p1', kind: 'person', attrs: { gender: 'male', birthYear: 1940 } }, { id: 'p2', kind: 'person', attrs: { gender: 'female', birthYear: 1945 } }, { id: 'p3', kind: 'person', attrs: { gender: 'male', birthYear: 1870 } }, { id: 'p4', kind: 'person', attrs: { gender: 'female', birthYear: 1875 } }, { id: 'p5', kind: 'person', attrs: { gender: 'male', birthYear: 1970 } } ], groups: [ { id: 'f1', kind: 'family', memberIds: ['p1', 'p2'], attrs: { husbandId: 'p1', wifeId: 'p2', childrenIds: [] } }, { id: 'f2', kind: 'family', memberIds: ['p3', 'p4', 'p1'], attrs: { husbandId: 'p3', wifeId: 'p4', childrenIds: ['p1'] } }, { id: 'f3', kind: 'family', memberIds: ['p5'], attrs: { husbandId: 'p5', wifeId: null, childrenIds: [] } } ], relations: [ { id: 'r1', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f2', childFamilyId: 'f1', childPersonId: 'p1' } }, { id: 'r2', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f1', childFamilyId: 'f3', childPersonId: 'p5' } } ] }; const scene = engine.compute(state, '3d', 'vertical-3d'); const ancestorHub = scene.nodes.find(n => n.role === 'family_hub' && n.groupId === 'f2'); const rootHub = scene.nodes.find(n => n.role === 'family_hub' && n.groupId === 'f1'); const descendantHub = scene.nodes.find(n => n.role === 'family_hub' && n.groupId === 'f3'); expect(ancestorHub.position.y).toBeLessThan(rootHub.position.y); expect(rootHub.position.y).toBeLessThan(descendantHub.position.y); }); }); describe('LayoutEngine - Node Separation', () => { const engine = new LayoutEngine(); it('nodes within same family have minimum separation', () => { const state = { config: { modelProfile: 'genealogy', layoutVersion: 'ortho-tree-v1', styleVersion: 'white-gray-v1' }, entities: [ { id: 'p1', kind: 'person', attrs: { gender: 'male' } }, { id: 'p2', kind: 'person', attrs: { gender: 'female' } } ], groups: [ { id: 'f1', kind: 'family', memberIds: ['p1', 'p2'], attrs: { husbandId: 'p1', wifeId: 'p2', childrenIds: [] } } ], relations: [] }; const scene = engine.compute(state, '3d', 'vertical-3d'); const p1 = scene.nodes.find(n => n.id === 'p1'); const p2 = scene.nodes.find(n => n.id === 'p2'); const dx = Math.abs(p1.position.x - p2.position.x); expect(dx).toBeGreaterThan(0); }); it('hubs at same Y level have minimum horizontal separation', () => { const state = { config: { modelProfile: 'genealogy', layoutVersion: 'ortho-tree-v1', styleVersion: 'white-gray-v1' }, entities: [ { id: 'p1', kind: 'person', attrs: { gender: 'male' } }, { id: 'p2', kind: 'person', attrs: { gender: 'female' } }, { id: 'p3', kind: 'person', attrs: { gender: 'male' } }, { id: 'p4', kind: 'person', attrs: { gender: 'female' } } ], groups: [ { id: 'f1', kind: 'family', memberIds: ['p1', 'p2'], attrs: { husbandId: 'p1', wifeId: 'p2', childrenIds: [] } }, { id: 'f2', kind: 'family', memberIds: ['p3', 'p4'], attrs: { husbandId: 'p3', wifeId: 'p4', childrenIds: [] } } ], relations: [] }; const scene = engine.compute(state, '3d', 'vertical-3d'); const hub1 = scene.nodes.find(n => n.id === 'hub-f1'); const hub2 = scene.nodes.find(n => n.id === 'hub-f2'); const dx = Math.abs(hub1.position.x - hub2.position.x); expect(dx).toBeGreaterThan(0); }); it('no overlapping nodes in complex tree', () => { const state = { config: { modelProfile: 'genealogy', layoutVersion: 'ortho-tree-v1', styleVersion: 'white-gray-v1' }, entities: [ { id: 'p1', kind: 'person', attrs: { gender: 'male', birthYear: 1940 } }, { id: 'p2', kind: 'person', attrs: { gender: 'female', birthYear: 1945 } }, { id: 'p3', kind: 'person', attrs: { gender: 'male', birthYear: 1970 } }, { id: 'p4', kind: 'person', attrs: { gender: 'female', birthYear: 1972 } }, { id: 'p5', kind: 'person', attrs: { gender: 'male', birthYear: 1870 } }, { id: 'p6', kind: 'person', attrs: { gender: 'female', birthYear: 1875 } } ], groups: [ { id: 'f1', kind: 'family', memberIds: ['p1', 'p2'], attrs: { husbandId: 'p1', wifeId: 'p2', childrenIds: ['p3'] } }, { id: 'f2', kind: 'family', memberIds: ['p3', 'p4'], attrs: { husbandId: 'p3', wifeId: 'p4', childrenIds: [] } }, { id: 'f3', kind: 'family', memberIds: ['p5', 'p6', 'p1'], attrs: { husbandId: 'p5', wifeId: 'p6', childrenIds: ['p1'] } } ], relations: [ { id: 'r1', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f1', childFamilyId: 'f2', childPersonId: 'p3' } }, { id: 'r2', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f3', childFamilyId: 'f1', childPersonId: 'p1' } } ] }; const scene = engine.compute(state, '3d', 'vertical-3d'); const personNodes = scene.nodes.filter(n => n.role === 'person'); const MIN_SEPARATION = 5; for (let i = 0; i < personNodes.length; i++) { for (let j = i + 1; j < personNodes.length; j++) { const p1 = personNodes[i].position; const p2 = personNodes[j].position; const dist = Math.sqrt( Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2) + Math.pow(p1.z - p2.z, 2) ); expect(dist).toBeGreaterThanOrEqual(MIN_SEPARATION); } } }); }); describe('LayoutEngine - Edge Routing', () => { const engine = new LayoutEngine(); it('edges do not intersect with family hubs', () => { const state = { config: { modelProfile: 'genealogy', layoutVersion: 'ortho-tree-v1', styleVersion: 'white-gray-v1' }, entities: [ { id: 'p1', kind: 'person', attrs: { gender: 'male', birthYear: 1940 } }, { id: 'p2', kind: 'person', attrs: { gender: 'female', birthYear: 1945 } }, { id: 'p3', kind: 'person', attrs: { gender: 'male', birthYear: 1970 } } ], groups: [ { id: 'f1', kind: 'family', memberIds: ['p1', 'p2'], attrs: { husbandId: 'p1', wifeId: 'p2', childrenIds: ['p3'] } }, { id: 'f2', kind: 'family', memberIds: ['p3'], attrs: { husbandId: 'p3', wifeId: null, childrenIds: [] } } ], relations: [ { id: 'r1', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f1', childFamilyId: 'f2', childPersonId: 'p3' } } ] }; const scene = engine.compute(state, '3d', 'vertical-3d'); const edge = scene.edges.find(e => e.role === 'parent-child'); expect(edge).toBeDefined(); expect(edge.route.points.length).toBeGreaterThanOrEqual(3); }); it('multiple siblings have separate edge paths', () => { const state = { config: { modelProfile: 'genealogy', layoutVersion: 'ortho-tree-v1', styleVersion: 'white-gray-v1' }, entities: [ { id: 'p1', kind: 'person', attrs: { gender: 'male', birthYear: 1940 } }, { id: 'p2', kind: 'person', attrs: { gender: 'female', birthYear: 1945 } }, { id: 'p3', kind: 'person', attrs: { gender: 'male', birthYear: 1970 } }, { id: 'p4', kind: 'person', attrs: { gender: 'female', birthYear: 1972 } }, { id: 'p5', kind: 'person', attrs: { gender: 'male', birthYear: 1975 } } ], groups: [ { id: 'f1', kind: 'family', memberIds: ['p1', 'p2'], attrs: { husbandId: 'p1', wifeId: 'p2', childrenIds: ['p3', 'p4', 'p5'] } }, { id: 'f2', kind: 'family', memberIds: ['p3'], attrs: { husbandId: 'p3', wifeId: null, childrenIds: [] } }, { id: 'f3', kind: 'family', memberIds: ['p4'], attrs: { husbandId: 'p4', wifeId: null, childrenIds: [] } }, { id: 'f4', kind: 'family', memberIds: ['p5'], attrs: { husbandId: 'p5', wifeId: null, childrenIds: [] } } ], relations: [ { id: 'r1', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f1', childFamilyId: 'f2', childPersonId: 'p3' } }, { id: 'r2', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f1', childFamilyId: 'f3', childPersonId: 'p4' } }, { id: 'r3', kind: 'parent-child-family-link', attrs: { parentFamilyId: 'f1', childFamilyId: 'f4', childPersonId: 'p5' } } ] }; const scene = engine.compute(state, '3d', 'vertical-3d'); const edges = scene.edges.filter(e => e.role === 'parent-child'); expect(edges.length).toBe(3); edges.forEach(edge => { expect(edge.route.points.length).toBeGreaterThanOrEqual(3); }); }); });