import { LogManager } from '../http/log-handler.js';
export interface TestStep {
order: number;
action: string;
expectedBehavior?: string;
}
export interface TestPlan {
bugDescription: string;
attemptNumber: number;
steps: TestStep[];
userPrompt: string;
userOptions: string[];
modifiedFiles: string[];
}
export class TestStepGenerator {
private logManager: LogManager;
constructor() {
this.logManager = new LogManager();
}
/**
* Generate test steps based on bug description
*/
generateTestSteps(
bugDescription: string,
attemptNumber: number,
modifiedFiles: string[],
possibleCauses?: string[]
): TestPlan {
const steps: TestStep[] = [];
const lowerDesc = bugDescription.toLowerCase();
// Analyze bug type and generate appropriate steps
// 1. Click/interaction issues
if (lowerDesc.includes('click') || lowerDesc.includes('button')) {
steps.push({
order: 1,
action: 'Open the application/page where the issue occurs',
expectedBehavior: 'Page loads without errors'
});
steps.push({
order: 2,
action: 'Locate the button or interactive element',
expectedBehavior: 'Button is visible and clickable'
});
steps.push({
order: 3,
action: 'Click the button',
expectedBehavior: 'Expected action should occur'
});
steps.push({
order: 4,
action: 'Check if debug logs were sent (check browser console or debug log file)',
expectedBehavior: 'Debug logs should show the click event and any data'
});
}
// 2. Login/auth issues
else if (lowerDesc.includes('login') || lowerDesc.includes('登录')) {
steps.push({
order: 1,
action: 'Navigate to the login page',
expectedBehavior: 'Login form is displayed'
});
steps.push({
order: 2,
action: 'Enter username and password',
expectedBehavior: 'Form accepts input'
});
steps.push({
order: 3,
action: 'Click the login button',
expectedBehavior: 'Login request is sent'
});
steps.push({
order: 4,
action: 'Check debug logs for API request/response',
expectedBehavior: 'Logs should show the login attempt and server response'
});
steps.push({
order: 5,
action: 'Verify login result (success or failure)',
expectedBehavior: 'Based on the actual behavior'
});
}
// 3. Display/rendering issues
else if (lowerDesc.includes('display') || lowerDesc.includes('show') || lowerDesc.includes('显示')) {
steps.push({
order: 1,
action: 'Navigate to the page where content should be displayed',
expectedBehavior: 'Page loads'
});
steps.push({
order: 2,
action: 'Wait for data to load (check loading indicators)',
expectedBehavior: 'Loading completes'
});
steps.push({
order: 3,
action: 'Check if content is displayed',
expectedBehavior: 'Content should be visible'
});
steps.push({
order: 4,
action: 'Check debug logs for data retrieval',
expectedBehavior: 'Logs should show fetched data and rendering state'
});
steps.push({
order: 5,
action: 'Inspect the element in browser DevTools',
expectedBehavior: 'Check if element exists but is hidden'
});
}
// 4. API issues
else if (lowerDesc.includes('api') || lowerDesc.includes('request') || lowerDesc.includes('fetch')) {
steps.push({
order: 1,
action: 'Trigger the API request (perform action that calls the API)',
expectedBehavior: 'Request should be initiated'
});
steps.push({
order: 2,
action: 'Check browser Network tab or debug logs',
expectedBehavior: 'Should see the request being sent'
});
steps.push({
order: 3,
action: 'Examine request details (URL, headers, body)',
expectedBehavior: 'All required data should be included'
});
steps.push({
order: 4,
action: 'Check the response status and body',
expectedBehavior: 'Response should be successful (2xx) and contain expected data'
});
steps.push({
order: 5,
action: 'Review debug logs for any error messages',
expectedBehavior: 'Should identify the issue if request failed'
});
}
// 5. Form issues
else if (lowerDesc.includes('form') || lowerDesc.includes('input') || lowerDesc.includes('submit')) {
steps.push({
order: 1,
action: 'Open the form',
expectedBehavior: 'Form is displayed'
});
steps.push({
order: 2,
action: 'Fill in form fields with test data',
expectedBehavior: 'All fields accept input'
});
steps.push({
order: 3,
action: 'Submit the form',
expectedBehavior: 'Submit action is triggered'
});
steps.push({
order: 4,
action: 'Check debug logs for form data and validation results',
expectedBehavior: 'Logs should show captured form data'
});
steps.push({
order: 5,
action: 'Verify if data was submitted successfully',
expectedBehavior: 'Success message or data submission confirmation'
});
}
// Default generic steps
else {
steps.push({
order: 1,
action: 'Reproduce the issue by following the steps that trigger the bug',
expectedBehavior: 'Bug should occur'
});
steps.push({
order: 2,
action: 'Check debug logs for any output',
expectedBehavior: 'Debug logs should provide insights'
});
steps.push({
order: 3,
action: 'Examine error messages or unexpected behavior',
expectedBehavior: 'Note any errors or deviations from expected behavior'
});
steps.push({
order: 4,
action: 'Review the code sections indicated by debug logs',
expectedBehavior: 'Should identify problematic code'
});
}
// Add final step about providing feedback
steps.push({
order: steps.length + 1,
action: 'Provide feedback: Did the bug get fixed or is it still occurring?',
expectedBehavior: 'Select "Bug已修复" (Fixed) or "Bug未修复" (Not Fixed)'
});
return {
bugDescription,
attemptNumber,
steps,
userPrompt: this.generateUserPrompt(attemptNumber, possibleCauses),
userOptions: ['Bug已修复 (Fixed)', 'Bug未修复 (Not Fixed)'],
modifiedFiles
};
}
private generateUserPrompt(attemptNumber: number, possibleCauses?: string[]): string {
let prompt = `=== Debugging Attempt #${attemptNumber} ===\n\n`;
if (attemptNumber === 1) {
prompt += `I've added debug logs to your code to help diagnose the issue.\n\n`;
prompt += `Please follow the test steps above to reproduce the bug.\n`;
prompt += `The debug logs will help us understand what's happening in your code.\n\n`;
} else {
prompt += `I've added more debug logs based on the previous analysis.\n\n`;
prompt += `Please test again and provide feedback on the results.\n\n`;
}
if (possibleCauses && possibleCauses.length > 0) {
prompt += `Possible causes I'm investigating:\n`;
possibleCauses.slice(0, 3).forEach((cause, index) => {
prompt += `${index + 1}. ${cause}\n`;
});
prompt += '\n';
}
prompt += `After testing, please select one of the following:\n`;
prompt += `• "Bug已修复 (Fixed)" - The issue is resolved\n`;
prompt += `• "Bug未修复 (Not Fixed)" - The issue still occurs\n`;
return prompt;
}
/**
* Read current debug logs and provide analysis
*/
analyzeDebugLogs(): {
logs: string[];
analysis: string;
suggestions: string[];
} {
const logs = this.logManager.readLogs(100);
if (logs.length === 0) {
return {
logs: [],
analysis: 'No debug logs found. The debug code may not have been executed yet.',
suggestions: [
'Verify that the code with debug logs is actually being executed',
'Check if the application is running and can reach the debug server',
'Ensure the debug server is running on the correct port',
'Look for any errors in the application console'
]
};
}
// Analyze logs
const analysis: string[] = [];
const suggestions: string[] = [];
analysis.push(`Found ${logs.length} log entries`);
// Check for errors
const errors = logs.filter(log =>
log.level === 'error' ||
log.message.toLowerCase().includes('error') ||
log.message.toLowerCase().includes('fail')
);
if (errors.length > 0) {
analysis.push(`Detected ${errors.length} error(s) in logs`);
suggestions.push('Investigate the errors first - they are likely the root cause');
suggestions.push('Add more debug logs around the error locations');
}
// Check for undefined/null
const nulls = logs.filter(log => {
const str = JSON.stringify(log);
return str.includes('null') || str.includes('undefined');
});
if (nulls.length > 0) {
analysis.push(`Found ${nulls.length} entries with null/undefined values`);
suggestions.push('Check for missing or uninitialized data');
suggestions.push('Add null checks where values are used');
}
// Get latest messages
const latestLogs = logs.slice(-5).map(log =>
`[${log.level?.toUpperCase() || 'INFO'}] ${log.message}`
);
return {
logs: latestLogs,
analysis: analysis.join('. '),
suggestions
};
}
/**
* Generate summary after successful fix
*/
generateFixSummary(
bugDescription: string,
attemptNumber: number,
modifiedFiles: string[],
finalAnalysis?: string
): string {
let summary = `=== Bug Fixed Successfully! ===\n\n`;
summary += `Bug Description: ${bugDescription}\n`;
summary += `Attempts Required: ${attemptNumber}\n`;
summary += `Files Modified: ${modifiedFiles.length}\n\n`;
if (modifiedFiles.length > 0) {
summary += `Modified Files:\n`;
modifiedFiles.forEach(file => {
summary += ` • ${file}\n`;
});
summary += '\n';
}
if (finalAnalysis) {
summary += `Root Cause Analysis:\n${finalAnalysis}\n\n`;
}
summary += `All debug logs have been removed from your code.\n`;
summary += `Your codebase is now clean and the bug is fixed!\n`;
return summary;
}
}