diff --git a/test/spec.spec.ts b/test/spec.spec.ts new file mode 100644 index 0000000..61f59c1 --- /dev/null +++ b/test/spec.spec.ts @@ -0,0 +1,105 @@ +import { parseSpec } from '../src/utils/spec-parser.js'; + +describe('Spec Parser', () => { + describe('JSON parsing', () => { + it('should parse valid JSON spec', () => { + const content = JSON.stringify({ + name: 'test-cli', + version: '1.0.0', + description: 'A test CLI', + commands: [{ name: 'test', description: 'Test command' }], + }); + + const result = parseSpec({ content, format: 'json' }); + + expect(result.success).toBe(true); + expect(result.spec).toBeDefined(); + expect(result.spec?.name).toBe('test-cli'); + expect(result.spec?.version).toBe('1.0.0'); + }); + + it('should detect JSON format automatically', () => { + const content = '{"name": "test", "version": "1.0.0", "description": "test", "commands": [{"name": "cmd", "description": "a command"}]}'; + const result = parseSpec({ content, format: 'auto' }); + + expect(result.success).toBe(true); + }); + }); + + describe('YAML parsing', () => { + it('should parse valid YAML spec', () => { + const content = ` +name: test-cli +version: 1.0.0 +description: A test CLI +commands: + - name: test + description: Test command +`; + + const result = parseSpec({ content, format: 'yaml' }); + + expect(result.success).toBe(true); + expect(result.spec).toBeDefined(); + expect(result.spec?.name).toBe('test-cli'); + }); + + it('should detect YAML format automatically', () => { + const content = 'name: test\nversion: 1.0.0\ndescription: test\ncommands:\n - name: cmd\n description: a command'; + const result = parseSpec({ content, format: 'auto' }); + + expect(result.success).toBe(true); + }); + }); + + describe('Error handling', () => { + it('should fail on invalid JSON', () => { + const content = '{invalid json}'; + const result = parseSpec({ content, format: 'json' }); + + expect(result.success).toBe(false); + expect(result.errors).toBeDefined(); + expect(result.errors?.length).toBeGreaterThan(0); + }); + + it('should fail on missing required fields', () => { + const content = JSON.stringify({ + name: 'test', + commands: [], + }); + + const result = parseSpec({ content, format: 'json' }); + + expect(result.success).toBe(false); + expect(result.errors?.some((e) => e.includes('version'))).toBe(true); + }); + + it('should fail on empty commands array', () => { + const content = JSON.stringify({ + name: 'test', + version: '1.0.0', + description: 'test', + commands: [], + }); + + const result = parseSpec({ content, format: 'json' }); + + expect(result.success).toBe(false); + expect(result.errors?.some((e) => e.includes('command'))).toBe(true); + }); + + it('should fail when file does not exist', () => { + const result = parseSpec({ filePath: '/nonexistent/path/spec.yaml' }); + + expect(result.success).toBe(false); + expect(result.errors?.some((e) => e.includes('not found'))).toBe(true); + }); + + it('should fail when no content or file path provided', () => { + const result = parseSpec({}); + + expect(result.success).toBe(false); + expect(result.errors?.some((e) => e.includes('filePath or content'))).toBe(true); + }); + }); +});