import { describe, it, expect, vi, type Mock } from 'vitest';; import { DartAdapter } from '../dart'; vi.mock('fs', () => ({ readFileSync: vi.fn(), existsSync: vi.fn(() => true), })); import { readFileSync } from 'fs'; describe('DartAdapter', () => { it('should implement the Adapter interface', () => { (readFileSync as Mock).mockReturnValue('void testFn() {}\nclass TestClass {}'); const adapter = new DartAdapter('test.dart'); expect(adapter).toHaveProperty('detectLanguage'); expect(adapter).toHaveProperty('parseAST'); expect(adapter).toHaveProperty('extractFunctions'); expect(adapter).toHaveProperty('extractClasses'); expect(adapter).toHaveProperty('countLines'); }); it('should detect language as dart for .dart files', () => { (readFileSync as Mock).mockReturnValue('void testFn() {}'); const adapter = new DartAdapter('test.dart'); const detected = adapter.detectLanguage(); expect(detected).toBe('dart'); }); it('should parse Dart file AST correctly', () => { (readFileSync as Mock).mockReturnValue('void testFn() {}\nclass TestClass {}'); const adapter = new DartAdapter('test.dart'); const ast = adapter.parseAST(); expect(ast).toHaveProperty('content'); expect(ast).toHaveProperty('language'); expect(ast).toHaveProperty('filePath'); expect((ast as { language: unknown }).language).toBe('dart'); }); it('should extract functions from Dart AST', () => { (readFileSync as Mock).mockReturnValue('void testFn() {}\nclass TestClass {}'); const adapter = new DartAdapter('test.dart'); const functions = adapter.extractFunctions(); expect(Array.isArray(functions)).toBe(true); expect(functions.some(fn => (fn as {name: string}).name === 'testFn')).toBe(true); }); it('should extract classes from Dart AST', () => { (readFileSync as Mock).mockReturnValue('void testFn() {}\nclass TestClass {}'); const adapter = new DartAdapter('test.dart'); const classes = adapter.extractClasses(); expect(Array.isArray(classes)).toBe(true); expect(classes.some(cls => (cls as {name: string}).name === 'TestClass')).toBe(true); }); it('should count Dart file physical lines', () => { (readFileSync as Mock).mockReturnValue('void testFn() {}\nvoid testFn2() {}'); const adapter = new DartAdapter('test.dart'); const lineCount = adapter.countLines(); expect(lineCount).toBe(2); }); it('should fall back to super.detectLanguage for non-dart extensions', () => { (readFileSync as Mock).mockReturnValue('content'); const adapter = new DartAdapter('test.py'); expect(adapter.detectLanguage()).toBe('python'); }); it('should handle async functions in Dart', () => { (readFileSync as Mock).mockReturnValue('Future fetchData() async {}\nasync void fireAndForget() {}'); const adapter = new DartAdapter('test.dart'); const functions = adapter.extractFunctions(); const asyncFns = functions.filter(fn => (fn as {type: string}).type === 'async_function'); expect(asyncFns.length).toBeGreaterThan(0); }); it('should handle abstract class declarations in Dart', () => { (readFileSync as Mock).mockReturnValue('abstract class Repository {\n void save();\n}\n'); const adapter = new DartAdapter('test.dart'); const classes = adapter.extractClasses(); const abstractClasses = classes.filter(cls => (cls as {type: string}).type === 'abstract_class'); expect(abstractClasses.length).toBeGreaterThan(0); }); });