import { beforeEach, describe, expect, it } from 'vitest'; import { createEmptyMap } from '@/services/mapFactory'; import { useEditorStore } from '@/stores/editorStore'; function store() { return useEditorStore.getState(); } function rootId(): string { return store().map?.nodes[0]?.id as string; } function nodeById(id: string) { return store().map?.nodes.find((node) => node.id === id); } /** Cree trois noeuds a des positions connues, avec des tailles mesurees. */ function threeNodes(): string[] { const ids = [rootId()]; for (let index = 0; index < 2; index += 1) { ids.push(store().addChild(rootId()) as string); } store().setEditingNode(null); const positions = [ { x: 0, y: 0 }, { x: 60, y: 200 }, { x: 300, y: 500 }, ]; ids.forEach((id, index) => { store().moveNodes([{ id, position: positions[index] as { x: number; y: number } }]); store().setMeasuredSize(id, { width: 100, height: 40 }); }); return ids; } beforeEach(() => { useEditorStore.getState().loadMap(createEmptyMap('Mise en page')); }); describe('redimensionnement', () => { it('passe le noeud en taille fixe et conserve les dimensions', () => { const id = rootId(); store().beginResize(); store().resizeNode(id, { width: 260, height: 120 }); const node = nodeById(id); expect(node?.layout?.widthMode).toBe('fixed'); expect(node?.layout?.heightMode).toBe('fixed'); expect(node?.layout?.width).toBe(260); expect(node?.layout?.height).toBe(120); }); it('borne les dimensions saisies', () => { const id = rootId(); store().beginResize(); store().resizeNode(id, { width: -50, height: 100000 }); expect(nodeById(id)?.layout?.width).toBeGreaterThanOrEqual(60); expect(nodeById(id)?.layout?.height).toBeLessThanOrEqual(900); }); it('un resize continu ne cree qu une seule entree d historique', () => { const id = rootId(); const before = store().past.length; store().beginResize(); for (let width = 200; width <= 260; width += 10) { store().resizeNode(id, { width, height: 80 }); } expect(store().past.length).toBe(before + 1); store().undo(); expect(nodeById(id)?.layout?.width).toBeUndefined(); }); it('met a jour la position quand la poignee haut-gauche est utilisee', () => { const id = rootId(); store().beginResize(); store().resizeNode(id, { width: 200, height: 90, position: { x: -40, y: -20 } }); expect(nodeById(id)?.position).toEqual({ x: -40, y: -20 }); }); it('repasse en taille automatique avec "adapter au contenu"', () => { const id = rootId(); store().beginResize(); store().resizeNode(id, { width: 300, height: 150 }); store().fitNodesToContent([id]); const node = nodeById(id); expect(node?.layout?.width).toBeUndefined(); expect(node?.layout?.height).toBeUndefined(); expect(node?.layout?.widthMode).toBe('auto'); }); }); describe('alignement multi-selection', () => { it('aligne les bords gauches en une seule entree d historique', () => { const ids = threeNodes(); store().setSelection(ids); const before = store().past.length; store().alignNodes('left'); expect(store().past.length).toBe(before + 1); const xs = ids.map((id) => nodeById(id)?.position.x); expect(new Set(xs).size).toBe(1); expect(xs[0]).toBe(0); }); it('aligne les bords droits en tenant compte de la largeur', () => { const ids = threeNodes(); store().setMeasuredSize(ids[1] as string, { width: 200, height: 40 }); store().setSelection(ids); store().alignNodes('right'); const rights = ids.map((id) => { const node = nodeById(id); const width = id === ids[1] ? 200 : 100; return (node?.position.x ?? 0) + width; }); expect(new Set(rights).size).toBe(1); }); it('centre verticalement la selection', () => { const ids = threeNodes(); store().setSelection(ids); store().alignNodes('vcenter'); const centers = ids.map((id) => (nodeById(id)?.position.y ?? 0) + 20); expect(new Set(centers).size).toBe(1); }); it('ne fait rien avec un seul noeud selectionne', () => { const ids = threeNodes(); store().setSelection([ids[0] as string]); const before = store().past.length; store().alignNodes('left'); expect(store().past.length).toBe(before); }); }); describe('distribution', () => { it('repartit les espaces verticaux en conservant les extremes', () => { const ids = threeNodes(); store().setSelection(ids); const before = store().past.length; store().distributeNodes('vertical'); expect(store().past.length).toBe(before + 1); const ys = ids.map((id) => nodeById(id)?.position.y ?? 0).sort((a, b) => a - b); expect(ys[0]).toBe(0); expect(ys[2]).toBe(500); // Espaces egaux entre les bords : (500 + 40 - 0 - 120) / 2 = 210 expect((ys[1] as number) - ((ys[0] as number) + 40)).toBeCloseTo(210, 0); }); it('repartit les espaces horizontaux', () => { const ids = threeNodes(); store().setSelection(ids); store().distributeNodes('horizontal'); const xs = ids.map((id) => nodeById(id)?.position.x ?? 0).sort((a, b) => a - b); expect(xs[0]).toBe(0); expect(xs[2]).toBe(300); expect((xs[1] as number) - ((xs[0] as number) + 100)).toBeCloseTo( (xs[2] as number) - ((xs[1] as number) + 100), 0, ); }); it('exige au moins trois noeuds', () => { const ids = threeNodes(); store().setSelection([ids[0] as string, ids[1] as string]); const before = store().past.length; store().distributeNodes('horizontal'); expect(store().past.length).toBe(before); }); });