1import { describe, expect, it } from 'vitest'2import { ENGINE_CATALOG } from '../src/catalog'3import { ENGINE_IDS } from '../../shared/engines'45describe('engine catalog', () => {6 it('covers every catalog engine exactly once', () => {7 expect(ENGINE_CATALOG).toHaveLength(32)8 expect(new Set(ENGINE_CATALOG.map(engine => engine.id)).size).toBe(32)9 expect(ENGINE_CATALOG.map(engine => engine.id)).toEqual(ENGINE_IDS)10 })1112 it('reports an honest capability for every pinned renderer contract', () => {13 const presentationOnly = new Set(['diagramsnet'])14 for (const engine of ENGINE_CATALOG) {15 expect(engine.normalization).toMatchObject({16 schema: '1',17 normalizer: 'svg-normalizer-4',18 })19 expect(engine.normalization.profile).not.toBe('safe-raw-1')20 if (presentationOnly.has(engine.id)) {21 expect(engine.normalization).toMatchObject({22 profile: 'authored-svg-presentation-1',23 conformance: 'presentation-only',24 appearances: ['raw', 'auto-framed', 'light-framed', 'dark-framed'],25 })26 } else {27 expect(['semantic', 'adaptive']).toContain(engine.normalization.conformance)28 expect(engine.normalization.appearances).toEqual(expect.arrayContaining(['raw', 'auto-transparent', 'dark-framed']))29 }30 }31 expect(ENGINE_CATALOG.find(entry => entry.id === 'graphviz')?.normalization).toMatchObject({32 profile: 'graphviz-15-semantic-2',33 conformance: 'semantic',34 appearances: expect.arrayContaining(['raw', 'auto-transparent', 'dark-framed']),35 })36 for (const id of ['excalidraw', 'tikz']) {37 expect(ENGINE_CATALOG.find(entry => entry.id === id)?.normalization).toMatchObject({38 profile: 'authored-neutral-semantic-1',39 conformance: 'adaptive',40 appearances: expect.arrayContaining(['raw', 'auto-transparent', 'dark-framed']),41 })42 }43 })4445 it('marks the BlockDiag family as edge Python', () => {46 const family = ENGINE_CATALOG.filter(engine => [47 'blockdiag', 'seqdiag', 'actdiag', 'nwdiag', 'packetdiag', 'rackdiag',48 ].includes(engine.id))49 expect(family).toHaveLength(6)50 for (const engine of family) {51 expect(engine.activeRuntime).toBe('edge-python')52 expect(engine.version).toContain('python-worker-1')53 }54 })5556 it('marks GraphViz, DBML, and ERD as one edge-Wasm family', () => {57 const family = ENGINE_CATALOG.filter(engine => ['graphviz', 'dbml', 'erd'].includes(engine.id))58 expect(family).toHaveLength(3)59 for (const engine of family) {60 expect(engine.activeRuntime).toBe('edge-wasm')61 expect(engine.version).toContain('graphviz@15.1.1')62 }63 })6465 it('marks WireViz as a dedicated Python translator unit', () => {66 const wireviz = ENGINE_CATALOG.find(engine => engine.id === 'wireviz')!67 expect(wireviz.activeRuntime).toBe('edge-python')68 expect(wireviz.version).toContain('python-translator-1')69 })7071 it('marks Pikchr as a dedicated edge-Wasm unit', () => {72 const pikchr = ENGINE_CATALOG.find(engine => engine.id === 'pikchr')!73 expect(pikchr.activeRuntime).toBe('edge-wasm')74 expect(pikchr.version).toContain('pikchr@85e65b9686')75 })7677 it('marks Svgbob as a dedicated edge-Wasm unit', () => {78 const svgbob = ENGINE_CATALOG.find(engine => engine.id === 'svgbob')!79 expect(svgbob.activeRuntime).toBe('edge-wasm')80 expect(svgbob.version).toContain('svgbob@0.7.6')81 })8283 it('groups the Ditaa translation with the shared Svgbob edge-Wasm dependency', () => {84 const ditaa = ENGINE_CATALOG.find(engine => engine.id === 'ditaa')!85 expect(ditaa.activeRuntime).toBe('edge-wasm')86 expect(ditaa.version).toContain('svgbob@0.7.6')87 })8889 it('marks GoAT as a dedicated edge-Wasm unit', () => {90 const goat = ENGINE_CATALOG.find(engine => engine.id === 'goat')!91 expect(goat.activeRuntime).toBe('edge-wasm')92 expect(goat.version).toContain('goat@0.5.1')93 })9495 it('marks D2 as a dedicated edge-Wasm unit', () => {96 const d2 = ENGINE_CATALOG.find(engine => engine.id === 'd2')!97 expect(d2.activeRuntime).toBe('edge-wasm')98 expect(d2.version).toContain('d2@0.7.1/dagre-wasm')99 })100101 it('marks Symbolator as a dedicated Python translation unit', () => {102 const symbolator = ENGINE_CATALOG.find(engine => engine.id === 'symbolator')!103 expect(symbolator.activeRuntime).toBe('edge-python')104 expect(symbolator.version).toContain('symbolator@1.2.2/python-translation')105 })106107 it('marks PlantUML and lowered C4 as one edge-Wasm family', () => {108 const family = ENGINE_CATALOG.filter(engine => ['plantuml', 'c4plantuml'].includes(engine.id))109 expect(family).toHaveLength(2)110 for (const engine of family) {111 expect(engine.activeRuntime).toBe('edge-wasm')112 expect(engine.version).toContain('plantuml@1.2026.6')113 }114 })115116 it('marks diagrams.net as an official browser renderer', () => {117 const diagramsnet = ENGINE_CATALOG.find(engine => engine.id === 'diagramsnet')!118 expect(diagramsnet.activeRuntime).toBe('browser-run')119 expect(diagramsnet.version).toContain('diagrams.net@29.6.1')120 })121122 it('marks BPMN as a direct edge renderer', () => {123 const bpmn = ENGINE_CATALOG.find(engine => engine.id === 'bpmn')!124 expect(bpmn.activeRuntime).toBe('edge-js')125 expect(bpmn.version).toBe('diagramzip-bpmn-svg@1')126 })127128 it('marks Excalidraw as a native edge renderer', () => {129 const excalidraw = ENGINE_CATALOG.find(engine => engine.id === 'excalidraw')!130 expect(excalidraw.activeRuntime).toBe('edge-js')131 expect(excalidraw.version).toBe('@excalidraw/excalidraw@0.18.1')132 })133134 it('marks TikZ and UMLet as direct edge renderers', () => {135 const tikz = ENGINE_CATALOG.find(engine => engine.id === 'tikz')!136 const umlet = ENGINE_CATALOG.find(engine => engine.id === 'umlet')!137 expect(tikz.activeRuntime).toBe('edge-wasm')138 expect(tikz.version).toContain('tikzjax@1.0.63')139 expect(umlet.activeRuntime).toBe('edge-js')140 expect(umlet.version).toContain('diagramzip-umlet-svg')141 })142143 it('assigns every engine its final runtime and version', () => {144 for (const engine of ENGINE_CATALOG) {145 expect(engine.activeRuntime).toBe(engine.targetRuntime)146 expect(engine.version).not.toHaveLength(0)147 }148 })149})