Files
typeflow/test/parser.test.ts
7000pctAUTO 312d0e9782
Some checks failed
CI / test (push) Has been cancelled
Add test files
2026-01-30 01:03:05 +00:00

310 lines
7.5 KiB
TypeScript

import { TypeParser, createTypeParser } from '../src/parsers/typeParser';
import { InterfaceParser, createInterfaceParser } from '../src/parsers/interfaceParser';
import { TypeAliasParser, createTypeAliasParser } from '../src/parsers/typeAliasParser';
import { ImportParser, createImportParser } from '../src/parsers/importParser';
describe('TypeParser', () => {
let parser: ReturnType<typeof createTypeParser>;
beforeEach(() => {
parser = createTypeParser();
});
describe('parse', () => {
it('should parse a simple interface', () => {
const source = `
interface User {
id: number;
name: string;
email: string;
}
`;
const result = parser.parse(source, 'test.ts');
expect(result.types).toHaveLength(1);
expect(result.types[0].name).toBe('User');
expect(result.types[0].kind).toBe('interface');
});
it('should parse multiple interfaces', () => {
const source = `
interface A {
id: number;
}
interface B {
name: string;
}
`;
const result = parser.parse(source, 'test.ts');
expect(result.types).toHaveLength(2);
});
it('should parse type aliases', () => {
const source = `
type ID = number | string;
type UserResponse = {
id: ID;
name: string;
};
`;
const result = parser.parse(source, 'test.ts');
expect(result.types.length).toBeGreaterThanOrEqual(1);
});
it('should parse enums', () => {
const source = `
enum Status {
Pending = 'pending',
Approved = 'approved',
Rejected = 'rejected'
}
`;
const result = parser.parse(source, 'test.ts');
expect(result.types.some(t => t.kind === 'enum')).toBe(true);
});
it('should parse imports', () => {
const source = `
import { A, B } from './module';
import C from './default';
import * as D from './namespace';
`;
const result = parser.parse(source, 'test.ts');
expect(result.imports.length).toBe(3);
});
it('should handle empty source', () => {
const source = '';
const result = parser.parse(source, 'test.ts');
expect(result.types).toHaveLength(0);
expect(result.imports).toHaveLength(0);
});
it('should track dependencies', () => {
const source = `
interface A {
b: B;
}
interface B {
c: C;
}
`;
const result = parser.parse(source, 'test.ts');
const a = result.types.find(t => t.name === 'A');
expect(a?.dependencies).toContain('B');
});
});
});
describe('InterfaceParser', () => {
let parser: ReturnType<typeof createInterfaceParser>;
beforeEach(() => {
parser = createInterfaceParser();
});
describe('parseInterface', () => {
it('should parse interface properties', () => {
const source = `
interface User {
id: number;
name: string;
age?: number;
}
`;
const interfaces = parser.parse(source, 'test.ts');
expect(interfaces).toHaveLength(1);
expect(interfaces[0].members.length).toBe(3);
});
it('should parse interface with extends', () => {
const source = `
interface A {}
interface B extends A {}
`;
const interfaces = parser.parse(source, 'test.ts');
const b = interfaces.find(i => i.name === 'B');
expect(b?.extends).toContain('A');
});
it('should parse generic parameters', () => {
const source = `
interface Container<T> {
value: T;
}
`;
const interfaces = parser.parse(source, 'test.ts');
expect(interfaces[0].generics).toHaveLength(1);
expect(interfaces[0].generics[0].name).toBe('T');
});
it('should parse readonly properties', () => {
const source = `
interface A {
readonly id: number;
}
`;
const interfaces = parser.parse(source, 'test.ts');
const member = interfaces[0].members.find(m => m.name === 'id');
expect(member?.isReadonly).toBe(true);
});
});
});
describe('TypeAliasParser', () => {
let parser: ReturnType<typeof createTypeAliasParser>;
beforeEach(() => {
parser = createTypeAliasParser();
});
describe('parseTypeAlias', () => {
it('should parse simple type alias', () => {
const source = `
type ID = number;
`;
const typeAliases = parser.parse(source, 'test.ts');
expect(typeAliases).toHaveLength(1);
expect(typeAliases[0].name).toBe('ID');
});
it('should parse union type', () => {
const source = `
type Status = 'pending' | 'approved' | 'rejected';
`;
const typeAliases = parser.parse(source, 'test.ts');
expect(typeAliases[0].typeAnnotation).toContain('|');
});
it('should parse intersection type', () => {
const source = `
type Combined = A & B;
`;
const typeAliases = parser.parse(source, 'test.ts');
expect(typeAliases[0].typeAnnotation).toContain('&');
});
it('should extract dependencies from union types', () => {
const source = `
type A = {};
type B = {};
type C = A | B;
`;
const typeAliases = parser.parse(source, 'test.ts');
const c = typeAliases.find(t => t.name === 'C');
expect(c?.dependencies).toContain('A');
expect(c?.dependencies).toContain('B');
});
});
describe('getComplexityScore', () => {
it('should calculate complexity score', () => {
const source = `
type Simple = number;
type Complex = A | B | C | D | E;
`;
const typeAliases = parser.parse(source, 'test.ts');
const simple = typeAliases.find(t => t.name === 'Simple');
const complex = typeAliases.find(t => t.name === 'Complex');
const simpleScore = parser.getComplexityScore(simple!);
const complexScore = parser.getComplexityScore(complex!);
expect(complexScore).toBeGreaterThan(simpleScore);
});
});
});
describe('ImportParser', () => {
let parser: ReturnType<typeof createImportParser>;
beforeEach(() => {
parser = createImportParser();
});
describe('parse', () => {
it('should parse named imports', () => {
const source = `
import { A, B, C } from './module';
`;
const imports = parser.parse(source, 'test.ts');
expect(imports).toHaveLength(1);
expect(imports[0].namedImports).toHaveLength(3);
});
it('should parse default import', () => {
const source = `
import MyDefault from './module';
`;
const imports = parser.parse(source, 'test.ts');
expect(imports[0].defaultImport).toBe('MyDefault');
});
it('should parse namespace import', () => {
const source = `
import * as Namespace from './module';
`;
const imports = parser.parse(source, 'test.ts');
expect(imports[0].namespaceImport).toBe('Namespace');
});
it('should detect external modules', () => {
const source = `
import { something } from 'external-package';
`;
const imports = parser.parse(source, 'test.ts');
expect(imports[0].isExternal).toBe(true);
});
it('should detect relative imports', () => {
const source = `
import { something } from './local-module';
`;
const imports = parser.parse(source, 'test.ts');
expect(imports[0].isExternal).toBe(false);
});
});
});