claude-flow
Version:
Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)
275 lines (230 loc) • 11.3 kB
JavaScript
const { TestHarness } = require('../test-harness');
const assert = require('assert');
describe('Architect Mode Batch Integration Tests', () => {
let harness;
beforeEach(() => {
harness = new TestHarness();
harness.createMockProject('complex');
});
afterEach(() => {
harness.reset();
});
describe('Parallel Architecture Analysis', () => {
it('should analyze multiple components concurrently', async () => {
const components = [
'src/services/auth.service.ts',
'src/services/user.service.ts',
'src/controllers/auth.controller.ts',
'src/models/user.model.ts'
];
const analysisResults = await harness.executeBatch(components, async (component) => {
const content = await harness.mockReadFile(component);
return {
component,
type: component.includes('service') ? 'service' :
component.includes('controller') ? 'controller' : 'model',
imports: content.match(/import\s+{[^}]+}/g) || [],
exports: content.match(/export\s+(class|interface|const)/g) || [],
complexity: content.length
};
});
assert.strictEqual(analysisResults.successful.length, 4);
assert(analysisResults.successful.every(r => r.type));
assert(analysisResults.successful.every(r => r.complexity > 0));
});
it('should generate architecture diagrams in parallel', async () => {
const diagramTypes = ['component', 'sequence', 'deployment', 'data-flow'];
const diagramTasks = diagramTypes.map(type => async () => {
await harness.simulateDelay(50); // Simulate diagram generation
return {
type,
diagram: `@startuml\ntitle ${type} Diagram\n' ${type} specific content\n@enduml`,
metadata: {
generated: new Date().toISOString(),
components: Math.floor(Math.random() * 10) + 5
}
};
});
const results = await harness.executeBatch(diagramTasks, async (task) => await task());
assert.strictEqual(results.successful.length, 4);
results.successful.forEach(diagram => {
assert(diagram.diagram.includes('@startuml'));
assert(diagram.metadata.components >= 5);
});
});
it('should analyze dependencies across multiple files', async () => {
// Add more complex dependencies
harness.mockFS.set('src/services/auth.service.ts',
'import { UserService } from "./user.service";\nimport { Logger } from "../utils/logger";\nexport class AuthService { }');
harness.mockFS.set('src/services/user.service.ts',
'import { User } from "../models/user.model";\nimport { Logger } from "../utils/logger";\nexport class UserService { }');
const files = ['src/services/auth.service.ts', 'src/services/user.service.ts'];
const dependencyAnalysis = await harness.executeBatch(files, async (file) => {
const content = await harness.mockReadFile(file);
const imports = content.match(/from\s+"([^"]+)"/g) || [];
return {
file,
dependencies: imports.map(imp => imp.replace(/from\s+"(.+)"/, '$1')),
dependencyCount: imports.length
};
});
assert.strictEqual(dependencyAnalysis.successful.length, 2);
const authDeps = dependencyAnalysis.successful.find(r => r.file.includes('auth.service'));
assert.strictEqual(authDeps.dependencyCount, 2);
assert(authDeps.dependencies.includes('./user.service'));
});
});
describe('Concurrent Pattern Detection', () => {
it('should detect design patterns across multiple files', async () => {
// Add pattern examples
harness.mockFS.set('src/patterns/singleton.ts',
'export class Singleton { private static instance: Singleton; }');
harness.mockFS.set('src/patterns/factory.ts',
'export abstract class Factory { abstract create(): Product; }');
harness.mockFS.set('src/patterns/observer.ts',
'export interface Observer { update(subject: Subject): void; }');
const patternFiles = [
'src/patterns/singleton.ts',
'src/patterns/factory.ts',
'src/patterns/observer.ts'
];
const patternDetection = await harness.executeBatch(patternFiles, async (file) => {
const content = await harness.mockReadFile(file);
const patterns = [];
if (content.includes('static instance')) patterns.push('Singleton');
if (content.includes('abstract') && content.includes('create')) patterns.push('Factory');
if (content.includes('Observer') && content.includes('update')) patterns.push('Observer');
return { file, patterns, confidence: patterns.length > 0 ? 0.9 : 0 };
});
assert.strictEqual(patternDetection.successful.length, 3);
assert(patternDetection.successful.every(r => r.patterns.length > 0));
assert(patternDetection.successful.every(r => r.confidence > 0.8));
});
it('should analyze architectural layers in parallel', async () => {
const layers = ['presentation', 'business', 'data', 'infrastructure'];
const layerAnalysis = await harness.executeBatch(layers, async (layer) => {
// Simulate analyzing each layer
const files = Array.from(harness.mockFS.keys()).filter(f => {
if (layer === 'presentation') return f.includes('controller');
if (layer === 'business') return f.includes('service');
if (layer === 'data') return f.includes('model');
if (layer === 'infrastructure') return f.includes('config') || f.includes('utils');
return false;
});
return {
layer,
fileCount: files.length,
components: files.map(f => ({ path: f, type: layer })),
health: files.length > 0 ? 'healthy' : 'missing'
};
});
assert.strictEqual(layerAnalysis.successful.length, 4);
const healthyLayers = layerAnalysis.successful.filter(l => l.health === 'healthy');
assert(healthyLayers.length >= 3); // At least 3 layers should have files
});
});
describe('Batch Documentation Generation', () => {
it('should generate multiple architecture documents concurrently', async () => {
const documentTypes = [
{ type: 'overview', title: 'System Overview' },
{ type: 'components', title: 'Component Architecture' },
{ type: 'deployment', title: 'Deployment Architecture' },
{ type: 'security', title: 'Security Architecture' }
];
const docGeneration = await harness.executeBatch(documentTypes, async (doc) => {
const content = `# ${doc.title}\n\n## Overview\nThis document describes the ${doc.type} architecture.\n\n## Details\n...`;
const path = `docs/architecture/${doc.type}.md`;
await harness.mockWriteFile(path, content);
return { path, size: content.length, generated: true };
});
assert.strictEqual(docGeneration.successful.length, 4);
// Verify all documents were created
for (const doc of docGeneration.successful) {
const content = await harness.mockReadFile(doc.path);
assert(content.includes('# '));
assert(content.includes('architecture'));
}
});
it('should extract and analyze architectural decisions', async () => {
// Add ADR (Architecture Decision Records)
const adrs = [
{ id: '001', title: 'Use TypeScript', status: 'accepted' },
{ id: '002', title: 'Microservices Architecture', status: 'proposed' },
{ id: '003', title: 'PostgreSQL for persistence', status: 'accepted' },
{ id: '004', title: 'Redis for caching', status: 'deprecated' }
];
adrs.forEach(adr => {
harness.mockFS.set(`docs/adr/ADR-${adr.id}.md`,
`# ADR-${adr.id}: ${adr.title}\n\nStatus: ${adr.status}\n\n## Context\n...`);
});
const adrAnalysis = await harness.executeBatch(adrs, async (adr) => {
const content = await harness.mockReadFile(`docs/adr/ADR-${adr.id}.md`);
return {
...adr,
hasContext: content.includes('## Context'),
hasDecision: content.includes('## Decision'),
wordCount: content.split(/\s+/).length
};
});
assert.strictEqual(adrAnalysis.successful.length, 4);
const acceptedADRs = adrAnalysis.successful.filter(a => a.status === 'accepted');
assert.strictEqual(acceptedADRs.length, 2);
});
});
describe('Performance Profiling', () => {
it('should profile architecture analysis performance', async () => {
harness.createMockProject('large'); // Create 100+ files
const allFiles = Array.from(harness.mockFS.keys());
const batches = [10, 20, 50];
const results = {};
for (const batchSize of batches) {
const files = allFiles.slice(0, batchSize);
const { metrics } = await harness.measureResourceUsage(async () => {
return await harness.executeBatch(files, async (file) => {
const content = await harness.mockReadFile(file);
return { file, size: content.length, analyzed: true };
});
});
results[batchSize] = {
duration: metrics.duration,
throughput: batchSize / (metrics.duration / 1000)
};
}
// Throughput should remain relatively stable
const throughputs = Object.values(results).map(r => r.throughput);
const avgThroughput = throughputs.reduce((a, b) => a + b) / throughputs.length;
throughputs.forEach(tp => {
const deviation = Math.abs(tp - avgThroughput) / avgThroughput;
assert(deviation < 0.3, `Throughput deviation too high: ${(deviation * 100).toFixed(1)}%`);
});
});
it('should handle complex architectural queries efficiently', async () => {
const queries = [
{ type: 'find-circular-deps', complexity: 'high' },
{ type: 'analyze-coupling', complexity: 'medium' },
{ type: 'check-layer-violations', complexity: 'high' },
{ type: 'identify-god-classes', complexity: 'medium' },
{ type: 'detect-anti-patterns', complexity: 'high' }
];
const startTime = Date.now();
const queryResults = await harness.executeBatch(queries, async (query) => {
// Simulate complex analysis
const delay = query.complexity === 'high' ? 100 : 50;
await harness.simulateDelay(delay);
return {
query: query.type,
issues: Math.floor(Math.random() * 5),
suggestions: Math.floor(Math.random() * 3) + 1,
executionTime: delay
};
});
const totalTime = Date.now() - startTime;
assert.strictEqual(queryResults.successful.length, 5);
// With parallel execution, should complete faster than sequential
const sequentialTime = queries.reduce((sum, q) =>
sum + (q.complexity === 'high' ? 100 : 50), 0);
assert(totalTime < sequentialTime * 0.7,
`Parallel execution should be faster: ${totalTime}ms vs ${sequentialTime}ms sequential`);
});
});
});