59df2f6856
Update error handling and improve streaming capabilities in the Ollama client and related components. Key changes include: - Simplify error types and improve error handling - Refactor streaming logic to use async generators - Update tool execution and vault indexing - Improve utility functions and types - Update test files to reflect changes
192 lines
7.2 KiB
TypeScript
Executable File
192 lines
7.2 KiB
TypeScript
Executable File
import { ErrorHandler } from '../src/error-handler';
|
|
import {
|
|
OllamaError,
|
|
ErrorType,
|
|
NetworkError,
|
|
ApiError,
|
|
ValidationError,
|
|
StreamingError,
|
|
ToolExecutionError,
|
|
PathValidationError,
|
|
} from '../src/types';
|
|
|
|
// Mock Notice from Obsidian
|
|
jest.mock('obsidian', () => ({
|
|
Notice: jest.fn(),
|
|
}));
|
|
|
|
describe('ErrorHandler', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('handleError', () => {
|
|
it('should handle OllamaError with user-friendly message', () => {
|
|
const error = new NetworkError('Connection failed');
|
|
ErrorHandler.handleError(error);
|
|
expect(require('obsidian').Notice).toHaveBeenCalledWith(
|
|
'Connection error. Please check if Ollama is running.'
|
|
);
|
|
});
|
|
|
|
it('should handle generic Error with user-friendly message', () => {
|
|
const error = new Error('Network timeout occurred');
|
|
ErrorHandler.handleError(error);
|
|
expect(require('obsidian').Notice).toHaveBeenCalledWith(
|
|
'Request timed out. Please check your Ollama connection.'
|
|
);
|
|
});
|
|
|
|
it('should handle unknown error type with generic message', () => {
|
|
const error = 'some string error';
|
|
ErrorHandler.handleError(error);
|
|
expect(require('obsidian').Notice).toHaveBeenCalledWith('An unexpected error occurred');
|
|
});
|
|
|
|
it('should log detailed error information to console', () => {
|
|
const error = new Error('Test error');
|
|
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
ErrorHandler.handleError(error);
|
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Test error'));
|
|
consoleSpy.mockRestore();
|
|
});
|
|
});
|
|
|
|
describe('NetworkError handling', () => {
|
|
it('should create user-friendly message for network errors', () => {
|
|
const error = new NetworkError('Connection failed');
|
|
const message = ErrorHandler['getUserFriendlyMessage'](error);
|
|
expect(message).toBe('Connection error. Please check if Ollama is running.');
|
|
});
|
|
|
|
it('should include status code in error details', () => {
|
|
const error = new NetworkError('Connection failed', 500);
|
|
expect(error.statusCode).toBe(500);
|
|
});
|
|
});
|
|
|
|
describe('ValidationError handling', () => {
|
|
it('should create user-friendly message for validation errors', () => {
|
|
const error = new ValidationError('Invalid input', {
|
|
field: 'path',
|
|
message: 'Path is required',
|
|
});
|
|
const message = ErrorHandler['getUserFriendlyMessage'](error);
|
|
expect(message).toContain('Invalid path');
|
|
});
|
|
|
|
it('should handle validation errors without field details', () => {
|
|
const error = new ValidationError('Invalid input');
|
|
const message = ErrorHandler['getUserFriendlyMessage'](error);
|
|
expect(message).toBe('Input validation error. Please correct your input.');
|
|
});
|
|
});
|
|
|
|
describe('StreamingError handling', () => {
|
|
it('should create user-friendly message for streaming errors', () => {
|
|
const error = new StreamingError('Response too long');
|
|
const message = ErrorHandler['getUserFriendlyMessage'](error);
|
|
expect(message).toBe('Response too long. Please try a shorter request.');
|
|
});
|
|
});
|
|
|
|
describe('ToolExecutionError handling', () => {
|
|
it('should create user-friendly message for tool errors', () => {
|
|
const error = new ToolExecutionError('Tool failed', 'create_file');
|
|
const message = ErrorHandler['getUserFriendlyMessage'](error);
|
|
expect(message).toContain('Tool error');
|
|
expect(message).toContain('create_file');
|
|
});
|
|
});
|
|
|
|
describe('PathValidationError handling', () => {
|
|
it('should create user-friendly message for path errors', () => {
|
|
const error = new PathValidationError('Invalid path', '/../test.md');
|
|
const message = ErrorHandler['getUserFriendlyMessage'](error);
|
|
expect(message).toContain('Invalid file path');
|
|
});
|
|
});
|
|
|
|
describe('Error creation methods', () => {
|
|
it('should create NetworkError with proper type', () => {
|
|
const error = ErrorHandler.createNetworkError('Connection failed');
|
|
expect(error).toBeInstanceOf(NetworkError);
|
|
expect(error.type).toBe(ErrorType.NETWORK_ERROR);
|
|
});
|
|
|
|
it('should create ApiError with proper type', () => {
|
|
const error = ErrorHandler.createApiError('API error');
|
|
expect(error).toBeInstanceOf(ApiError);
|
|
expect(error.type).toBe(ErrorType.API_ERROR);
|
|
});
|
|
|
|
it('should create ValidationError with proper type', () => {
|
|
const error = ErrorHandler.createValidationError('Validation failed', 'path');
|
|
expect(error).toBeInstanceOf(ValidationError);
|
|
expect(error.type).toBe(ErrorType.VALIDATION_ERROR);
|
|
});
|
|
|
|
it('should create StreamingError with proper type', () => {
|
|
const error = ErrorHandler.createStreamingError('Streaming failed');
|
|
expect(error).toBeInstanceOf(StreamingError);
|
|
expect(error.type).toBe(ErrorType.STREAMING_ERROR);
|
|
});
|
|
|
|
it('should create ToolExecutionError with proper type', () => {
|
|
const error = ErrorHandler.createToolExecutionError('Tool failed');
|
|
expect(error).toBeInstanceOf(ToolExecutionError);
|
|
expect(error.type).toBe(ErrorType.TOOL_EXECUTION_ERROR);
|
|
});
|
|
|
|
it('should create PathValidationError with proper type', () => {
|
|
const error = ErrorHandler.createPathValidationError('Path invalid');
|
|
expect(error).toBeInstanceOf(PathValidationError);
|
|
expect(error.type).toBe(ErrorType.PATH_VALIDATION_ERROR);
|
|
});
|
|
|
|
it('should create UnknownError with proper type', () => {
|
|
const error = ErrorHandler.createUnknownError('Unknown error');
|
|
expect(error).toBeInstanceOf(OllamaError);
|
|
expect(error.type).toBe(ErrorType.UNKNOWN_ERROR);
|
|
});
|
|
});
|
|
|
|
describe('Error message detection', () => {
|
|
it('should detect network-related errors in generic Error', () => {
|
|
const error = new Error('Network connection failed');
|
|
const message = ErrorHandler['getUserFriendlyMessageFromError'](error);
|
|
expect(message).toContain('Connection error');
|
|
});
|
|
|
|
it('should detect timeout errors in generic Error', () => {
|
|
const error = new Error('Request timeout occurred');
|
|
const message = ErrorHandler['getUserFriendlyMessageFromError'](error);
|
|
expect(message).toContain('timed out');
|
|
});
|
|
|
|
it('should detect validation errors in generic Error', () => {
|
|
const error = new Error('Validation format error');
|
|
const message = ErrorHandler['getUserFriendlyMessageFromError'](error);
|
|
expect(message).toContain('Invalid input');
|
|
});
|
|
|
|
it('should detect streaming errors in generic Error', () => {
|
|
const error = new Error('Streaming chunk error');
|
|
const message = ErrorHandler['getUserFriendlyMessageFromError'](error);
|
|
expect(message).toContain('Response too long');
|
|
});
|
|
|
|
it('should detect tool errors in generic Error', () => {
|
|
const error = new Error('Tool function error');
|
|
const message = ErrorHandler['getUserFriendlyMessageFromError'](error);
|
|
expect(message).toContain('Tool execution error');
|
|
});
|
|
|
|
it('should detect path errors in generic Error', () => {
|
|
const error = new Error('Path file error');
|
|
const message = ErrorHandler['getUserFriendlyMessageFromError'](error);
|
|
expect(message).toContain('Invalid file path');
|
|
});
|
|
});
|
|
});
|