import { describe, expect, it } from 'vitest'; import { toDxf } from '../src/lib/export-dxf'; const shape = { outer: [{ x: 0, y: 0 }, { x: 100, y: 0 }, { x: 100, y: 50 }, { x: 0, y: 50 }], holes: [[{ x: 10, y: 10 }, { x: 20, y: 10 }, { x: 20, y: 20 }]], }; /** Split DXF text into [groupCode, value] pairs. */ function pairs(dxf: string): [string, string][] { const lines = dxf.split('\r\n'); if (lines[lines.length - 1] === '') lines.pop(); const out: [string, string][] = []; for (let i = 0; i < lines.length; i += 2) out.push([lines[i].trim(), lines[i + 1]]); return out; } describe('toDxf', () => { it('is a well-formed R12 file in mm with CRLF line endings', () => { const dxf = toDxf(shape); expect(dxf).not.toMatch(/[^\r]\n/); const p = pairs(dxf); expect(p[0]).toEqual(['0', 'SECTION']); expect(p).toContainEqual(['1', 'AC1009']); const unitsIdx = p.findIndex(([c, v]) => c === '9' && v === '$INSUNITS'); expect(p[unitsIdx + 1]).toEqual(['70', '4']); expect(p[p.length - 1]).toEqual(['0', 'EOF']); }); it('writes one closed POLYLINE per ring with all vertices', () => { const p = pairs(toDxf(shape)); const entities = p.filter(([c]) => c === '0').map(([, v]) => v); expect(entities.filter((e) => e === 'POLYLINE')).toHaveLength(2); expect(entities.filter((e) => e === 'VERTEX')).toHaveLength(7); expect(entities.filter((e) => e === 'SEQEND')).toHaveLength(2); const polyIdx = p.findIndex(([c, v]) => c === '0' && v === 'POLYLINE'); const flags = p.slice(polyIdx, polyIdx + 8).find(([c]) => c === '70'); expect(flags).toEqual(['70', '1']); }); it('flips Y so the piece is not mirrored', () => { const p = pairs(toDxf(shape)); const firstVertex = p.findIndex(([c, v]) => c === '0' && v === 'VERTEX'); const x = p.slice(firstVertex).find(([c]) => c === '10')![1]; const y = p.slice(firstVertex).find(([c]) => c === '20')![1]; expect([x, y]).toEqual(['0', '50']); // (0,0) top-left → (0,50) in Y-up space }); });