Files
proffesor-for-testing__agen…/tests/mcp/handlers/AnalysisTools.test.ts
Profa 5380421f1e docs: update implementation progress analysis - MCP server 100% complete
- Corrected MCP server implementation status from 0% to 100%
- Added details of 52 MCP tools across 8 categories
- Updated overall progress from 46% to 54% (7/13 areas complete)
- Added MCP server architecture details (357 lines server, 1836 lines tools, 60+ handlers)
- Updated integration metrics: MCP Tools 52/50 (104% - exceeded target)
- Removed MCP server from future work (already production-ready)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 17:50:41 +00:00

520 lines
16 KiB
TypeScript

/**
* Comprehensive Test Suite for Analysis MCP Tools
* Tests all 5 analysis handlers with edge cases and integration scenarios
*/
import { coverageAnalyzeSublinear } from '../../../src/mcp/handlers/analysis/coverageAnalyzeSublinear';
import { coverageGapsDetect } from '../../../src/mcp/handlers/analysis/coverageGapsDetect';
import { performanceBenchmarkRun } from '../../../src/mcp/handlers/analysis/performanceBenchmarkRun';
import { performanceMonitorRealtime } from '../../../src/mcp/handlers/analysis/performanceMonitorRealtime';
import { securityScanComprehensive } from '../../../src/mcp/handlers/analysis/securityScanComprehensive';
describe('Analysis MCP Tools - Coverage Analyze Sublinear', () => {
it('should analyze coverage with Johnson-Lindenstrauss for large codebases', async () => {
const sourceFiles = Array.from({ length: 150 }, (_, i) => `src/file${i}.ts`);
const result = await coverageAnalyzeSublinear({
sourceFiles,
coverageThreshold: 0.8,
useJohnsonLindenstrauss: true
});
expect(result.overallCoverage).toBeGreaterThan(0);
expect(result.overallCoverage).toBeLessThanOrEqual(1);
expect(result.sublinearMetrics.algorithmUsed).toBe('johnson-lindenstrauss');
expect(result.sublinearMetrics.originalDimension).toBe(150);
expect(result.sublinearMetrics.reducedDimension).toBeLessThan(150);
expect(result.sublinearMetrics.distortion).toBeGreaterThan(0);
expect(result.fileCoverage).toBeDefined();
expect(Object.keys(result.fileCoverage).length).toBe(150);
});
it('should use spectral sparsification for medium codebases', async () => {
const sourceFiles = Array.from({ length: 75 }, (_, i) => `src/module${i}.ts`);
const result = await coverageAnalyzeSublinear({
sourceFiles,
useJohnsonLindenstrauss: true
});
expect(result.sublinearMetrics.algorithmUsed).toBe('spectral-sparsification');
expect(result.sublinearMetrics.originalDimension).toBe(75);
});
it('should use adaptive sampling for small codebases', async () => {
const sourceFiles = ['src/main.ts', 'src/utils.ts'];
const result = await coverageAnalyzeSublinear({
sourceFiles
});
expect(result.sublinearMetrics.algorithmUsed).toBe('adaptive-sampling');
});
it('should detect uncovered regions when requested', async () => {
const sourceFiles = ['src/critical.ts'];
const result = await coverageAnalyzeSublinear({
sourceFiles,
includeUncoveredLines: true
});
expect(result.uncoveredRegions).toBeDefined();
if (result.uncoveredRegions && result.uncoveredRegions.length > 0) {
expect(result.uncoveredRegions[0]).toHaveProperty('file');
expect(result.uncoveredRegions[0]).toHaveProperty('lines');
expect(result.uncoveredRegions[0]).toHaveProperty('complexity');
expect(result.uncoveredRegions[0]).toHaveProperty('priority');
}
});
it('should generate recommendations based on coverage', async () => {
const sourceFiles = ['src/low-coverage.ts'];
const result = await coverageAnalyzeSublinear({
sourceFiles,
coverageThreshold: 0.9
});
expect(result.recommendations).toBeDefined();
expect(result.recommendations.length).toBeGreaterThan(0);
});
it('should respect custom target dimension for JL', async () => {
const sourceFiles = Array.from({ length: 200 }, (_, i) => `src/file${i}.ts`);
const result = await coverageAnalyzeSublinear({
sourceFiles,
targetDimension: 10
});
expect(result.sublinearMetrics.reducedDimension).toBe(10);
});
});
describe('Analysis MCP Tools - Coverage Gaps Detect', () => {
it('should detect all gap types', async () => {
const sourceFiles = ['src/app.ts', 'src/service.ts'];
const result = await coverageGapsDetect({
sourceFiles,
aiAnalysis: true,
riskAssessment: true
});
expect(result.gaps).toBeDefined();
expect(result.gaps.length).toBeGreaterThan(0);
const gapTypes = new Set(result.gaps.map(g => g.type));
expect(gapTypes.size).toBeGreaterThan(0);
});
it('should calculate risk scores for gaps', async () => {
const sourceFiles = ['src/critical.ts'];
const result = await coverageGapsDetect({
sourceFiles,
riskAssessment: true
});
result.gaps.forEach(gap => {
expect(gap.riskScore).toBeGreaterThanOrEqual(0);
expect(gap.riskScore).toBeLessThanOrEqual(100);
});
});
it('should provide AI insights when enabled', async () => {
const sourceFiles = ['src/main.ts'];
const result = await coverageGapsDetect({
sourceFiles,
aiAnalysis: true
});
expect(result.aiInsights).toBeDefined();
expect(result.aiInsights?.patterns).toBeDefined();
expect(result.aiInsights?.recommendations).toBeDefined();
expect(result.aiInsights?.riskAreas).toBeDefined();
});
it('should prioritize gaps correctly', async () => {
const sourceFiles = ['src/app.ts'];
const result = await coverageGapsDetect({
sourceFiles,
riskAssessment: true
});
expect(result.prioritizedActions).toBeDefined();
// Verify prioritized actions are sorted by priority
for (let i = 1; i < result.prioritizedActions.length; i++) {
expect(result.prioritizedActions[i - 1].priority)
.toBeGreaterThanOrEqual(result.prioritizedActions[i].priority);
}
});
it('should generate summary statistics', async () => {
const sourceFiles = ['src/service.ts'];
const result = await coverageGapsDetect({
sourceFiles
});
expect(result.summary).toBeDefined();
expect(result.summary.totalGaps).toBe(result.gaps.length);
expect(result.summary.estimatedEffort).toBeDefined();
expect(result.summary.estimatedEffort.hours).toBeGreaterThan(0);
expect(result.summary.estimatedEffort.tests).toBeGreaterThan(0);
});
it('should suggest appropriate tests for each gap', async () => {
const sourceFiles = ['src/module.ts'];
const result = await coverageGapsDetect({
sourceFiles
});
result.gaps.forEach(gap => {
expect(gap.suggestedTests).toBeDefined();
expect(gap.suggestedTests.length).toBeGreaterThan(0);
});
});
});
describe('Analysis MCP Tools - Performance Benchmark Run', () => {
it('should run benchmarks with specified iterations', async () => {
const targets = ['api/endpoint1', 'api/endpoint2'];
const result = await performanceBenchmarkRun({
targets,
iterations: 50,
warmupRuns: 5
});
expect(result.benchmarks).toBeDefined();
expect(result.benchmarks.length).toBe(2);
expect(result.summary.totalTests).toBe(2);
});
it('should calculate statistical metrics', async () => {
const targets = ['service/method'];
const result = await performanceBenchmarkRun({
targets,
iterations: 100
});
const benchmark = result.benchmarks[0];
if (benchmark.metrics.latency) {
expect(benchmark.metrics.latency.mean).toBeDefined();
expect(benchmark.metrics.latency.median).toBeDefined();
expect(benchmark.metrics.latency.stdDev).toBeDefined();
expect(benchmark.metrics.latency.p50).toBeDefined();
expect(benchmark.metrics.latency.p95).toBeDefined();
expect(benchmark.metrics.latency.p99).toBeDefined();
}
});
it('should collect specified metrics only', async () => {
const targets = ['endpoint'];
const result = await performanceBenchmarkRun({
targets,
metricsToCollect: ['latency', 'cpu']
});
const benchmark = result.benchmarks[0];
expect(benchmark.metrics.latency).toBeDefined();
expect(benchmark.metrics.cpu).toBeDefined();
expect(benchmark.metrics.network).toBeUndefined();
});
it('should determine pass/fail status', async () => {
const targets = ['endpoint1', 'endpoint2'];
const result = await performanceBenchmarkRun({
targets,
iterations: 50
});
result.benchmarks.forEach(benchmark => {
expect(['pass', 'fail', 'warning']).toContain(benchmark.status);
});
});
it('should provide baseline comparison', async () => {
const targets = ['api/v2'];
const result = await performanceBenchmarkRun({
targets,
baselineComparison: true
});
expect(result.comparison).toBeDefined();
expect(result.comparison?.improvement).toBeGreaterThanOrEqual(0);
expect(result.comparison?.regression).toBeGreaterThanOrEqual(0);
expect(result.comparison?.neutral).toBeGreaterThanOrEqual(0);
});
it('should generate performance recommendations', async () => {
const targets = ['slow-endpoint'];
const result = await performanceBenchmarkRun({
targets,
iterations: 30
});
expect(result.recommendations).toBeDefined();
expect(result.recommendations.length).toBeGreaterThan(0);
});
});
describe('Analysis MCP Tools - Performance Monitor Realtime', () => {
it('should monitor performance in real-time', async () => {
const targets = ['service1'];
const result = await performanceMonitorRealtime({
targets,
interval: 100,
duration: 500
});
expect(result.status).toBe('stopped');
expect(result.metrics.length).toBeGreaterThan(0);
});
it('should collect all metric types', async () => {
const targets = ['endpoint'];
const result = await performanceMonitorRealtime({
targets,
interval: 100,
duration: 300
});
const metric = result.metrics[0];
expect(metric.timestamp).toBeDefined();
expect(metric.latency).toBeDefined();
expect(metric.throughput).toBeDefined();
expect(metric.cpu).toBeDefined();
expect(metric.memory).toBeDefined();
expect(metric.errorRate).toBeDefined();
expect(metric.activeConnections).toBeDefined();
});
it('should trigger alerts on threshold violations', async () => {
const targets = ['monitored-service'];
const result = await performanceMonitorRealtime({
targets,
interval: 100,
duration: 500,
thresholds: {
latency: 100,
cpu: 70,
memory: 500
},
alerting: true
});
// Alerts may or may not be triggered based on random metrics
expect(result.alerts).toBeDefined();
expect(Array.isArray(result.alerts)).toBe(true);
});
it('should analyze performance trends', async () => {
const targets = ['service'];
const result = await performanceMonitorRealtime({
targets,
interval: 50,
duration: 600
});
expect(result.trends).toBeDefined();
if (result.trends && result.trends.length > 0) {
result.trends.forEach(trend => {
expect(['improving', 'stable', 'degrading']).toContain(trend.trend);
expect(trend.changeRate).toBeGreaterThanOrEqual(0);
});
}
});
it('should generate monitoring summary', async () => {
const targets = ['api'];
const result = await performanceMonitorRealtime({
targets,
interval: 100,
duration: 400
});
expect(result.summary).toBeDefined();
expect(result.summary.startTime).toBeGreaterThan(0);
expect(result.summary.duration).toBeGreaterThan(0);
expect(result.summary.dataPoints).toBe(result.metrics.length);
expect(result.summary.alertsTriggered).toBe(result.alerts.length);
});
});
describe('Analysis MCP Tools - Security Scan Comprehensive', () => {
it('should run all scan types', async () => {
const targets = ['src/app.ts', 'src/api.ts'];
const result = await securityScanComprehensive({
targets,
scanTypes: ['sast', 'dast', 'sca', 'secrets', 'dependencies']
});
expect(result.vulnerabilities).toBeDefined();
expect(result.vulnerabilities.length).toBeGreaterThan(0);
});
it('should detect SAST vulnerabilities', async () => {
const targets = ['src/insecure.ts'];
const result = await securityScanComprehensive({
targets,
scanTypes: ['sast']
});
const sastVulns = result.vulnerabilities.filter(v => v.type === 'sast');
expect(sastVulns.length).toBeGreaterThanOrEqual(0);
});
it('should detect DAST vulnerabilities', async () => {
const targets = ['api/endpoint'];
const result = await securityScanComprehensive({
targets,
scanTypes: ['dast']
});
const dastVulns = result.vulnerabilities.filter(v => v.type === 'dast');
expect(dastVulns.length).toBeGreaterThanOrEqual(0);
});
it('should calculate risk scores', async () => {
const targets = ['src/app.ts'];
const result = await securityScanComprehensive({
targets
});
expect(result.riskScore).toBeDefined();
expect(result.riskScore.overall).toBeGreaterThanOrEqual(0);
expect(result.riskScore.overall).toBeLessThanOrEqual(100);
expect(result.riskScore.breakdown).toBeDefined();
});
it('should provide fix suggestions when enabled', async () => {
const targets = ['src/vulnerable.ts'];
const result = await securityScanComprehensive({
targets,
fixSuggestions: true
});
const vulnsWithFixes = result.vulnerabilities.filter(v => v.fixSuggestion);
expect(vulnsWithFixes.length).toBeGreaterThan(0);
});
it('should run compliance checks', async () => {
const targets = ['src/app.ts'];
const result = await securityScanComprehensive({
targets,
includeCompliance: true
});
expect(result.compliance).toBeDefined();
expect(result.compliance!.length).toBeGreaterThan(0);
result.compliance!.forEach(check => {
expect(check.standard).toBeDefined();
expect(['compliant', 'non-compliant', 'partial']).toContain(check.status);
});
});
it('should categorize vulnerabilities by severity', async () => {
const targets = ['src/app.ts'];
const result = await securityScanComprehensive({
targets
});
expect(result.summary.critical).toBeGreaterThanOrEqual(0);
expect(result.summary.high).toBeGreaterThanOrEqual(0);
expect(result.summary.medium).toBeGreaterThanOrEqual(0);
expect(result.summary.low).toBeGreaterThanOrEqual(0);
const total = result.summary.critical + result.summary.high +
result.summary.medium + result.summary.low;
expect(total).toBe(result.summary.totalVulnerabilities);
});
it('should generate security recommendations', async () => {
const targets = ['src/app.ts'];
const result = await securityScanComprehensive({
targets
});
expect(result.recommendations).toBeDefined();
expect(result.recommendations.length).toBeGreaterThan(0);
});
it('should include CVE and CWE information', async () => {
const targets = ['src/service.ts'];
const result = await securityScanComprehensive({
targets
});
const vulnsWithCwe = result.vulnerabilities.filter(v => v.cwe);
expect(vulnsWithCwe.length).toBeGreaterThan(0);
});
});
describe('Analysis MCP Tools - Integration Tests', () => {
it('should work together: coverage analysis -> gap detection', async () => {
const sourceFiles = ['src/main.ts', 'src/utils.ts'];
// First analyze coverage
const coverageResult = await coverageAnalyzeSublinear({
sourceFiles,
includeUncoveredLines: true
});
// Then detect gaps (without passing coverageResult since it's not compatible format)
const gapsResult = await coverageGapsDetect({
sourceFiles
});
expect(coverageResult.overallCoverage).toBeDefined();
expect(gapsResult.gaps).toBeDefined();
});
it('should handle empty input gracefully', async () => {
const result = await coverageAnalyzeSublinear({
sourceFiles: []
});
expect(result.fileCoverage).toBeDefined();
expect(Object.keys(result.fileCoverage).length).toBe(0);
});
it('should handle concurrent benchmark and monitoring', async () => {
const targets = ['service1'];
const [benchmarkResult, monitorResult] = await Promise.all([
performanceBenchmarkRun({ targets, iterations: 10 }),
performanceMonitorRealtime({ targets, interval: 100, duration: 300 })
]);
expect(benchmarkResult.benchmarks).toBeDefined();
expect(monitorResult.metrics).toBeDefined();
});
});