UNPKG

@labnex/cli

Version:

CLI for Labnex, an AI-Powered Testing Automation Platform

226 lines • 11.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.analyzeCommand = void 0; const commander_1 = require("commander"); const inquirer_1 = __importDefault(require("inquirer")); const chalk_1 = __importDefault(require("chalk")); const ora_1 = __importDefault(require("ora")); const client_1 = require("../api/client"); exports.analyzeCommand = new commander_1.Command('analyze') .description('Analyze test execution results and pinpoint failure causes.') .addCommand(new commander_1.Command('failure') .description('Analyze a specific test failure from a run ID using AI for insights.') .option('--run-id <runId>', 'Test run ID to analyze failures from') .action(async (options) => { try { let { runId } = options; // Prompt for run ID if not provided if (!runId) { const runIdPrompt = await inquirer_1.default.prompt([ { type: 'input', name: 'runId', message: 'Enter test run ID:', validate: (input) => input.length > 0 || 'Test run ID is required' } ]); runId = runIdPrompt.runId; } console.log(chalk_1.default.cyan('šŸ” Analyzing test failure...')); console.log(chalk_1.default.gray(`šŸ†” Test Run ID: ${runId}`)); const spinner = (0, ora_1.default)('Fetching failure details...').start(); try { // Get test run results to find failures const resultsResponse = await client_1.apiClient.getTestRunResults(runId); if (!resultsResponse.success) { spinner.fail(chalk_1.default.red('Failed to fetch test run results: ' + resultsResponse.error)); return; } const results = resultsResponse.data; // Find failed test cases const failedTests = results.testCases.filter((testCase) => testCase.status === 'FAIL' || testCase.status === 'FAILED' || testCase.status === 'fail'); if (failedTests.length === 0) { spinner.succeed(chalk_1.default.green('No failed tests found in this test run')); console.log(chalk_1.default.gray('✨ All tests passed successfully!')); return; } spinner.succeed(`Found ${failedTests.length} failed test(s)`); let selectedFailure; if (failedTests.length === 1) { // Auto-select the single failure selectedFailure = failedTests[0]; console.log(chalk_1.default.gray(`šŸ“‹ Analyzing: ${selectedFailure.title}`)); } else { // Let user choose which failure to analyze console.log(chalk_1.default.yellow(`\nFound ${failedTests.length} failed tests:`)); failedTests.forEach((test, index) => { console.log(` ${index + 1}. ${test.title} - ${test.error || 'Unknown error'}`); }); const selectionPrompt = await inquirer_1.default.prompt([ { type: 'list', name: 'failure', message: 'Select which failure to analyze:', choices: failedTests.map((test, index) => ({ name: `${test.title} - ${test.error || 'Unknown error'}`, value: test })) } ]); selectedFailure = selectionPrompt.failure; } const analysisSpinner = (0, ora_1.default)('Analyzing failure with AI...').start(); try { // Use the test case ID as the failure ID for the AI analysis const response = await client_1.apiClient.analyzeFailure(runId, selectedFailure._id); if (response.success) { analysisSpinner.succeed(chalk_1.default.green('Failure analysis completed')); console.log(chalk_1.default.cyan('\nšŸ¤– AI Failure Analysis:')); console.log(chalk_1.default.gray('─'.repeat(60))); console.log(`${chalk_1.default.bold('Test Case:')} ${selectedFailure.title}`); console.log(`${chalk_1.default.bold('Status:')} ${chalk_1.default.red(selectedFailure.status)}`); console.log(`${chalk_1.default.bold('Duration:')} ${selectedFailure.duration}ms`); if (selectedFailure.error) { console.log(`${chalk_1.default.bold('Error:')} ${chalk_1.default.red(selectedFailure.error)}`); } console.log(`\n${chalk_1.default.bold('šŸ” Analysis:')}`); console.log(chalk_1.default.white(response.data.analysis)); if (response.data.suggestions.length > 0) { console.log(`\n${chalk_1.default.bold('šŸ’” Suggestions:')}`); response.data.suggestions.forEach((suggestion, index) => { console.log(` ${chalk_1.default.green(index + 1)}. ${suggestion}`); }); } console.log(chalk_1.default.gray('\n─'.repeat(60))); console.log(chalk_1.default.gray('šŸ’” Tip: Fix the issues above and re-run your tests!')); } else { analysisSpinner.fail(chalk_1.default.red('Analysis failed: ' + response.error)); } } catch (error) { analysisSpinner.fail(chalk_1.default.red('Analysis failed: ' + error.message)); } } catch (error) { spinner.fail(chalk_1.default.red('Failed to analyze failure: ' + error.message)); console.log(chalk_1.default.gray('Please check the test run ID and try again.')); } } catch (error) { console.error(chalk_1.default.red('Error:'), error.message); } })) .addCommand(new commander_1.Command('interactive') .description('Start an interactive AI session to analyze a failed test run.') .option('--run-id <runId>', 'The ID of the test run to analyze interactively') .action(async (options) => { let { runId } = options; if (!runId) { // Prompt for run ID if not provided const answers = await inquirer_1.default.prompt([{ type: 'input', name: 'runId', message: 'Enter the test run ID to analyze:' }]); runId = answers.runId; } console.log(chalk_1.default.cyan(`šŸš€ Starting interactive analysis for run ID: ${runId}`)); const initialSpinner = (0, ora_1.default)('Fetching initial failure data...').start(); try { const resultsResponse = await client_1.apiClient.getTestRunResults(runId); if (!resultsResponse.success || !resultsResponse.data) { initialSpinner.fail(chalk_1.default.red('Could not fetch test run results.')); return; } const failedTests = resultsResponse.data.testCases.filter((tc) => tc.status.toLowerCase() === 'failed' || tc.status.toLowerCase() === 'fail'); if (failedTests.length === 0) { initialSpinner.succeed(chalk_1.default.green('āœ… No failed tests found in this run!')); return; } initialSpinner.succeed(chalk_1.default.green('Found failed tests. Launching AI session...')); // For simplicity, we'll start with the first failed test. // This could be expanded to let the user choose. const testToAnalyze = failedTests[0]; // This will be our conversational loop await conversationalAnalysisLoop(runId, testToAnalyze); } catch (error) { initialSpinner.fail(chalk_1.default.red(`An error occurred: ${error.message}`)); } })); async function conversationalAnalysisLoop(runId, testCase) { let conversationHistory = []; let continueConversation = true; console.log(chalk_1.default.yellow(`\n\n--- Analyzing Failure: ${testCase.title} ---`)); // Initial analysis call const initialAnalysisSpinner = (0, ora_1.default)('Performing initial AI analysis...').start(); try { const initialResponse = await client_1.apiClient.analyzeFailure(runId, testCase._id); if (initialResponse.success) { initialAnalysisSpinner.succeed('Initial analysis complete.'); console.log(chalk_1.default.blue.bold('\nšŸ¤– Initial AI Analysis:')); console.log(chalk_1.default.white(initialResponse.data.analysis)); if (initialResponse.data.suggestions.length > 0) { console.log(chalk_1.default.green.bold('\nšŸ’” Suggestions:')); initialResponse.data.suggestions.forEach((s) => console.log(chalk_1.default.green(`- ${s}`))); } // Add AI response to history conversationHistory.push({ role: 'assistant', content: initialResponse.data.analysis }); } else { initialAnalysisSpinner.fail(chalk_1.default.red('Initial analysis failed.')); return; } } catch (e) { initialAnalysisSpinner.fail(chalk_1.default.red(`An error occurred during analysis: ${e.message}`)); return; } while (continueConversation) { const { action } = await inquirer_1.default.prompt([ { type: 'list', name: 'action', message: '\nWhat would you like to do next?', choices: [ { name: 'Ask a follow-up question', value: 'ask' }, { name: 'Suggest a code fix (coming soon)', value: 'fix', disabled: true }, new inquirer_1.default.Separator(), { name: 'Exit interactive session', value: 'exit' }, ], }, ]); if (action === 'exit') { continueConversation = false; } else if (action === 'ask') { const { question } = await inquirer_1.default.prompt([ { type: 'input', name: 'question', message: 'Your question for the AI:' } ]); const followUpSpinner = (0, ora_1.default)('Thinking...').start(); conversationHistory.push({ role: 'user', content: question }); try { const response = await client_1.apiClient.analyzeFailureConversational(runId, testCase._id, conversationHistory, question); if (response.success) { followUpSpinner.succeed('AI responded.'); console.log(chalk_1.default.blue.bold('\nšŸ¤– AI:')); console.log(chalk_1.default.white(response.data.analysis)); conversationHistory.push({ role: 'assistant', content: response.data.analysis }); } else { followUpSpinner.fail(chalk_1.default.red(`The AI could not respond: ${response.error}`)); // Remove the failed user question from history conversationHistory.pop(); } } catch (error) { followUpSpinner.fail(chalk_1.default.red(`An error occurred: ${error.message}`)); // Remove the failed user question from history conversationHistory.pop(); } } } console.log(chalk_1.default.cyan('\nāœ… Exited interactive analysis session.')); } //# sourceMappingURL=analyze.js.map