2026-08-26 20:53:42 +02:00
|
|
|
|
/**
|
|
|
|
|
|
* Seating-Tests — countSeats: Zählung nach Reihe/Block/Gesamt.
|
|
|
|
|
|
* Ergänzt Task B5; Grundlage ist der BUG-1-Fix (rowId pro Block-Reihe).
|
|
|
|
|
|
*/
|
|
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
|
|
|
|
import { SeatingService } from '../src/services/seatingService';
|
|
|
|
|
|
import type { CADElement } from '../src/types/cad.types';
|
|
|
|
|
|
|
|
|
|
|
|
function makeChair(id: string, props: Record<string, unknown> = {}): CADElement {
|
|
|
|
|
|
return {
|
|
|
|
|
|
id,
|
|
|
|
|
|
type: 'chair',
|
|
|
|
|
|
layerId: 'layer-1',
|
|
|
|
|
|
x: 0,
|
|
|
|
|
|
y: 0,
|
|
|
|
|
|
width: 50,
|
|
|
|
|
|
height: 50,
|
|
|
|
|
|
properties: props,
|
|
|
|
|
|
} as unknown as CADElement;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function makeNonChair(id: string): CADElement {
|
|
|
|
|
|
return {
|
|
|
|
|
|
id,
|
|
|
|
|
|
type: 'rect',
|
|
|
|
|
|
layerId: 'layer-1',
|
|
|
|
|
|
x: 0,
|
|
|
|
|
|
y: 0,
|
|
|
|
|
|
width: 10,
|
|
|
|
|
|
height: 10,
|
|
|
|
|
|
properties: {},
|
|
|
|
|
|
} as unknown as CADElement;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
describe('countSeats', () => {
|
|
|
|
|
|
const svc = new SeatingService();
|
|
|
|
|
|
|
|
|
|
|
|
it('zählt eine freie Reihe korrekt (5 Stühle, 1 rowId)', () => {
|
|
|
|
|
|
const els = svc.createSeatingRow(0, 0, 'layer-1', { count: 5 });
|
|
|
|
|
|
const result = svc.countSeats(els);
|
|
|
|
|
|
expect(result.total).toBe(5);
|
|
|
|
|
|
expect(Object.keys(result.byRow).length).toBe(1);
|
|
|
|
|
|
expect(Object.values(result.byRow)[0]).toBe(5);
|
|
|
|
|
|
expect(Object.keys(result.byBlock).length).toBe(0);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('zählt einen Block korrekt (3 Reihen × 4 Stühle = 12)', () => {
|
|
|
|
|
|
const els = svc.createSeatingBlock(0, 0, 'layer-1', { rows: 3, cols: 4 });
|
|
|
|
|
|
const result = svc.countSeats(els);
|
|
|
|
|
|
expect(result.total).toBe(12);
|
|
|
|
|
|
expect(Object.keys(result.byBlock).length).toBe(1); // 1 Block
|
|
|
|
|
|
expect(Object.values(result.byBlock)[0]).toBe(12);
|
|
|
|
|
|
expect(Object.keys(result.byRow).length).toBe(3); // 3 Reihen (BUG-1-Fix!)
|
|
|
|
|
|
for (const count of Object.values(result.byRow)) {
|
|
|
|
|
|
expect(count).toBe(4); // je Reihe 4 Stühle
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('summiert gemischte Zeichnung korrekt (Reihe + Block + Fremdelemente)', () => {
|
|
|
|
|
|
const rows = svc.createSeatingRow(0, 0, 'layer-1', { count: 3 });
|
|
|
|
|
|
const block = svc.createSeatingBlock(100, 100, 'layer-1', { rows: 2, cols: 2 });
|
|
|
|
|
|
const others = [makeNonChair('x1'), makeNonChair('x2')];
|
|
|
|
|
|
const all: CADElement[] = [...rows, ...block, ...others];
|
|
|
|
|
|
const result = svc.countSeats(all);
|
|
|
|
|
|
expect(result.total).toBe(7); // 3 + 4, Nicht-Stühle ignorieren
|
|
|
|
|
|
expect(Object.keys(result.byRow).length).toBe(3); // 1 freie Reihe + 2 Block-Reihen
|
|
|
|
|
|
expect(Object.keys(result.byBlock).length).toBe(1);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('liefert leere Summen bei leerer Eingabe', () => {
|
|
|
|
|
|
const result = svc.countSeats([]);
|
|
|
|
|
|
expect(result.total).toBe(0);
|
|
|
|
|
|
expect(result.byRow).toEqual({});
|
|
|
|
|
|
expect(result.byBlock).toEqual({});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('zählt handgebaute Stühle ohne rowId nur im Gesamt', () => {
|
|
|
|
|
|
const els = [makeChair('h1'), makeChair('h2'), makeChair('h3', { rowId: 'row_manual' })];
|
|
|
|
|
|
const result = svc.countSeats(els);
|
|
|
|
|
|
expect(result.total).toBe(3);
|
|
|
|
|
|
expect(result.byRow['row_manual']).toBe(1);
|
|
|
|
|
|
expect(Object.keys(result.byRow).length).toBe(1);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2026-08-27 23:55:11 +02:00
|
|
|
|
|
|
|
|
|
|
describe('exportSeatListCSV', () => {
|
|
|
|
|
|
const svc = new SeatingService();
|
|
|
|
|
|
|
|
|
|
|
|
it('erzeugt CSV mit Header und Stuhl-Zeilen', () => {
|
|
|
|
|
|
const els = svc.createSeatingRow(0, 0, 'layer-1', { count: 3 });
|
|
|
|
|
|
const csv = svc.exportSeatListCSV(els);
|
|
|
|
|
|
const lines = csv.split('\n');
|
|
|
|
|
|
expect(lines[0]).toBe('type,row_id,block_id,x,y');
|
|
|
|
|
|
expect(lines.length).toBe(4); // Header + 3 Stühle
|
|
|
|
|
|
expect(lines[1]).toContain('chair');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('ignoriert Nicht-Stuhl-Elemente', () => {
|
|
|
|
|
|
const chairs = svc.createSeatingRow(0, 0, 'layer-1', { count: 2 });
|
|
|
|
|
|
const other: CADElement = {
|
|
|
|
|
|
id: 'x1', type: 'rect', layerId: 'l', x: 0, y: 0, width: 1, height: 1, properties: {},
|
|
|
|
|
|
} as unknown as CADElement;
|
|
|
|
|
|
const csv = svc.exportSeatListCSV([...chairs, other]);
|
|
|
|
|
|
expect(csv.split('\n').length).toBe(3); // Header + 2 Stühle
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('leere Eingabe ergibt nur Header', () => {
|
|
|
|
|
|
expect(svc.exportSeatListCSV([])).toBe('type,row_id,block_id,x,y');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|