Files
obsidian_ollama/tests/error-handler.test.ts

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 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');
});
});
});