claude-flow
Version:
Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)
467 lines (395 loc) • 16.8 kB
JavaScript
const { TestHarness } = require('../test-harness');
const assert = require('assert');
describe('Code Mode Batch Integration Tests', () => {
let harness;
beforeEach(() => {
harness = new TestHarness();
harness.createMockProject('complex');
});
afterEach(() => {
harness.reset();
});
describe('Parallel Code Generation', () => {
it('should generate multiple code files concurrently', async () => {
const codeTemplates = [
{ name: 'UserRepository', type: 'repository', entity: 'User' },
{ name: 'ProductRepository', type: 'repository', entity: 'Product' },
{ name: 'OrderRepository', type: 'repository', entity: 'Order' },
{ name: 'AuthMiddleware', type: 'middleware', purpose: 'authentication' },
{ name: 'ValidationMiddleware', type: 'middleware', purpose: 'validation' }
];
const codeGeneration = await harness.executeBatch(codeTemplates, async (template) => {
let code = '';
if (template.type === 'repository') {
code = `import { Repository } from './base-repository';
import { ${template.entity} } from '../models/${template.entity.toLowerCase()}.model';
export class ${template.name} extends Repository<${template.entity}> {
constructor() {
super('${template.entity.toLowerCase()}s');
}
async findByEmail(email: string): Promise<${template.entity} | null> {
return this.findOne({ email });
}
async findActive(): Promise<${template.entity}[]> {
return this.find({ isActive: true });
}
}`;
} else if (template.type === 'middleware') {
code = `import { Request, Response, NextFunction } from 'express';
export const ${template.name} = async (
req: Request,
res: Response,
next: NextFunction
): Promise<void> => {
try {
// ${template.purpose} logic here
console.log('${template.name} processing request');
next();
} catch (error) {
res.status(401).json({ error: '${template.purpose} failed' });
}
};`;
}
const path = `src/${template.type}s/${template.name}.ts`;
await harness.mockWriteFile(path, code);
return {
path,
linesOfCode: code.split('\n').length,
generated: true,
template: template.name
};
});
assert.strictEqual(codeGeneration.successful.length, 5);
assert(codeGeneration.successful.every(r => r.linesOfCode > 10));
// Verify code was generated correctly
const userRepo = await harness.mockReadFile('src/repositorys/UserRepository.ts');
assert(userRepo.includes('extends Repository<User>'));
assert(userRepo.includes('findByEmail'));
});
it('should refactor multiple files in parallel', async () => {
// Setup files to refactor
const filesToRefactor = [
{ path: 'src/old-service1.ts', newPath: 'src/services/service1.ts' },
{ path: 'src/old-service2.ts', newPath: 'src/services/service2.ts' },
{ path: 'src/old-controller.ts', newPath: 'src/controllers/main.controller.ts' }
];
// Add old files
filesToRefactor.forEach(f => {
harness.mockFS.set(f.path, `// Old code in ${f.path}\nexport class OldClass {}`);
});
const refactoring = await harness.executeBatch(filesToRefactor, async (file) => {
const oldContent = await harness.mockReadFile(file.path);
// Simulate refactoring
const newContent = oldContent
.replace(/Old/g, 'New')
.replace(/\/\/ Old code/, '// Refactored code')
+ '\n\n// Additional improvements';
await harness.mockWriteFile(file.newPath, newContent);
harness.mockFS.delete(file.path); // Remove old file
return {
oldPath: file.path,
newPath: file.newPath,
changes: 3,
improved: true
};
});
assert.strictEqual(refactoring.successful.length, 3);
// Verify refactoring
const refactoredContent = await harness.mockReadFile('src/services/service1.ts');
assert(refactoredContent.includes('Refactored code'));
assert(refactoredContent.includes('NewClass'));
assert(!harness.mockFS.has('src/old-service1.ts')); // Old file removed
});
it('should apply code transformations across multiple files', async () => {
const transformations = [
{ pattern: 'console.log', replacement: 'logger.info', type: 'logging' },
{ pattern: 'var ', replacement: 'const ', type: 'es6' },
{ pattern: 'function\\s+(\\w+)\\s*\\(', replacement: 'const $1 = (', type: 'arrow-functions' }
];
// Add files with old patterns
const testFiles = [
'src/utils/helper1.js',
'src/utils/helper2.js',
'src/utils/helper3.js'
];
testFiles.forEach(file => {
harness.mockFS.set(file, `var x = 5;
console.log('Hello');
function doSomething() {
console.log('Doing something');
var result = x * 2;
return result;
}`);
});
const transformResults = await harness.executeBatch(testFiles, async (file) => {
let content = await harness.mockReadFile(file);
const changes = [];
for (const transform of transformations) {
const regex = new RegExp(transform.pattern, 'g');
const matches = content.match(regex);
if (matches) {
content = content.replace(regex, transform.replacement);
changes.push({
type: transform.type,
count: matches.length
});
}
}
await harness.mockWriteFile(file, content);
return {
file,
transformations: changes,
totalChanges: changes.reduce((sum, c) => sum + c.count, 0)
};
});
assert.strictEqual(transformResults.successful.length, 3);
// Verify transformations
const transformed = await harness.mockReadFile(testFiles[0]);
assert(transformed.includes('const x = 5'));
assert(transformed.includes('logger.info'));
assert(transformed.includes('const doSomething = ('));
});
});
describe('Concurrent Code Analysis', () => {
it('should analyze code quality metrics in parallel', async () => {
const filesToAnalyze = Array.from(harness.mockFS.keys())
.filter(f => f.endsWith('.ts') || f.endsWith('.js'));
const analysisResults = await harness.executeBatch(filesToAnalyze, async (file) => {
const content = await harness.mockReadFile(file);
const lines = content.split('\n');
return {
file,
metrics: {
loc: lines.length,
complexity: Math.floor(Math.random() * 10) + 1, // Simulated
maintainability: Math.random() * 30 + 70, // 70-100
issues: {
high: Math.floor(Math.random() * 2),
medium: Math.floor(Math.random() * 5),
low: Math.floor(Math.random() * 10)
}
}
};
});
assert(analysisResults.successful.length > 5);
// Aggregate metrics
const totalLOC = analysisResults.successful.reduce((sum, r) => sum + r.metrics.loc, 0);
const avgComplexity = analysisResults.successful.reduce((sum, r) =>
sum + r.metrics.complexity, 0) / analysisResults.successful.length;
assert(totalLOC > 100);
assert(avgComplexity > 1 && avgComplexity < 10);
});
it('should detect code smells across multiple files', async () => {
// Add files with various code smells
harness.mockFS.set('src/smelly1.ts', `export class GodClass {
private prop1: string;
private prop2: number;
private prop3: boolean;
private prop4: any[];
private prop5: object;
method1() {}
method2() {}
method3() {}
method4() {}
method5() {}
method6() {}
method7() {}
method8() {}
}`);
harness.mockFS.set('src/smelly2.ts', `export function veryLongMethodNameThatDoesTooManyThings() {
// 100+ lines of code
${Array(100).fill('// code line').join('\n')}
}`);
harness.mockFS.set('src/smelly3.ts', `export class DataClass {
public field1: string;
public field2: number;
public field3: boolean;
// No methods, just data
}`);
const codeSmellDetection = await harness.executeBatch(
['src/smelly1.ts', 'src/smelly2.ts', 'src/smelly3.ts'],
async (file) => {
const content = await harness.mockReadFile(file);
const smells = [];
// Detect various code smells
const methodCount = (content.match(/method\d+/g) || []).length;
const propertyCount = (content.match(/private \w+:/g) || []).length;
const lineCount = content.split('\n').length;
if (methodCount > 5) smells.push({ type: 'god-class', severity: 'high' });
if (lineCount > 50) smells.push({ type: 'long-method', severity: 'medium' });
if (propertyCount > 0 && methodCount === 0) smells.push({ type: 'data-class', severity: 'low' });
return {
file,
smells,
refactoringPriority: smells.some(s => s.severity === 'high') ? 'high' : 'normal'
};
}
);
assert.strictEqual(codeSmellDetection.successful.length, 3);
const highPriorityFiles = codeSmellDetection.successful.filter(r =>
r.refactoringPriority === 'high');
assert(highPriorityFiles.length >= 1);
});
});
describe('Batch Code Optimization', () => {
it('should optimize multiple files for performance', async () => {
// Add files with optimization opportunities
const filesToOptimize = {
'src/loops.js': `for (var i = 0; i < arr.length; i++) {
process(arr[i]);
}`,
'src/strings.js': `let result = '';
for (let i = 0; i < 1000; i++) {
result = result + 'x';
}`,
'src/arrays.js': `const filtered = [];
for (let item of items) {
if (item.active) {
filtered.push(item);
}
}`
};
Object.entries(filesToOptimize).forEach(([path, content]) => {
harness.mockFS.set(path, content);
});
const optimizations = await harness.executeBatch(
Object.keys(filesToOptimize),
async (file) => {
let content = await harness.mockReadFile(file);
const improvements = [];
// Apply optimizations
if (content.includes('for (var i = 0; i < arr.length; i++)')) {
content = content.replace(
'for (var i = 0; i < arr.length; i++) {\n process(arr[i]);\n }',
'arr.forEach(process);'
);
improvements.push('replaced for loop with forEach');
}
if (content.includes('result = result +')) {
content = content.replace(
/let result = '';\s*for.*?{\s*result = result \+ 'x';\s*}/s,
"const result = 'x'.repeat(1000);"
);
improvements.push('optimized string concatenation');
}
if (content.includes('filtered.push')) {
content = content.replace(
/const filtered = \[\];\s*for.*?{\s*if.*?{\s*filtered\.push.*?}\s*}/s,
'const filtered = items.filter(item => item.active);'
);
improvements.push('replaced manual filter with Array.filter');
}
await harness.mockWriteFile(file, content);
return {
file,
improvements,
optimized: improvements.length > 0
};
}
);
assert.strictEqual(optimizations.successful.length, 3);
assert(optimizations.successful.every(r => r.optimized));
// Verify optimizations
const optimizedLoops = await harness.mockReadFile('src/loops.js');
assert(optimizedLoops.includes('forEach'));
});
it('should apply security fixes across multiple files', async () => {
// Add files with security issues
const vulnerableFiles = {
'src/sql.js': `db.query("SELECT * FROM users WHERE id = " + userId);`,
'src/xss.js': `element.innerHTML = userInput;`,
'src/eval.js': `eval(userCode);`,
'src/regex.js': `new RegExp(userPattern);`
};
Object.entries(vulnerableFiles).forEach(([path, content]) => {
harness.mockFS.set(path, content);
});
const securityFixes = await harness.executeBatch(
Object.keys(vulnerableFiles),
async (file) => {
let content = await harness.mockReadFile(file);
const vulnerabilities = [];
const fixes = [];
// Detect and fix vulnerabilities
if (content.includes('+ userId')) {
vulnerabilities.push({ type: 'SQL Injection', severity: 'critical' });
content = content.replace(
'"SELECT * FROM users WHERE id = " + userId',
'"SELECT * FROM users WHERE id = ?", [userId]'
);
fixes.push('parameterized SQL query');
}
if (content.includes('innerHTML = userInput')) {
vulnerabilities.push({ type: 'XSS', severity: 'high' });
content = content.replace(
'element.innerHTML = userInput',
'element.textContent = userInput'
);
fixes.push('replaced innerHTML with textContent');
}
if (content.includes('eval(')) {
vulnerabilities.push({ type: 'Code Injection', severity: 'critical' });
content = content.replace(
'eval(userCode)',
'// eval removed for security - use Function constructor or safer alternative'
);
fixes.push('removed eval usage');
}
if (content.includes('new RegExp(userPattern)')) {
vulnerabilities.push({ type: 'ReDoS', severity: 'medium' });
content = content.replace(
'new RegExp(userPattern)',
'new RegExp(escapeRegExp(userPattern))'
);
fixes.push('escaped regex pattern');
}
await harness.mockWriteFile(file, content);
return {
file,
vulnerabilities,
fixes,
secure: fixes.length === vulnerabilities.length
};
}
);
assert.strictEqual(securityFixes.successful.length, 4);
assert(securityFixes.successful.every(r => r.secure));
const criticalVulns = securityFixes.successful
.flatMap(r => r.vulnerabilities)
.filter(v => v.severity === 'critical');
assert(criticalVulns.length >= 2);
});
});
describe('Performance Benchmarks', () => {
it('should demonstrate speedup with parallel code generation', async () => {
const componentCount = 20;
const components = Array.from({ length: componentCount }, (_, i) => ({
name: `Component${i}`,
type: 'react',
props: ['id', 'name', 'onClick']
}));
// Measure sequential generation (simulated)
harness.concurrencyLimit = 1;
const sequentialStart = Date.now();
await harness.executeBatch(components, async (comp) => {
await harness.simulateDelay(30); // Simulate generation time
const code = `export const ${comp.name} = (props) => { return <div>{props.name}</div>; };`;
return { component: comp.name, generated: true, size: code.length };
});
const sequentialTime = Date.now() - sequentialStart;
// Measure parallel generation
harness.concurrencyLimit = 5;
const parallelStart = Date.now();
await harness.executeBatch(components, async (comp) => {
await harness.simulateDelay(30);
const code = `export const ${comp.name} = (props) => { return <div>{props.name}</div>; };`;
return { component: comp.name, generated: true, size: code.length };
});
const parallelTime = Date.now() - parallelStart;
const speedup = sequentialTime / parallelTime;
assert(speedup > 2.5, `Expected speedup > 2.5x, got ${speedup.toFixed(2)}x`);
const report = harness.getPerformanceReport();
console.log('Code generation performance:', report);
});
});
});