mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 12:21:13 -05:00
feat: implement code action provider for VS Code integration
This commit is contained in:
145
src/core/__tests__/CodeActionProvider.test.ts
Normal file
145
src/core/__tests__/CodeActionProvider.test.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { CodeActionProvider } from '../CodeActionProvider';
|
||||
|
||||
// Mock VSCode API
|
||||
jest.mock('vscode', () => ({
|
||||
CodeAction: jest.fn().mockImplementation((title, kind) => ({
|
||||
title,
|
||||
kind,
|
||||
command: undefined
|
||||
})),
|
||||
CodeActionKind: {
|
||||
QuickFix: { value: 'quickfix' },
|
||||
RefactorRewrite: { value: 'refactor.rewrite' }
|
||||
},
|
||||
Range: jest.fn().mockImplementation((startLine, startChar, endLine, endChar) => ({
|
||||
start: { line: startLine, character: startChar },
|
||||
end: { line: endLine, character: endChar }
|
||||
})),
|
||||
Position: jest.fn().mockImplementation((line, character) => ({
|
||||
line,
|
||||
character
|
||||
})),
|
||||
workspace: {
|
||||
getWorkspaceFolder: jest.fn()
|
||||
},
|
||||
DiagnosticSeverity: {
|
||||
Error: 0,
|
||||
Warning: 1,
|
||||
Information: 2,
|
||||
Hint: 3
|
||||
}
|
||||
}));
|
||||
|
||||
describe('CodeActionProvider', () => {
|
||||
let provider: CodeActionProvider;
|
||||
let mockDocument: any;
|
||||
let mockRange: any;
|
||||
let mockContext: any;
|
||||
|
||||
beforeEach(() => {
|
||||
provider = new CodeActionProvider();
|
||||
|
||||
// Mock document
|
||||
mockDocument = {
|
||||
getText: jest.fn(),
|
||||
lineAt: jest.fn(),
|
||||
lineCount: 10,
|
||||
uri: { fsPath: '/test/file.ts' }
|
||||
};
|
||||
|
||||
// Mock range
|
||||
mockRange = new vscode.Range(0, 0, 0, 10);
|
||||
|
||||
// Mock context
|
||||
mockContext = {
|
||||
diagnostics: []
|
||||
};
|
||||
});
|
||||
|
||||
describe('getEffectiveRange', () => {
|
||||
it('should return selected text when available', () => {
|
||||
mockDocument.getText.mockReturnValue('selected text');
|
||||
|
||||
const result = (provider as any).getEffectiveRange(mockDocument, mockRange);
|
||||
|
||||
expect(result).toEqual({
|
||||
range: mockRange,
|
||||
text: 'selected text'
|
||||
});
|
||||
});
|
||||
|
||||
it('should return null for empty line', () => {
|
||||
mockDocument.getText.mockReturnValue('');
|
||||
mockDocument.lineAt.mockReturnValue({ text: '', lineNumber: 0 });
|
||||
|
||||
const result = (provider as any).getEffectiveRange(mockDocument, mockRange);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFilePath', () => {
|
||||
it('should return relative path when in workspace', () => {
|
||||
const mockWorkspaceFolder = {
|
||||
uri: { fsPath: '/test' }
|
||||
};
|
||||
(vscode.workspace.getWorkspaceFolder as jest.Mock).mockReturnValue(mockWorkspaceFolder);
|
||||
|
||||
const result = (provider as any).getFilePath(mockDocument);
|
||||
|
||||
expect(result).toBe('file.ts');
|
||||
});
|
||||
|
||||
it('should return absolute path when not in workspace', () => {
|
||||
(vscode.workspace.getWorkspaceFolder as jest.Mock).mockReturnValue(null);
|
||||
|
||||
const result = (provider as any).getFilePath(mockDocument);
|
||||
|
||||
expect(result).toBe('/test/file.ts');
|
||||
});
|
||||
});
|
||||
|
||||
describe('provideCodeActions', () => {
|
||||
beforeEach(() => {
|
||||
mockDocument.getText.mockReturnValue('test code');
|
||||
mockDocument.lineAt.mockReturnValue({ text: 'test code', lineNumber: 0 });
|
||||
});
|
||||
|
||||
it('should provide explain and improve actions by default', () => {
|
||||
const actions = provider.provideCodeActions(mockDocument, mockRange, mockContext);
|
||||
|
||||
expect(actions).toHaveLength(2);
|
||||
expect((actions as any)[0].title).toBe('Roo Cline: Explain Code');
|
||||
expect((actions as any)[1].title).toBe('Roo Cline: Improve Code');
|
||||
});
|
||||
|
||||
it('should provide fix action when diagnostics exist', () => {
|
||||
mockContext.diagnostics = [{
|
||||
message: 'test error',
|
||||
severity: vscode.DiagnosticSeverity.Error,
|
||||
range: mockRange
|
||||
}];
|
||||
|
||||
const actions = provider.provideCodeActions(mockDocument, mockRange, mockContext);
|
||||
|
||||
expect(actions).toHaveLength(3);
|
||||
expect((actions as any).some((a: any) => a.title === 'Roo Cline: Fix Code')).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle errors gracefully', () => {
|
||||
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
mockDocument.getText.mockImplementation(() => {
|
||||
throw new Error('Test error');
|
||||
});
|
||||
mockDocument.lineAt.mockReturnValue({ text: 'test', lineNumber: 0 });
|
||||
|
||||
const actions = provider.provideCodeActions(mockDocument, mockRange, mockContext);
|
||||
|
||||
expect(actions).toEqual([]);
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith('Error getting effective range:', expect.any(Error));
|
||||
|
||||
consoleErrorSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user