@iservu-inc/adf-cli
Version:
CLI tool for AgentDevFramework - AI-assisted development framework with multi-provider AI support
222 lines (170 loc) • 6.74 kB
JavaScript
const fs = require('fs-extra');
const path = require('path');
const { analyzeProject, getProjectSummary, PROJECT_TYPES } = require('../lib/analyzers/project-analyzer');
describe('Project Analyzer', () => {
const tempDir = path.join(__dirname, 'temp-test-project');
beforeEach(async () => {
await fs.ensureDir(tempDir);
});
afterEach(async () => {
await fs.remove(tempDir);
});
describe('analyzeProject', () => {
test('should detect React web app from package.json', async () => {
// Create package.json with React
const packageJson = {
name: 'test-app',
version: '1.0.0',
description: 'A React web application',
dependencies: {
react: '^18.0.0',
'react-dom': '^18.0.0'
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
const context = await analyzeProject(tempDir);
expect(context.type).toBe(PROJECT_TYPES.WEB_APP);
expect(context.frameworks).toContain('React');
expect(context.languages).toContain('JavaScript/TypeScript');
expect(context.confidence).toBeGreaterThan(50);
});
test('should detect CLI tool from package.json bin field', async () => {
const packageJson = {
name: 'test-cli',
version: '1.0.0',
description: 'A command-line tool',
bin: {
'test-cli': 'bin/cli.js'
},
dependencies: {
commander: '^9.0.0'
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
const context = await analyzeProject(tempDir);
expect(context.type).toBe(PROJECT_TYPES.CLI_TOOL);
expect(context.confidence).toBeGreaterThan(50);
});
test('should detect npm library from package.json main field', async () => {
const packageJson = {
name: 'test-library',
version: '1.0.0',
description: 'A utility library',
main: 'index.js',
private: false
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
const context = await analyzeProject(tempDir);
expect(context.type).toBe(PROJECT_TYPES.LIBRARY);
expect(context.confidence).toBeGreaterThan(30);
});
test('should detect API server from dependencies', async () => {
const packageJson = {
name: 'test-api',
version: '1.0.0',
description: 'RESTful API server',
dependencies: {
express: '^4.18.0',
cors: '^2.8.5'
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
const context = await analyzeProject(tempDir);
expect(context.type).toBe(PROJECT_TYPES.API_SERVER);
expect(context.frameworks).toContain('Express');
});
test('should detect fullstack app with React and Express', async () => {
const packageJson = {
name: 'test-fullstack',
version: '1.0.0',
dependencies: {
react: '^18.0.0',
express: '^4.18.0'
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
const context = await analyzeProject(tempDir);
expect(context.type).toBe(PROJECT_TYPES.FULLSTACK);
expect(context.frameworks).toContain('React');
expect(context.frameworks).toContain('Express');
});
test('should extract description from README', async () => {
const readmeContent = `# Test Project
This is a test project for demonstrating the analyzer. It has a clear description.
## Features
- Feature 1
- Feature 2
`;
await fs.writeFile(path.join(tempDir, 'README.md'), readmeContent);
const context = await analyzeProject(tempDir);
expect(context.description).toBeTruthy();
expect(context.description).toContain('test project');
});
test('should detect test framework presence', async () => {
const packageJson = {
name: 'test-project',
devDependencies: {
jest: '^29.0.0'
}
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
const context = await analyzeProject(tempDir);
expect(context.hasTests).toBe(true);
});
test('should detect Docker presence', async () => {
await fs.writeFile(path.join(tempDir, 'Dockerfile'), 'FROM node:18');
const context = await analyzeProject(tempDir);
expect(context.hasDocker).toBe(true);
});
test('should handle project with no package.json gracefully', async () => {
const context = await analyzeProject(tempDir);
expect(context.type).toBe(PROJECT_TYPES.UNKNOWN);
expect(context.confidence).toBeLessThan(50);
});
});
describe('getProjectSummary', () => {
test('should return readable summary for web app', () => {
const context = {
type: PROJECT_TYPES.WEB_APP,
frameworks: ['React', 'Next.js'],
languages: ['JavaScript/TypeScript'],
confidence: 90
};
const summary = getProjectSummary(context);
expect(summary).toContain('Web Application');
expect(summary).toContain('React');
expect(summary).toContain('Next.js');
});
test('should return readable summary for CLI tool', () => {
const context = {
type: PROJECT_TYPES.CLI_TOOL,
frameworks: [],
languages: ['JavaScript/TypeScript'],
confidence: 85
};
const summary = getProjectSummary(context);
expect(summary).toContain('CLI Tool');
});
});
describe('Confidence scoring', () => {
test('should have high confidence with complete information', async () => {
const packageJson = {
name: 'complete-project',
version: '1.0.0',
description: 'A complete project with all metadata',
bin: { cli: 'bin/cli.js' },
dependencies: { commander: '^9.0.0' },
devDependencies: { jest: '^29.0.0' }
};
await fs.writeJson(path.join(tempDir, 'package.json'), packageJson);
await fs.writeFile(path.join(tempDir, 'README.md'), '# Project\n\nDescription here');
await fs.writeFile(path.join(tempDir, 'Dockerfile'), 'FROM node:18');
const context = await analyzeProject(tempDir);
expect(context.confidence).toBeGreaterThanOrEqual(75);
});
test('should have low confidence with minimal information', async () => {
const context = await analyzeProject(tempDir);
expect(context.confidence).toBeLessThan(50);
});
});
});