Files
web-cad/frontend/tests/elementDrawers.test.ts

177 lines
6.3 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.
/**
* elementToPrimitives Tests (Task C2).
* Deckt alle unterstützten Typen + Legacy-Konventionen + Grenzfälle ab.
*/
import { describe, it, expect } from 'vitest';
import { elementToPrimitives } from '../src/render/pixi/elementDrawers';
import type { CADElement } from '../src/types/cad.types';
function el(id: string, type: string, props: Record<string, unknown> = {}, geom: Partial<CADElement> = {}): CADElement {
return {
id,
type,
layerId: 'l',
x: 0,
y: 0,
width: 10,
height: 10,
properties: props,
...geom,
} as unknown as CADElement;
}
describe('elementToPrimitives', () => {
it('line: aus properties.x1..y2 mit stroke/sw', () => {
const prims = elementToPrimitives(el('l', 'line', {
x1: 0, y1: 0, x2: 100, y2: 50, stroke: '#f00', strokeWidth: 3,
}));
expect(prims.length).toBe(1);
expect(prims[0]).toEqual({
kind: 'line', from: { x: 0, y: 0 }, to: { x: 100, y: 50 },
stroke: '#f00', strokeWidth: 3,
});
});
it('line ohne Koordinaten ergibt leere Liste', () => {
expect(elementToPrimitives(el('l', 'line', {}))).toEqual([]);
});
it('rect: x/y ist Zentrum der BBox (Legacy-Konvention)', () => {
const prims = elementToPrimitives(el('r', 'rect', { fill: '#123456' }, {
x: 100, y: 50, width: 80, height: 40,
}));
expect(prims.length).toBe(1);
const p = prims[0];
if (p.kind !== 'rect') throw new Error('erwartete rect');
expect(p.x).toBe(60); // 100 40
expect(p.y).toBe(30); // 50 20
expect(p.w).toBe(80);
expect(p.h).toBe(40);
expect(p.fill).toBe('#123456');
});
it('rect fill none wird zu null', () => {
const prims = elementToPrimitives(el('r', 'rect', { fill: 'none' }));
const p = prims[0];
if (p.kind !== 'rect') throw new Error('erwartete rect');
expect(p.fill).toBeNull();
});
it('circle: radius mit Fallback width/2', () => {
const withExplicit = elementToPrimitives(el('c', 'circle', { radius: 25, fill: '#abcdef' }, { x: 5, y: 5 }));
const p = withExplicit[0];
if (p.kind !== 'circle') throw new Error('erwartete circle');
expect(p.radius).toBe(25);
expect(p.center).toEqual({ x: 5, y: 5 });
expect(p.fill).toBe('#abcdef');
const byWidth = elementToPrimitives(el('c', 'circle', {}, { width: 120 }));
const pb = byWidth[0];
if (pb.kind !== 'circle') throw new Error('erwartete circle');
expect(pb.radius).toBe(60); // fallback
});
it('arc: Winkel in Grad wie Legacy', () => {
const prims = elementToPrimitives(el('a', 'arc', {
radius: 40, startAngle: 0, endAngle: 90,
}, { x: 0, y: 0 }));
const p = prims[0];
if (p.kind !== 'arc') throw new Error('erwartete arc');
expect(p.startDeg).toBe(0);
expect(p.endDeg).toBe(90);
expect(p.radius).toBe(40);
});
it('polyline/polygon: points-Array, close je nach Typ', () => {
const pts = [{ x: 0, y: 0 }, { x: 10, y: 0 }, { x: 10, y: 10 }];
const open = elementToPrimitives(el('pl', 'polyline', { points: pts }));
const closed = elementToPrimitives(el('pg', 'polygon', { points: pts }));
expect(open.length).toBe(1);
expect(closed.length).toBe(1);
if (open[0].kind !== 'polyline' || closed[0].kind !== 'polyline') {
throw new Error('erwartete polyline');
}
expect(open[0].close).toBe(false);
expect(closed[0].close).toBe(true);
});
it('text: leer nicht gerendert; gefuellt mit fontSize/color', () => {
expect(elementToPrimitives(el('t', 'text', { text: '' }))).toEqual([]);
const filled = elementToPrimitives(el('t', 'text', {
text: 'Bühne A', fontSize: 18, color: '#ffffff',
}, { x: 50, y: 75 }));
expect(filled.length).toBe(1);
const p = filled[0];
if (p.kind !== 'text') throw new Error('erwartete text');
expect(p.text).toBe('Bühne A');
expect(p.fontSize).toBe(18);
expect(p.color).toBe('#ffffff');
});
it('unbekannter Typ ergibt leere Liste (renderer-sicher)', () => {
expect(elementToPrimitives(el('x', 'definitely-unknown'))).toEqual([]);
});
it('dimension: komplette Bemassung (Extension+Masslinie+Pfeile+Text, CAD-1)', () => {
const prims = elementToPrimitives(el('d', 'dimension', {
x1: 0, y1: 0, x2: 100, y2: 0, value: '250 cm',
}, { x: 50, y: 0 }));
// CAD-1: 2 Extension lines + 1 Masslinie + 2 Pfeilspitzen + 1 Text = 6
expect(prims.length).toBe(6);
expect(prims.filter((p) => p.kind === 'line').length).toBe(3);
expect(prims.filter((p) => p.kind === 'polyline').length).toBe(2);
const txt = prims.find((p) => p.kind === 'text');
if (!txt || txt.kind !== 'text') throw new Error('erwartete text');
expect(txt.text).toBe('250 cm');
});
it('leader: Linie + Label am Ende', () => {
const prims = elementToPrimitives(el('ld', 'leader', {
x1: 10, y1: 10, x2: 80, y2: 60, text: 'A1', fontSize: 14,
}));
expect(prims.length).toBe(2);
expect(prims[0].kind).toBe('line');
const txt = prims[1];
if (txt.kind !== 'text') throw new Error('erwartete text');
expect(txt.text).toBe('A1');
expect(txt.fontSize).toBe(14);
});
it('revcloud: geschlossener Punktzug', () => {
const prims = elementToPrimitives(el('rc', 'revcloud', {
points: [{ x: 0, y: 0 }, { x: 50, y: 0 }, { x: 50, y: 30 }],
}));
expect(prims.length).toBe(1);
const p = prims[0];
if (p.kind !== 'polyline') throw new Error('erwartete polyline');
expect(p.close).toBe(true);
});
it('chair: gefuelltes Rechteck mit Fallback-Farbe', () => {
const prims = elementToPrimitives(el('ch', 'chair', {}, { x: 50, y: 50, width: 20, height: 20 }));
const p = prims[0];
if (p.kind !== 'rect') throw new Error('erwartete rect');
expect(p.fill).toBe('#4a90d9');
expect(p.x).toBe(40);
expect(p.y).toBe(40);
});
it('table: Kreis mit Fallback-Farbe und Radius aus width', () => {
const prims = elementToPrimitives(el('tb', 'table', {}, { x: 0, y: 0, width: 60, height: 60 }));
const p = prims[0];
if (p.kind !== 'circle') throw new Error('erwartete circle');
expect(p.radius).toBe(30);
expect(p.fill).toBe('#8b7355');
});
it('stage: dunkles Rechteck', () => {
const prims = elementToPrimitives(el('st', 'stage', {}, { x: 0, y: 0, width: 200, height: 100 }));
const p = prims[0];
if (p.kind !== 'rect') throw new Error('erwartete rect');
expect(p.fill).toBe('#3a3a4a');
expect(p.w).toBe(200);
expect(p.h).toBe(100);
});
});