import { TypeInferrer } from '../src/type-inferrer.js'; describe('TypeInferrer', () => { describe('infer', () => { it('should infer string type', () => { const inferrer = new TypeInferrer({ rootName: 'StringType' }); const result = inferrer.infer('hello'); expect(result.types.length).toBeGreaterThan(0); }); it('should infer number type', () => { const inferrer = new TypeInferrer({ rootName: 'NumberType' }); const result = inferrer.infer(42); expect(result.types.length).toBeGreaterThan(0); }); it('should infer boolean type', () => { const inferrer = new TypeInferrer({ rootName: 'BooleanType' }); const result = inferrer.infer(true); expect(result.types.length).toBeGreaterThan(0); }); it('should infer null type', () => { const inferrer = new TypeInferrer({ rootName: 'NullType' }); const result = inferrer.infer(null); expect(result.types.length).toBeGreaterThan(0); }); it('should infer array of primitives', () => { const inferrer = new TypeInferrer(); const result = inferrer.infer([1, 2, 3]); expect(result.types.length).toBeGreaterThan(0); }); it('should infer array of strings', () => { const inferrer = new TypeInferrer(); const result = inferrer.infer(['a', 'b', 'c']); expect(result.types.length).toBeGreaterThan(0); }); it('should infer empty array', () => { const inferrer = new TypeInferrer(); const result = inferrer.infer([]); expect(result.types.length).toBeGreaterThan(0); }); it('should infer simple object', () => { const inferrer = new TypeInferrer({ rootName: 'User' }); const result = inferrer.infer({ name: 'John', age: 30, active: true, }); expect(result.types.length).toBeGreaterThan(0); expect(result.types[0].name).toBe('User'); }); it('should infer nested objects', () => { const inferrer = new TypeInferrer({ rootName: 'Company' }); const result = inferrer.infer({ name: 'Acme', address: { street: '123 Main St', city: 'Boston', }, }); expect(result.types.length).toBeGreaterThanOrEqual(1); expect(result.types.find(t => t.name === 'Company')).toBeDefined(); }); it('should infer array of objects', () => { const inferrer = new TypeInferrer({ rootName: 'UserList' }); const result = inferrer.infer([ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, ]); expect(result.types.length).toBeGreaterThan(0); }); it('should handle mixed type arrays', () => { const inferrer = new TypeInferrer(); const result = inferrer.infer([1, 'two', true]); expect(result.types.length).toBeGreaterThan(0); }); }); describe('inferFromMultiple', () => { it('should merge compatible objects', () => { const inferrer = new TypeInferrer({ rootName: 'User' }); const result = inferrer.inferFromMultiple([ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, ]); expect(result.types.length).toBeGreaterThan(0); expect(result.types[0].name).toBe('User'); }); it('should detect optional fields', () => { const inferrer = new TypeInferrer({ rootName: 'User' }); const result = inferrer.inferFromMultiple([ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob' }, ]); expect(result.types.length).toBeGreaterThan(0); }); it('should create union types for field variations', () => { const inferrer = new TypeInferrer({ rootName: 'Response' }); const result = inferrer.inferFromMultiple([ { id: 1 }, { id: 'two' }, ]); expect(result.types.length).toBeGreaterThan(0); }); it('should return empty result for empty samples', () => { const inferrer = new TypeInferrer(); const result = inferrer.inferFromMultiple([]); expect(result.types.length).toBe(0); expect(result.warnings.length).toBeGreaterThan(0); }); it('should handle single sample', () => { const inferrer = new TypeInferrer({ rootName: 'Single' }); const result = inferrer.inferFromMultiple([{ key: 'value' }]); expect(result.types.length).toBeGreaterThan(0); }); it('should create literal types for enum-like values', () => { const inferrer = new TypeInferrer({ rootName: 'Status' }); const result = inferrer.inferFromMultiple([ { status: 'active' }, { status: 'inactive' }, ]); expect(result.types.length).toBeGreaterThan(0); }); }); });