Files
web-cad/frontend/tests/titleBlock.test.ts
T

100 lines
3.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Task G3 Titelblock: Blockdefinition mit attributierten Texten
* (Projekt/Datum/Maßstab/Autor) + auto-insert als Layout-Frame.
*
* Die Text-Elemente tragen tag/attdef-Metadaten (F5/F6-Konvention),
* sodass der Titelblock als DXF ATTDEF/ATTRIB roundtripped und das
* spätere PropertiesPanel (D12) das Formular daraus bauen kann.
*/
import { describe, it, expect } from 'vitest';
import { CADDocument } from '../src/kernel/document/CADDocument';
import { createInMemoryDoc } from './helpers/inMemoryDoc';
import {
createTitleBlockElements,
insertTitleBlockForLayout,
TITLE_BLOCK_NAME,
type TitleBlockMeta,
} from '../src/services/titleBlockService';
import type { LayoutDefinition } from '../src/types/cad.types';
const META: TitleBlockMeta = {
project: 'Musterhalle A4',
date: '2026-08-29',
scale: '1:100',
author: 'L. Admin',
};
function mkDoc(): CADDocument {
const { ydoc } = createInMemoryDoc();
return new CADDocument(ydoc);
}
const LAYOUT: LayoutDefinition = {
id: 'layout-1',
name: 'A4 Plan',
viewport: { center: { x: 0, y: 0 }, scale: 1 },
};
describe('G3: createTitleBlockElements', () => {
it('Rahmen + Titel + 4 attributierte Texte mit Standard-Tags', () => {
const els = createTitleBlockElements(META);
const rects = els.filter((e) => e.type === 'rect');
const texts = els.filter((e) => e.type === 'text');
expect(rects.length).toBeGreaterThanOrEqual(1);
expect(texts.length).toBe(5); // Titel + PROJEKT + DATUM + MASSSTAB + AUTOR
const tags = texts.map((t) => t.properties.tag).filter(Boolean);
expect(tags).toEqual(['PROJEKT', 'DATUM', 'MASSSTAB', 'AUTOR']);
// Nur die attributierten Texte tragen attdef (Titel-Label bewusst nicht):
const attrTexts = texts.filter((t) => t.properties.tag);
expect(attrTexts.every((t) => t.properties.attdef === true)).toBe(true);
// Werte stehen im Text
const proj = texts.find((t) => t.properties.tag === 'PROJEKT');
expect(String(proj!.properties.text)).toContain('Musterhalle A4');
const autor = texts.find((t) => t.properties.tag === 'AUTOR');
expect(String(autor!.properties.text)).toContain('L. Admin');
});
it('Texte folgen der tag=Wert-Konvention des F5-ATTDEF-Parsers', () => {
const els = createTitleBlockElements(META);
const scale = els.find((e) => e.properties.tag === 'MASSSTAB')!;
expect(String(scale.properties.text)).toBe('MASSSTAB=1:100');
expect(scale.properties.prompt).toBeTruthy();
});
it('leere Meta erzeugt Füllzeichen statt undefined', () => {
const els = createTitleBlockElements({});
const proj = els.find((e) => e.properties.tag === 'PROJEKT')!;
expect(String(proj.properties.text)).toBe('PROJEKT=—');
});
});
describe('G3: insertTitleBlockForLayout (auto-insert als Frame)', () => {
it('erzeugt Blockdefinition im Doc und setzt frameBlockRef im Layout', () => {
const doc = mkDoc();
doc.addLayout(LAYOUT);
const blockId = insertTitleBlockForLayout(doc, 'layout-1', META);
expect(typeof blockId).toBe('string');
const layout = doc.getLayout('layout-1');
expect(layout!.frameBlockRef).toBe(blockId);
const block = doc.getBlock(blockId);
expect(block).toBeDefined();
expect(block!.name).toBe(TITLE_BLOCK_NAME);
expect(block!.category).toBe('frame');
expect(block!.elements.length).toBe(6); // 1 rect + 5 text
});
it('vorhandener frameBlockRef wird ersetzt (kein Duplikat-Block je Re-Insert)', () => {
const doc = mkDoc();
doc.addLayout(LAYOUT);
const first = insertTitleBlockForLayout(doc, 'layout-1', META);
const second = insertTitleBlockForLayout(doc, 'layout-1', { ...META, project: 'Neu' });
expect(second).not.toBe(first);
expect(doc.getLayout('layout-1')!.frameBlockRef).toBe(second);
});
it('Layout ohne frameBlockRef bleibt unverändert bei fehlendem Layout (throws)', () => {
const doc = mkDoc();
expect(() => insertTitleBlockForLayout(doc, 'gibts-nicht', META)).toThrow();
});
});