UNPKG

@ghostspeak/cli

Version:

Command-line interface for GhostSpeak AI Agent Commerce Protocol - Production Ready Beta

419 lines (366 loc) • 10.6 kB
#!/usr/bin/env bun /** * Test All Commands Script * * Automated script to test every GhostSpeak CLI command * and generate a comprehensive test report */ import { spawn } from 'child_process' import { join, dirname } from 'path' import { fileURLToPath } from 'url' import { writeFileSync, existsSync, mkdirSync } from 'fs' const __filename = fileURLToPath(import.meta.url) const __dirname = dirname(__filename) // ANSI color codes const colors = { green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', reset: '\x1b[0m', bold: '\x1b[1m' } // Test command definitions interface TestCommand { name: string command: string[] description: string expectedOutput?: string[] expectError?: boolean timeout?: number } const testCommands: TestCommand[] = [ // Basic commands { name: 'Version Check', command: ['--version'], description: 'Display CLI version', expectedOutput: ['2.'] }, { name: 'Help', command: ['--help'], description: 'Display help information', expectedOutput: ['command-line interface', 'agent', 'marketplace'] }, // Agent commands - using --help flag for consistent behavior { name: 'Agent Help', command: ['agent', '--help'], description: 'Display agent command help', expectedOutput: ['manage ai agents', 'register', 'list'] }, { name: 'Agent Status Help', command: ['agent', 'status', '--help'], description: 'Display agent status help', expectedOutput: ['check status'] }, // Marketplace commands - using --help flag { name: 'Marketplace Help', command: ['marketplace', '--help'], description: 'Display marketplace help', expectedOutput: ['marketplace'] }, // Escrow commands - using --help flag { name: 'Escrow Help', command: ['escrow', '--help'], description: 'Display escrow help', expectedOutput: ['escrow'] }, // Channel commands - using --help flag { name: 'Channel Help', command: ['channel', '--help'], description: 'Display channel help', expectedOutput: ['channel'] }, // Auction commands { name: 'Auction Help', command: ['auction', '--help'], description: 'Display auction help', expectedOutput: ['auction'] }, // Dispute commands { name: 'Dispute Help', command: ['dispute', '--help'], description: 'Display dispute help', expectedOutput: ['dispute'] }, // Governance commands { name: 'Governance Help', command: ['governance', '--help'], description: 'Display governance help', expectedOutput: ['governance'] }, // Wallet commands - using --help flag { name: 'Wallet Help', command: ['wallet', '--help'], description: 'Display wallet help', expectedOutput: ['wallet'] }, { name: 'Wallet Info', command: ['wallet', 'info'], description: 'Display wallet information', timeout: 5000 }, // Config commands - using --help flag { name: 'Config Help', command: ['config', '--help'], description: 'Display config help', expectedOutput: ['config'] }, { name: 'Config Show', command: ['config', 'show'], description: 'Show current configuration', timeout: 5000 }, // Faucet commands - using --help flag { name: 'Faucet Help', command: ['faucet', '--help'], description: 'Display faucet help', expectedOutput: ['faucet', 'sol'] }, // SDK commands { name: 'SDK Help', command: ['sdk', '--help'], description: 'Display SDK help', expectedOutput: ['sdk'] }, // Help system { name: 'Help Topics', command: ['help'], description: 'List help topics', expectedOutput: ['help'] }, { name: 'Help Search', command: ['help', '-s', 'agent'], description: 'Search help for "agent"', expectedOutput: ['agent'] }, // Aliases { name: 'Show Aliases', command: ['aliases'], description: 'Display command aliases', expectedOutput: ['shortcuts'] }, // Transaction history { name: 'Transaction History', command: ['tx'], description: 'Show transaction history', expectedOutput: ['transaction'] }, // Onboarding { name: 'Onboarding Help', command: ['onboard', '--help'], description: 'Display onboarding help', expectedOutput: ['onboarding'] }, // Error cases { name: 'Unknown Command', command: ['unknown-command'], description: 'Test unknown command handling', expectError: true }, { name: 'Invalid Option', command: ['agent', '--invalid-option'], description: 'Test invalid option handling', expectError: true } ] // Run a single CLI command async function runCommand(args: string[], timeout = 10000): Promise<{ stdout: string stderr: string exitCode: number | null }> { return new Promise((resolve) => { const cliPath = join(__dirname, '../dist/index.js') const proc = spawn('node', [cliPath, ...args], { env: { ...process.env, NODE_ENV: 'test', GHOSTSPEAK_CONFIG_DIR: join(process.cwd(), '.ghostspeak-test') }, timeout }) let stdout = '' let stderr = '' proc.stdout.on('data', (data) => { stdout += data.toString() }) proc.stderr.on('data', (data) => { stderr += data.toString() }) proc.on('close', (code) => { resolve({ stdout, stderr, exitCode: code }) }) proc.on('error', () => { resolve({ stdout, stderr, exitCode: -1 }) }) }) } // Test result interface interface TestResult { name: string command: string status: 'pass' | 'fail' duration: number output?: string error?: string details?: string } // Main test runner async function testAllCommands() { console.log(`${colors.bold}${colors.cyan}šŸš€ GhostSpeak CLI Command Test Runner${colors.reset}\n`) console.log(`Testing ${testCommands.length} commands...\n`) const results: TestResult[] = [] let passCount = 0 let failCount = 0 // Run each test for (let i = 0; i < testCommands.length; i++) { const test = testCommands[i] const commandStr = `gs ${test.command.join(' ')}` process.stdout.write(`[${i + 1}/${testCommands.length}] ${test.name}... `) const startTime = Date.now() try { const result = await runCommand(test.command, test.timeout) const duration = Date.now() - startTime let status: 'pass' | 'fail' = 'pass' let details = '' // Check exit code if (test.expectError) { if (result.exitCode === 0) { status = 'fail' details = 'Expected error but command succeeded' } } else { if (result.exitCode !== 0) { status = 'fail' details = `Exit code: ${result.exitCode}` } } // Check expected output if (status === 'pass' && test.expectedOutput) { const output = result.stdout.toLowerCase() for (const expected of test.expectedOutput) { if (!output.includes(expected.toLowerCase())) { status = 'fail' details = `Missing expected output: "${expected}"` break } } } // Record result results.push({ name: test.name, command: commandStr, status, duration, output: result.stdout.slice(0, 200), error: result.stderr, details }) if (status === 'pass') { console.log(`${colors.green}āœ“${colors.reset} (${duration}ms)`) passCount++ } else { console.log(`${colors.red}āœ—${colors.reset} (${duration}ms)`) failCount++ } } catch (error) { const duration = Date.now() - startTime console.log(`${colors.red}āœ—${colors.reset} (${duration}ms)`) results.push({ name: test.name, command: commandStr, status: 'fail', duration, error: error instanceof Error ? error.message : 'Unknown error' }) failCount++ } } // Generate report console.log('\n' + '━'.repeat(60) + '\n') console.log(`${colors.bold}šŸ“Š TEST SUMMARY${colors.reset}\n`) const totalDuration = results.reduce((sum, r) => sum + r.duration, 0) console.log(`Total Tests: ${colors.bold}${testCommands.length}${colors.reset}`) console.log(`Passed: ${colors.green}${passCount}${colors.reset}`) console.log(`Failed: ${colors.red}${failCount}${colors.reset}`) console.log(`Total Duration: ${colors.blue}${totalDuration}ms${colors.reset}`) console.log(`Average Duration: ${colors.blue}${Math.round(totalDuration / testCommands.length)}ms${colors.reset}`) // Show failed tests if (failCount > 0) { console.log(`\n${colors.bold}${colors.red}āŒ FAILED TESTS:${colors.reset}\n`) results.filter(r => r.status === 'fail').forEach(result => { console.log(`${colors.red}āœ—${colors.reset} ${result.name}`) console.log(` Command: ${colors.cyan}${result.command}${colors.reset}`) if (result.details) { console.log(` Details: ${result.details}`) } if (result.error) { console.log(` Error: ${result.error.trim()}`) } console.log() }) } // Generate detailed report const reportPath = join(__dirname, '../test-report.json') const report = { timestamp: new Date().toISOString(), summary: { total: testCommands.length, passed: passCount, failed: failCount, duration: totalDuration }, results } writeFileSync(reportPath, JSON.stringify(report, null, 2)) console.log(`\nšŸ“„ Detailed report saved to: ${colors.cyan}${reportPath}${colors.reset}`) // Exit with appropriate code if (failCount === 0) { console.log(`\n${colors.green}${colors.bold}šŸŽ‰ All tests passed!${colors.reset}`) process.exit(0) } else { console.log(`\n${colors.red}${colors.bold}āš ļø Some tests failed${colors.reset}`) process.exit(1) } } // Create test directory if needed const testDir = join(process.cwd(), '.ghostspeak-test') if (!existsSync(testDir)) { mkdirSync(testDir, { recursive: true }) } // Check if CLI is built const cliPath = join(__dirname, '../dist/index.js') if (!existsSync(cliPath)) { console.error(`${colors.red}Error: CLI not built. Run 'bun run build' first.${colors.reset}`) process.exit(1) } // Run tests testAllCommands().catch(error => { console.error(`${colors.red}Fatal error:${colors.reset}`, error) process.exit(1) })