mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
2253d05618
Remove the nested v3/ subdirectory by moving all active source code, tests, configs, and assets directly to the project root. Archive v2/ (dead code, 847MB) to v2-archive.tar.gz. Key changes: - Move v3/src/ → src/, v3/tests/ → tests/, v3/packages/ → packages/ - Move v3/tsconfig.json, v3/vitest.config.ts to root - Merge v3/package.json into root package.json (ESM, scripts, deps, exports) - Merge v3/scripts/ into scripts/, v3/implementation/ into docs/implementation/ - Update all CI workflows to remove "cd v3 &&" and v3/ path prefixes - Fix all init installer path resolution (3-level-up → 2-level-up) - Fix hooks to use "node ./dist/cli/bundle.js" instead of bare "aqe" - Update settings.json ADR/DDD directories to docs/implementation/ - Fix helper scripts (statusline, adr-compliance, ddd-tracker, guidance-hooks) - Update 58 agent definitions: aqe/v3/ → aqe/ memory namespaces - Update 15 guidance shards: v3/src/ → src/ path references - Fix sync interfaces: remove v3/ and v2/ path references - Fix test path calculations (process.cwd() + '..' no longer needed) - Fix flaky perf test threshold (500ms → 1000ms for CI environments) - Fix complexity-analyzer test to match ADR-051 keyword-based eligibility Build passes, 17,901 tests pass, CLI and MCP bundles verified. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
415 lines
13 KiB
TypeScript
415 lines
13 KiB
TypeScript
/**
|
|
* Agentic QE v3 - CLI Commands Tests
|
|
* Tests for various aqe-v3 CLI commands
|
|
*/
|
|
|
|
import { describe, it, expect, vi } from 'vitest';
|
|
import { ALL_DOMAINS, type DomainName } from '../../../src/shared/types';
|
|
|
|
describe('CLI Commands', () => {
|
|
describe('Status Command', () => {
|
|
it('should format health status with colors', () => {
|
|
const getStatusColor = (status: string): string => {
|
|
switch (status) {
|
|
case 'healthy':
|
|
case 'completed':
|
|
return 'green';
|
|
case 'degraded':
|
|
case 'running':
|
|
return 'yellow';
|
|
case 'unhealthy':
|
|
case 'failed':
|
|
return 'red';
|
|
default:
|
|
return 'gray';
|
|
}
|
|
};
|
|
|
|
expect(getStatusColor('healthy')).toBe('green');
|
|
expect(getStatusColor('completed')).toBe('green');
|
|
expect(getStatusColor('degraded')).toBe('yellow');
|
|
expect(getStatusColor('running')).toBe('yellow');
|
|
expect(getStatusColor('unhealthy')).toBe('red');
|
|
expect(getStatusColor('failed')).toBe('red');
|
|
expect(getStatusColor('unknown')).toBe('gray');
|
|
});
|
|
|
|
it('should format duration correctly', () => {
|
|
const formatDuration = (ms: number): string => {
|
|
if (ms < 1000) return `${ms}ms`;
|
|
if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
|
|
if (ms < 3600000) return `${(ms / 60000).toFixed(1)}m`;
|
|
return `${(ms / 3600000).toFixed(1)}h`;
|
|
};
|
|
|
|
expect(formatDuration(500)).toBe('500ms');
|
|
expect(formatDuration(1500)).toBe('1.5s');
|
|
expect(formatDuration(90000)).toBe('1.5m');
|
|
expect(formatDuration(5400000)).toBe('1.5h');
|
|
});
|
|
|
|
it('should format uptime correctly', () => {
|
|
const formatUptime = (ms: number): string => {
|
|
const hours = Math.floor(ms / 3600000);
|
|
const minutes = Math.floor((ms % 3600000) / 60000);
|
|
const seconds = Math.floor((ms % 60000) / 1000);
|
|
return `${hours}h ${minutes}m ${seconds}s`;
|
|
};
|
|
|
|
expect(formatUptime(0)).toBe('0h 0m 0s');
|
|
expect(formatUptime(3661000)).toBe('1h 1m 1s');
|
|
expect(formatUptime(86400000)).toBe('24h 0m 0s');
|
|
});
|
|
|
|
it('should support verbose flag', () => {
|
|
const options = { verbose: true };
|
|
expect(options.verbose).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('Health Command', () => {
|
|
it('should accept domain filter', () => {
|
|
const options = { domain: 'test-generation' };
|
|
expect(ALL_DOMAINS).toContain(options.domain);
|
|
});
|
|
|
|
it('should validate domain name', () => {
|
|
const isValidDomain = (domain: string): boolean => {
|
|
return ALL_DOMAINS.includes(domain as DomainName);
|
|
};
|
|
|
|
expect(isValidDomain('test-generation')).toBe(true);
|
|
expect(isValidDomain('coverage-analysis')).toBe(true);
|
|
expect(isValidDomain('invalid-domain')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('Test Command', () => {
|
|
it('should accept generate action', () => {
|
|
const action = 'generate';
|
|
expect(['generate', 'execute']).toContain(action);
|
|
});
|
|
|
|
it('should accept execute action', () => {
|
|
const action = 'execute';
|
|
expect(['generate', 'execute']).toContain(action);
|
|
});
|
|
|
|
it('should accept framework option', () => {
|
|
const options = { framework: 'vitest' };
|
|
expect(['jest', 'vitest', 'mocha']).toContain(options.framework);
|
|
});
|
|
|
|
it('should accept test type option', () => {
|
|
const options = { type: 'unit' };
|
|
expect(['unit', 'integration', 'e2e']).toContain(options.type);
|
|
});
|
|
|
|
it('should accept target path', () => {
|
|
const target = 'src/services/user.ts';
|
|
expect(typeof target).toBe('string');
|
|
expect(target.length).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
|
|
describe('Coverage Command', () => {
|
|
it('should accept target path', () => {
|
|
const target = './src';
|
|
expect(typeof target).toBe('string');
|
|
});
|
|
|
|
it('should default target to current directory', () => {
|
|
const target = undefined;
|
|
const effectiveTarget = target || '.';
|
|
expect(effectiveTarget).toBe('.');
|
|
});
|
|
|
|
it('should support risk flag', () => {
|
|
const options = { risk: true };
|
|
expect(options.risk).toBe(true);
|
|
});
|
|
|
|
it('should support gaps flag', () => {
|
|
const options = { gaps: true };
|
|
expect(options.gaps).toBe(true);
|
|
});
|
|
|
|
it('should format coverage percentage with color', () => {
|
|
const getColorForPercent = (percent: number): string => {
|
|
if (percent >= 80) return 'green';
|
|
if (percent >= 50) return 'yellow';
|
|
return 'red';
|
|
};
|
|
|
|
expect(getColorForPercent(90)).toBe('green');
|
|
expect(getColorForPercent(80)).toBe('green');
|
|
expect(getColorForPercent(65)).toBe('yellow');
|
|
expect(getColorForPercent(50)).toBe('yellow');
|
|
expect(getColorForPercent(30)).toBe('red');
|
|
});
|
|
});
|
|
|
|
describe('Security Command', () => {
|
|
it('should support sast flag', () => {
|
|
const options = { sast: true };
|
|
expect(options.sast).toBe(true);
|
|
});
|
|
|
|
it('should support dast flag', () => {
|
|
const options = { dast: true };
|
|
expect(options.dast).toBe(true);
|
|
});
|
|
|
|
it('should support compliance frameworks', () => {
|
|
const options = { compliance: 'gdpr,hipaa,soc2' };
|
|
const frameworks = options.compliance.split(',');
|
|
|
|
expect(frameworks).toContain('gdpr');
|
|
expect(frameworks).toContain('hipaa');
|
|
expect(frameworks).toContain('soc2');
|
|
});
|
|
|
|
it('should accept target path', () => {
|
|
const options = { target: './src' };
|
|
expect(options.target).toBe('./src');
|
|
});
|
|
|
|
it('should default target to current directory', () => {
|
|
const options = { target: undefined };
|
|
const effectiveTarget = options.target || '.';
|
|
expect(effectiveTarget).toBe('.');
|
|
});
|
|
});
|
|
|
|
describe('Code Command', () => {
|
|
it('should accept index action', () => {
|
|
const action = 'index';
|
|
expect(['index', 'search', 'impact', 'deps']).toContain(action);
|
|
});
|
|
|
|
it('should accept search action', () => {
|
|
const action = 'search';
|
|
expect(['index', 'search', 'impact', 'deps']).toContain(action);
|
|
});
|
|
|
|
it('should accept impact action', () => {
|
|
const action = 'impact';
|
|
expect(['index', 'search', 'impact', 'deps']).toContain(action);
|
|
});
|
|
|
|
it('should accept deps action', () => {
|
|
const action = 'deps';
|
|
expect(['index', 'search', 'impact', 'deps']).toContain(action);
|
|
});
|
|
|
|
it('should support depth option', () => {
|
|
const options = { depth: '3' };
|
|
expect(parseInt(options.depth, 10)).toBe(3);
|
|
});
|
|
|
|
it('should support include-tests flag', () => {
|
|
const options = { includeTests: true };
|
|
expect(options.includeTests).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('Quality Command', () => {
|
|
it('should support gate flag', () => {
|
|
const options = { gate: true };
|
|
expect(options.gate).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('Task Command', () => {
|
|
describe('Submit Subcommand', () => {
|
|
it('should accept task type', () => {
|
|
const taskTypes = [
|
|
'generate-tests',
|
|
'execute-tests',
|
|
'analyze-coverage',
|
|
'assess-quality',
|
|
'predict-defects',
|
|
'validate-requirements',
|
|
'index-code',
|
|
'scan-security',
|
|
'validate-contracts',
|
|
'test-accessibility',
|
|
'run-chaos',
|
|
'optimize-learning',
|
|
];
|
|
|
|
for (const type of taskTypes) {
|
|
expect(typeof type).toBe('string');
|
|
}
|
|
expect(taskTypes.length).toBe(12);
|
|
});
|
|
|
|
it('should accept priority option', () => {
|
|
const priorities = ['p0', 'p1', 'p2', 'p3'];
|
|
for (const priority of priorities) {
|
|
expect(priorities).toContain(priority);
|
|
}
|
|
});
|
|
|
|
it('should accept domain option', () => {
|
|
const options = { domain: 'test-generation' };
|
|
expect(ALL_DOMAINS).toContain(options.domain);
|
|
});
|
|
|
|
it('should accept timeout option', () => {
|
|
const options = { timeout: '300000' };
|
|
const timeout = parseInt(options.timeout, 10);
|
|
expect(timeout).toBe(300000);
|
|
expect(timeout).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should accept payload option as JSON', () => {
|
|
const options = { payload: '{"source":"test.ts"}' };
|
|
const payload = JSON.parse(options.payload);
|
|
expect(payload.source).toBe('test.ts');
|
|
});
|
|
});
|
|
|
|
describe('List Subcommand', () => {
|
|
it('should accept status filter', () => {
|
|
const options = { status: 'running' };
|
|
expect(['pending', 'running', 'completed', 'failed']).toContain(options.status);
|
|
});
|
|
|
|
it('should accept priority filter', () => {
|
|
const options = { priority: 'p1' };
|
|
expect(['p0', 'p1', 'p2', 'p3']).toContain(options.priority);
|
|
});
|
|
|
|
it('should accept domain filter', () => {
|
|
const options = { domain: 'test-generation' };
|
|
expect(ALL_DOMAINS).toContain(options.domain);
|
|
});
|
|
});
|
|
|
|
describe('Status Subcommand', () => {
|
|
it('should accept task ID', () => {
|
|
const taskId = 'task-12345';
|
|
expect(typeof taskId).toBe('string');
|
|
expect(taskId.length).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
|
|
describe('Cancel Subcommand', () => {
|
|
it('should accept task ID', () => {
|
|
const taskId = 'task-12345';
|
|
expect(typeof taskId).toBe('string');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Agent Command', () => {
|
|
describe('List Subcommand', () => {
|
|
it('should accept domain filter', () => {
|
|
const options = { domain: 'test-generation' };
|
|
expect(ALL_DOMAINS).toContain(options.domain);
|
|
});
|
|
|
|
it('should accept status filter', () => {
|
|
const options = { status: 'active' };
|
|
expect(typeof options.status).toBe('string');
|
|
});
|
|
});
|
|
|
|
describe('Spawn Subcommand', () => {
|
|
it('should accept domain argument', () => {
|
|
const domain = 'test-generation';
|
|
expect(ALL_DOMAINS).toContain(domain);
|
|
});
|
|
|
|
it('should accept type option', () => {
|
|
const options = { type: 'worker' };
|
|
expect(['worker', 'specialist', 'coordinator']).toContain(options.type);
|
|
});
|
|
|
|
it('should accept capabilities option', () => {
|
|
const options = { capabilities: 'unit-test,integration-test' };
|
|
const capabilities = options.capabilities.split(',');
|
|
expect(capabilities.length).toBe(2);
|
|
expect(capabilities).toContain('unit-test');
|
|
expect(capabilities).toContain('integration-test');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Domain Command', () => {
|
|
describe('List Subcommand', () => {
|
|
it('should list all 14 domains', () => {
|
|
expect(ALL_DOMAINS.length).toBe(14);
|
|
});
|
|
});
|
|
|
|
describe('Health Subcommand', () => {
|
|
it('should accept domain argument', () => {
|
|
const domain = 'test-generation';
|
|
expect(ALL_DOMAINS).toContain(domain);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Protocol Command', () => {
|
|
describe('Run Subcommand', () => {
|
|
it('should accept protocol ID', () => {
|
|
const protocolId = 'comprehensive-testing';
|
|
expect(typeof protocolId).toBe('string');
|
|
});
|
|
|
|
it('should accept params option as JSON', () => {
|
|
const options = { params: '{"threshold":80}' };
|
|
const params = JSON.parse(options.params);
|
|
expect(params.threshold).toBe(80);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('CLI Error Handling', () => {
|
|
it('should handle invalid JSON in payload', () => {
|
|
const parsePayload = (payload: string) => {
|
|
try {
|
|
return JSON.parse(payload);
|
|
} catch {
|
|
return {};
|
|
}
|
|
};
|
|
|
|
expect(parsePayload('invalid')).toEqual({});
|
|
expect(parsePayload('{"valid":true}')).toEqual({ valid: true });
|
|
});
|
|
|
|
it('should handle invalid domain names', () => {
|
|
const isValidDomain = (domain: string): boolean => {
|
|
return ALL_DOMAINS.includes(domain as DomainName);
|
|
};
|
|
|
|
expect(isValidDomain('invalid')).toBe(false);
|
|
expect(isValidDomain('')).toBe(false);
|
|
expect(isValidDomain('test-generation')).toBe(true);
|
|
});
|
|
|
|
it('should handle invalid priority values', () => {
|
|
const isValidPriority = (priority: string): boolean => {
|
|
return ['p0', 'p1', 'p2', 'p3'].includes(priority);
|
|
};
|
|
|
|
expect(isValidPriority('p1')).toBe(true);
|
|
expect(isValidPriority('p5')).toBe(false);
|
|
expect(isValidPriority('high')).toBe(false);
|
|
});
|
|
|
|
it('should handle missing required arguments', () => {
|
|
const validateArgs = (args: { taskId?: string }): boolean => {
|
|
return !!args.taskId && args.taskId.length > 0;
|
|
};
|
|
|
|
expect(validateArgs({})).toBe(false);
|
|
expect(validateArgs({ taskId: '' })).toBe(false);
|
|
expect(validateArgs({ taskId: 'task-123' })).toBe(true);
|
|
});
|
|
});
|