88 lines
3.0 KiB
TypeScript
88 lines
3.0 KiB
TypeScript
|
|
/**
|
|||
|
|
* Task G1 – Layout-Datenmodell: Yjs Map layoutId → LayoutDefinition.
|
|||
|
|
*
|
|||
|
|
* LayoutDefinition: { id, name, viewport: { center: {x,y}, scale },
|
|||
|
|
* frameBlockRef? }. CRUD über CADDocument, undo-getrackt, Persistence
|
|||
|
|
* läuft automatisch über die Yjs-Doc-Serialisierung (drawing json).
|
|||
|
|
*/
|
|||
|
|
import { describe, it, expect } from 'vitest';
|
|||
|
|
import { CADDocument } from '../src/kernel/document/CADDocument';
|
|||
|
|
import { createInMemoryDoc } from './helpers/inMemoryDoc';
|
|||
|
|
|
|||
|
|
function mkDoc(): CADDocument {
|
|||
|
|
const { ydoc } = createInMemoryDoc();
|
|||
|
|
return new CADDocument(ydoc);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const LAYOUT = {
|
|||
|
|
id: 'layout-1',
|
|||
|
|
name: 'A4 Plan',
|
|||
|
|
viewport: { center: { x: 100, y: 50 }, scale: 0.5 },
|
|||
|
|
frameBlockRef: 'frame-a4',
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
describe('G1: Layout-CRUD', () => {
|
|||
|
|
it('addLayout + getLayout: Layout landet mit allen Feldern in der Map', () => {
|
|||
|
|
const doc = mkDoc();
|
|||
|
|
doc.addLayout(LAYOUT);
|
|||
|
|
const loaded = doc.getLayout('layout-1');
|
|||
|
|
expect(loaded).toBeDefined();
|
|||
|
|
expect(loaded!.name).toBe('A4 Plan');
|
|||
|
|
expect(loaded!.viewport.center.x).toBe(100);
|
|||
|
|
expect(loaded!.viewport.center.y).toBe(50);
|
|||
|
|
expect(loaded!.viewport.scale).toBe(0.5);
|
|||
|
|
expect(loaded!.frameBlockRef).toBe('frame-a4');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('getAllLayouts liefert Array; leer ohne Layouts', () => {
|
|||
|
|
const doc = mkDoc();
|
|||
|
|
expect(doc.getAllLayouts()).toHaveLength(0);
|
|||
|
|
doc.addLayout(LAYOUT);
|
|||
|
|
doc.addLayout({ ...LAYOUT, id: 'layout-2', name: 'A3 Plan' });
|
|||
|
|
const all = doc.getAllLayouts();
|
|||
|
|
expect(all).toHaveLength(2);
|
|||
|
|
expect(all.map((l) => l.name)).toContain('A3 Plan');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('updateLayout ändert name und viewport shallow (id/struktur bleibt)', () => {
|
|||
|
|
const doc = mkDoc();
|
|||
|
|
doc.addLayout(LAYOUT);
|
|||
|
|
doc.updateLayout('layout-1', { name: 'A4 geändert', viewport: { center: { x: 0, y: 0 }, scale: 2 } });
|
|||
|
|
const loaded = doc.getLayout('layout-1');
|
|||
|
|
expect(loaded!.name).toBe('A4 geändert');
|
|||
|
|
expect(loaded!.viewport.scale).toBe(2);
|
|||
|
|
expect(loaded!.frameBlockRef).toBe('frame-a4'); // unverändert erhalten
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('deleteLayout entfernt Layout still (unbekannte ID kein Fehler)', () => {
|
|||
|
|
const doc = mkDoc();
|
|||
|
|
doc.addLayout(LAYOUT);
|
|||
|
|
doc.deleteLayout('layout-1');
|
|||
|
|
expect(doc.getLayout('layout-1')).toBeUndefined();
|
|||
|
|
expect(() => doc.deleteLayout('gibts-nicht')).not.toThrow();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe('G1: Undo-Integration', () => {
|
|||
|
|
it('Undo entfernt hinzugefügtes Layout wieder', () => {
|
|||
|
|
const doc = mkDoc();
|
|||
|
|
doc.addLayout(LAYOUT);
|
|||
|
|
expect(doc.getLayout('layout-1')).toBeDefined();
|
|||
|
|
doc.undo();
|
|||
|
|
expect(doc.getLayout('layout-1')).toBeUndefined();
|
|||
|
|
doc.redo();
|
|||
|
|
expect(doc.getLayout('layout-1')).toBeDefined();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('Layout-Undo ist EIN Schritt (nicht mit Element-Transaktion vermischt)', () => {
|
|||
|
|
const doc = mkDoc();
|
|||
|
|
doc.addLayout(LAYOUT);
|
|||
|
|
doc.deleteLayout('layout-1');
|
|||
|
|
// Zwei Schritte: undo stellt Löschung wieder her
|
|||
|
|
doc.undo();
|
|||
|
|
expect(doc.getLayout('layout-1')).toBeDefined();
|
|||
|
|
doc.undo();
|
|||
|
|
expect(doc.getLayout('layout-1')).toBeUndefined();
|
|||
|
|
});
|
|||
|
|
});
|