import { describe, expect, it } from 'vitest'; import { discoverCatalogueCandidates, formatCatalogueIntegrityReport, validateCatalogueIntegrity, } from '../src/modules/machines/catalogueIntegrity'; const validMachineFixture = [ { id: 'inline-four-engine', title: 'Inline-Four Engine', category: 'engines', summary: 'A four-cylinder reciprocating piston engine with crankshaft-driven valve timing.', tags: ['engine', 'combustion', 'crankshaft'], modelPath: '/models/engines/inline-four-engine.glb', cameraPresets: [{ id: 'isometric', label: 'Isometric' }], animation: { channels: [{ id: 'crankshaft-rpm', componentId: 'crankshaft', property: 'rotation.z' }], }, components: [ { id: 'crankshaft', name: 'Crankshaft', description: 'Converts reciprocating piston motion into rotational output torque.', explodedOffset: [0, -0.45, 0], }, { id: 'piston-assembly', name: 'Piston assembly', description: 'Transfers combustion force through the connecting rod to the crankshaft.', parentComponentId: 'crankshaft', explodedOffset: { x: 0, y: 0.65, z: 0 }, }, ], }, ]; describe('catalogue integrity validation', () => { it('accepts a complete data-driven machine definition without hard errors', () => { const summary = validateCatalogueIntegrity(validMachineFixture); expect(summary.passed).toBe(true); expect(summary.errors).toBe(0); expect(summary.machineCount).toBe(1); expect(summary.componentCount).toBe(2); expect(summary.categories).toEqual(['engines']); expect(summary.tags).toEqual(['combustion', 'crankshaft', 'engine']); }); it('reports duplicate machine and component ids as actionable errors', () => { const summary = validateCatalogueIntegrity([ { ...validMachineFixture[0], components: [ { id: 'shaft', name: 'Input shaft', description: 'Receives torque.', explodedOffset: [0, 0, 0], }, { id: 'shaft', name: 'Output shaft', description: 'Delivers torque.', explodedOffset: [0, 1, 0], }, ], }, { ...validMachineFixture[0], title: 'Duplicate Inline-Four Engine', }, ]); expect(summary.passed).toBe(false); expect(summary.errors).toBeGreaterThanOrEqual(2); expect(summary.issues.map((issue) => issue.code)).toEqual( expect.arrayContaining(['DUPLICATE_MACHINE_ID', 'DUPLICATE_COMPONENT_ID']), ); const report = formatCatalogueIntegrityReport(summary, { includeWarnings: false }); expect(report).toContain('DUPLICATE_MACHINE_ID'); expect(report).toContain('DUPLICATE_COMPONENT_ID'); expect(report).toContain('machines[0].components[1].id'); }); it('rejects malformed exploded-view vectors because they break viewer controls', () => { const summary = validateCatalogueIntegrity([ { ...validMachineFixture[0], components: [ { id: 'flywheel', name: 'Flywheel', description: 'Stores rotational inertia.', explodedOffset: [0, Number.NaN, 0], }, ], }, ]); expect(summary.passed).toBe(false); expect(summary.issues.map((issue) => issue.code)).toContain('INVALID_EXPLODED_VECTOR'); }); it('can discover machine arrays nested in category-oriented blueprint modules', () => { const candidates = discoverCatalogueCandidates( { blueprint: { engines: [validMachineFixture[0]], pumps: [ { ...validMachineFixture[0], id: 'centrifugal-pump', title: 'Centrifugal Pump', category: 'pumps', tags: ['pump', 'impeller'], }, ], }, }, 'fixture', ); expect(candidates.some((candidate) => candidate.aggregate && candidate.machines.length === 2)).toBe( true, ); expect(candidates.map((candidate) => candidate.name)).toEqual( expect.arrayContaining(['fixture.blueprint.engines', 'fixture.blueprint.pumps']), ); }); });