220 lines
6.2 KiB
TypeScript
220 lines
6.2 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import * as os from 'os';
|
|
import { analyzeDependencies } from '../src/analyzers/dependencyAnalyzer';
|
|
|
|
describe('DependencyAnalyzer', () => {
|
|
let tempDir: string;
|
|
|
|
beforeEach(() => {
|
|
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ai-context-dep-test-'));
|
|
});
|
|
|
|
afterEach(() => {
|
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe('Node.js dependencies', () => {
|
|
it('should parse package.json dependencies', async () => {
|
|
const packageJson = {
|
|
name: 'test-project',
|
|
version: '1.0.0',
|
|
dependencies: {
|
|
express: '^4.18.2',
|
|
lodash: '^4.17.21'
|
|
},
|
|
devDependencies: {
|
|
jest: '^29.7.0',
|
|
typescript: '^5.3.3'
|
|
}
|
|
};
|
|
fs.writeFileSync(
|
|
path.join(tempDir, 'package.json'),
|
|
JSON.stringify(packageJson)
|
|
);
|
|
|
|
const result = await analyzeDependencies(tempDir, 'node');
|
|
|
|
expect(result.dependencies).toHaveLength(4);
|
|
expect(result.dependencies.find(d => d.name === 'express')).toEqual({
|
|
name: 'express',
|
|
version: '^4.18.2',
|
|
type: 'prod'
|
|
});
|
|
expect(result.dependencies.find(d => d.name === 'jest')).toEqual({
|
|
name: 'jest',
|
|
version: '^29.7.0',
|
|
type: 'dev'
|
|
});
|
|
expect(result.packageManager).toBe('npm');
|
|
});
|
|
|
|
it('should detect yarn package manager', async () => {
|
|
const packageJson = {
|
|
name: 'test-project',
|
|
dependencies: { express: '^4.18.0' }
|
|
};
|
|
fs.writeFileSync(
|
|
path.join(tempDir, 'package.json'),
|
|
JSON.stringify(packageJson)
|
|
);
|
|
fs.writeFileSync(path.join(tempDir, 'yarn.lock'), '# yarn lock file');
|
|
|
|
const result = await analyzeDependencies(tempDir, 'node');
|
|
|
|
expect(result.packageManager).toBe('yarn');
|
|
expect(result.lockFile).toBe('yarn.lock');
|
|
});
|
|
|
|
it('should detect pnpm package manager', async () => {
|
|
const packageJson = {
|
|
name: 'test-project',
|
|
dependencies: { express: '^4.18.0' }
|
|
};
|
|
fs.writeFileSync(
|
|
path.join(tempDir, 'package.json'),
|
|
JSON.stringify(packageJson)
|
|
);
|
|
fs.writeFileSync(path.join(tempDir, 'pnpm-lock.yaml'), '# pnpm lock file');
|
|
|
|
const result = await analyzeDependencies(tempDir, 'node');
|
|
|
|
expect(result.packageManager).toBe('pnpm');
|
|
});
|
|
});
|
|
|
|
describe('Python dependencies', () => {
|
|
it('should parse requirements.txt', async () => {
|
|
fs.writeFileSync(
|
|
path.join(tempDir, 'requirements.txt'),
|
|
`flask>=2.0.0
|
|
requests==2.28.0
|
|
numpy~=1.24.0
|
|
pandas # pandas for data analysis
|
|
django<4.0
|
|
black; python_version >= "3.6"
|
|
`
|
|
);
|
|
|
|
const result = await analyzeDependencies(tempDir, 'python');
|
|
|
|
expect(result.dependencies.length).toBeGreaterThan(0);
|
|
const flaskDep = result.dependencies.find(d => d.name === 'flask');
|
|
expect(flaskDep).toBeDefined();
|
|
expect(flaskDep?.type).toBe('prod');
|
|
expect(result.packageManager).toBe('pip');
|
|
});
|
|
|
|
it('should detect poetry package manager', async () => {
|
|
fs.writeFileSync(
|
|
path.join(tempDir, 'pyproject.toml'),
|
|
`[tool.poetry]
|
|
name = "test-project"
|
|
version = "0.1.0"
|
|
|
|
[tool.poetry.dependencies]
|
|
python = "^3.8"
|
|
fastapi = "^0.100.0"
|
|
`
|
|
);
|
|
fs.writeFileSync(path.join(tempDir, 'poetry.lock'), '# poetry lock');
|
|
|
|
const result = await analyzeDependencies(tempDir, 'python');
|
|
|
|
expect(result.packageManager).toBe('poetry');
|
|
});
|
|
});
|
|
|
|
describe('Go dependencies', () => {
|
|
it('should parse go.mod', async () => {
|
|
const goMod = `module github.com/test/project
|
|
|
|
go 1.20
|
|
|
|
require (
|
|
github.com/gin-gonic/gin v1.9.1
|
|
github.com/gofiber/fiber v2.52.0
|
|
)
|
|
`;
|
|
fs.writeFileSync(path.join(tempDir, 'go.mod'), goMod);
|
|
|
|
const result = await analyzeDependencies(tempDir, 'go');
|
|
|
|
expect(result.dependencies.length).toBe(2);
|
|
expect(result.packageManager).toBe('go');
|
|
const ginDep = result.dependencies.find(d => d.name.includes('gin-gonic/gin'));
|
|
expect(ginDep).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Rust dependencies', () => {
|
|
it('should parse Cargo.toml', async () => {
|
|
const cargoToml = `[package]
|
|
name = "test"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
serde = "1.0"
|
|
tokio = "1.0"
|
|
|
|
[dev.dependencies]
|
|
tempfile = "3.0"
|
|
`;
|
|
fs.writeFileSync(path.join(tempDir, 'Cargo.toml'), cargoToml);
|
|
|
|
const result = await analyzeDependencies(tempDir, 'rust');
|
|
|
|
expect(result.dependencies.length).toBe(3);
|
|
expect(result.packageManager).toBe('cargo');
|
|
const serdeDep = result.dependencies.find(d => d.name === 'serde');
|
|
expect(serdeDep).toBeDefined();
|
|
expect(serdeDep?.type).toBe('prod');
|
|
const tempfileDep = result.dependencies.find(d => d.name === 'tempfile');
|
|
expect(tempfileDep?.type).toBe('dev');
|
|
});
|
|
});
|
|
|
|
describe('Java dependencies', () => {
|
|
it('should parse pom.xml', async () => {
|
|
const pomXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<modelVersion>4.0.0</modelVersion>
|
|
<groupId>com.test</groupId>
|
|
<artifactId>test</artifactId>
|
|
<version>1.0.0</version>
|
|
|
|
<dependencies>
|
|
<dependency>
|
|
<groupId>org.springframework.boot</groupId>
|
|
<artifactId>spring-boot-starter</artifactId>
|
|
<version>3.1.0</version>
|
|
</dependency>
|
|
<dependency>
|
|
<groupId>com.fasterxml.jackson.core</groupId>
|
|
<artifactId>jackson-databind</artifactId>
|
|
<version>2.15.0</version>
|
|
</dependency>
|
|
</dependencies>
|
|
</project>`;
|
|
fs.writeFileSync(path.join(tempDir, 'pom.xml'), pomXml);
|
|
|
|
const result = await analyzeDependencies(tempDir, 'java');
|
|
|
|
expect(result.dependencies.length).toBe(2);
|
|
expect(result.packageManager).toBe('maven');
|
|
const springDep = result.dependencies.find(d => d.name.includes('spring-boot-starter'));
|
|
expect(springDep).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Empty project', () => {
|
|
it('should return empty dependencies for unknown project type', async () => {
|
|
const result = await analyzeDependencies(tempDir, 'unknown');
|
|
|
|
expect(result.dependencies).toHaveLength(0);
|
|
expect(result.packageManager).toBeNull();
|
|
});
|
|
});
|
|
});
|