UNPKG

what-is-my-tech-stack

Version:

Analyze project dependencies and generate a human-readable tech stack description

231 lines (195 loc) 8.05 kB
import { DependencyAnalyzer } from '../../../src/analyzers/dependencyAnalyzer.js'; import { FileReader } from '../../../src/utils/fileReader.js'; import { NodeAnalyzer } from '../../../src/analyzers/nodeAnalyzer.js'; import { PythonAnalyzer } from '../../../src/analyzers/pythonAnalyzer.js'; // Mock all dependencies jest.mock('../../../src/utils/fileReader.js'); jest.mock('../../../src/analyzers/nodeAnalyzer.js'); jest.mock('../../../src/analyzers/pythonAnalyzer.js'); jest.mock('../../../src/ai/openai.js'); describe('DependencyAnalyzer', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('analyze', () => { it('should analyze Node.js project', async () => { // Mock project type detection (FileReader.detectProjectType as jest.Mock).mockReturnValue('node'); // Mock Node.js analysis results const mockNodeDependencies = [ { name: 'react', version: '17.0.0', type: 'dependency' }, { name: 'jest', version: '27.0.0', type: 'devDependency' }, ]; const mockNodeCategories = { framework: ['react'], testing: ['jest'], }; (NodeAnalyzer.prototype.analyze as jest.Mock).mockReturnValue(mockNodeDependencies); (NodeAnalyzer.prototype.categorizeDependencies as jest.Mock).mockReturnValue( mockNodeCategories ); const analyzer = new DependencyAnalyzer('.'); const result = await analyzer.analyze(); expect(result).toEqual({ type: 'node', node: { dependencies: mockNodeDependencies, categories: mockNodeCategories, description: '• react\n• jest', }, }); }); it('should analyze Python project', async () => { // Mock project type detection (FileReader.detectProjectType as jest.Mock).mockReturnValue('python'); // Mock Python analysis results const mockPythonDependencies = [ { name: 'django', version: '3.2.0', constraint: '==' }, { name: 'pytest', version: '6.2.4', constraint: '==' }, ]; const mockPythonCategories = { web_framework: ['django'], testing: ['pytest'], }; (PythonAnalyzer.prototype.analyze as jest.Mock).mockReturnValue(mockPythonDependencies); (PythonAnalyzer.prototype.categorizeDependencies as jest.Mock).mockReturnValue( mockPythonCategories ); const analyzer = new DependencyAnalyzer('.'); const result = await analyzer.analyze(); expect(result).toEqual({ type: 'python', python: { dependencies: mockPythonDependencies, categories: mockPythonCategories, description: '• django\n• pytest', }, }); }); it('should analyze project with both Node.js and Python', async () => { // Mock project type detection (FileReader.detectProjectType as jest.Mock).mockReturnValue('both'); // Mock Node.js analysis results const mockNodeDependencies = [{ name: 'react', version: '17.0.0', type: 'dependency' }]; const mockNodeCategories = { framework: ['react'] }; // Mock Python analysis results const mockPythonDependencies = [{ name: 'django', version: '3.2.0', constraint: '==' }]; const mockPythonCategories = { web_framework: ['django'] }; (NodeAnalyzer.prototype.analyze as jest.Mock).mockReturnValue(mockNodeDependencies); (NodeAnalyzer.prototype.categorizeDependencies as jest.Mock).mockReturnValue( mockNodeCategories ); (PythonAnalyzer.prototype.analyze as jest.Mock).mockReturnValue(mockPythonDependencies); (PythonAnalyzer.prototype.categorizeDependencies as jest.Mock).mockReturnValue( mockPythonCategories ); const analyzer = new DependencyAnalyzer('.'); const result = await analyzer.analyze(); expect(result).toEqual({ type: 'both', node: { dependencies: mockNodeDependencies, categories: mockNodeCategories, description: '• react', }, python: { dependencies: mockPythonDependencies, categories: mockPythonCategories, description: '• django', }, }); }); it('should handle unknown project type', async () => { // Mock project type detection (FileReader.detectProjectType as jest.Mock).mockReturnValue('unknown'); const analyzer = new DependencyAnalyzer('.'); const result = await analyzer.analyze(); expect(result).toEqual({ type: 'unknown', }); }); it('should handle AI generation errors', async () => { // Mock project type detection (FileReader.detectProjectType as jest.Mock).mockReturnValue('node'); // Mock Node.js analysis results const mockNodeDependencies = [{ name: 'react', version: '17.0.0', type: 'dependency' }]; const mockNodeCategories = { framework: ['react'] }; (NodeAnalyzer.prototype.analyze as jest.Mock).mockReturnValue(mockNodeDependencies); (NodeAnalyzer.prototype.categorizeDependencies as jest.Mock).mockReturnValue( mockNodeCategories ); const analyzer = new DependencyAnalyzer('.'); const result = await analyzer.analyze(); // Should still return results with minimal description expect(result).toEqual({ type: 'node', node: { dependencies: mockNodeDependencies, categories: mockNodeCategories, description: '• react', }, }); }); }); describe('generateSummary', () => { it('should generate summary for Node.js project', () => { const techStack = { type: 'node' as const, node: { dependencies: [{ name: 'react', version: '17.0.0', type: 'dependency' as const }], categories: { framework: ['react'], }, description: 'AI-generated Node.js tech stack description', }, }; const analyzer = new DependencyAnalyzer('.'); const summary = analyzer.generateSummary(techStack); expect(summary).toContain('# Project Tech Stack Analysis'); expect(summary).toContain('## Node.js Dependencies'); expect(summary).toContain('### Overview'); expect(summary).toContain('AI-generated Node.js tech stack description'); expect(summary).toContain('### Frameworks'); expect(summary).toContain('react'); }); it('should generate summary for Python project', () => { const techStack = { type: 'python' as const, python: { dependencies: [{ name: 'django', version: '3.2.0', constraint: '==' }], categories: { web_framework: ['django'], }, description: 'AI-generated Python tech stack description', }, }; const analyzer = new DependencyAnalyzer('.'); const summary = analyzer.generateSummary(techStack); expect(summary).toContain('# Project Tech Stack Analysis'); expect(summary).toContain('## Python Dependencies'); expect(summary).toContain('### Overview'); expect(summary).toContain('AI-generated Python tech stack description'); expect(summary).toContain('### Web Frameworks'); expect(summary).toContain('django'); }); it('should handle missing AI descriptions', () => { const techStack = { type: 'node' as const, node: { dependencies: [{ name: 'react', version: '17.0.0', type: 'dependency' as const }], categories: { framework: ['react'], }, // No description provided }, }; const analyzer = new DependencyAnalyzer('.'); const summary = analyzer.generateSummary(techStack); expect(summary).toContain('# Project Tech Stack Analysis'); expect(summary).toContain('## Node.js Dependencies'); expect(summary).toContain('### Frameworks'); expect(summary).toContain('react'); expect(summary).not.toContain('### Overview'); }); }); });