1import { describe, expect, it } from 'vitest'2import fixture from './fixtures/bpmn/core.bpmn?raw'3import productionFixture from '../../../examples/diagrams/example.bpmn?raw'4import { parseBpmn, renderBpmn } from '../src/adapters/bpmn'56describe('bounded BPMN DI-to-SVG adapter', () => {7 it('renders core shapes, connections, labels, and dimensions', () => {8 const parsed = parseBpmn(fixture); expect(parsed.shapes).toHaveLength(5); expect(parsed.edges).toHaveLength(4)9 const svg = renderBpmn(fixture)10 expect(svg).toContain('viewBox="0 0 606 121"'); expect(svg).toContain('Review order'); expect(svg).toContain('Approved?')11 expect(svg).toContain('marker-end="url(#bpmn-arrow)"'); expect(svg).toContain('data-bpmn-id="Gateway"')12 })13 it('rejects active XML, malformed DI, and oversized coordinates', () => {14 expect(() => renderBpmn('<!DOCTYPE definitions [<!ENTITY x "y">]><definitions/>')).toThrow(/doctype|entity/i)15 expect(() => renderBpmn('<definitions xmlns="x"><process id="p"><task id="t"/></process><bpmndi:BPMNDiagram xmlns:bpmndi="d"><bpmndi:BPMNPlane><bpmndi:BPMNShape bpmnElement="t"/></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></definitions>')).toThrow(/bounds|shapes/i)16 expect(() => renderBpmn(fixture.replace('x="20"', 'x="999999"'))).toThrow(/range|coordinate/i)17 expect(() => renderBpmn('x'.repeat(512 * 1024 + 1))).toThrow(/512 KiB/i)18 })19 it('escapes labels and does not emit active content', () => {20 const svg = renderBpmn(fixture.replace('name="Review order"', 'name="<x>&danger</x>"'))21 expect(svg).toContain('<x>&danger</x>'); expect(svg).not.toContain('<x>'); expect(svg).not.toContain('foreignObject')22 })23 it('renders the production fixture including empty BPMN label bounds', () => {24 const svg = renderBpmn(productionFixture)25 expect(svg).toContain('Examine Situation')26 expect(svg).toContain('Notification Sent')27 })28})