osc-mcp-server
Version:
Model Context Protocol server for OSC (Open Sound Control) endpoint management
214 lines • 12.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = require("./index");
const index_2 = require("../types/index");
function getErrorDetail(error, key) {
return error.details?.[key];
}
describe('Error Handling System', () => {
describe('createOSCError', () => {
it('should create a basic OSC error', () => {
const error = (0, index_1.createOSCError)(index_2.ErrorCode.INTERNAL_ERROR, 'Test error');
expect(error.code).toBe(index_2.ErrorCode.INTERNAL_ERROR);
expect(error.message).toBe('Test error');
expect(error.details).toEqual({});
});
it('should create an OSC error with details', () => {
const details = { port: 8000, reason: 'test' };
const error = (0, index_1.createOSCError)(index_2.ErrorCode.PORT_IN_USE, 'Port in use', details);
expect(error.code).toBe(index_2.ErrorCode.PORT_IN_USE);
expect(error.message).toBe('Port in use');
expect(error.details).toEqual(details);
});
});
describe('NetworkErrors', () => {
it('should create port in use error', () => {
const error = index_1.NetworkErrors.portInUse(8000, [8001, 8002]);
expect(error.code).toBe(index_2.ErrorCode.PORT_IN_USE);
expect(error.message).toContain('Port 8000 is already in use');
expect(getErrorDetail(error, 'port')).toBe(8000);
expect(getErrorDetail(error, 'suggestedPorts')).toEqual([8001, 8002]);
});
it('should create port invalid error', () => {
const error = index_1.NetworkErrors.portInvalid(100);
expect(error.code).toBe(index_2.ErrorCode.PORT_INVALID);
expect(error.message).toContain('Invalid port number: 100');
expect(getErrorDetail(error, 'port')).toBe(100);
expect(getErrorDetail(error, 'validRange')).toEqual({ min: 1024, max: 65535 });
});
it('should create permission denied error', () => {
const error = index_1.NetworkErrors.permissionDenied(80);
expect(error.code).toBe(index_2.ErrorCode.PERMISSION_DENIED);
expect(error.message).toContain('Permission denied to bind to port 80');
expect(getErrorDetail(error, 'port')).toBe(80);
});
it('should create network error', () => {
const error = index_1.NetworkErrors.networkError('Connection failed', { reason: 'timeout' });
expect(error.code).toBe(index_2.ErrorCode.NETWORK_ERROR);
expect(error.message).toBe('Network error: Connection failed');
expect(getErrorDetail(error, 'reason')).toBe('timeout');
});
});
describe('EndpointErrors', () => {
it('should create endpoint not found error', () => {
const error = index_1.EndpointErrors.notFound('endpoint-1');
expect(error.code).toBe(index_2.ErrorCode.ENDPOINT_NOT_FOUND);
expect(error.message).toContain("Endpoint 'endpoint-1' not found");
expect(getErrorDetail(error, 'endpointId')).toBe('endpoint-1');
});
it('should create endpoint already exists error', () => {
const error = index_1.EndpointErrors.alreadyExists('endpoint-1', 8000);
expect(error.code).toBe(index_2.ErrorCode.ENDPOINT_ALREADY_EXISTS);
expect(error.message).toContain('endpoint already exists on port 8000');
expect(getErrorDetail(error, 'endpointId')).toBe('endpoint-1');
expect(getErrorDetail(error, 'port')).toBe(8000);
});
it('should create start failed error', () => {
const error = index_1.EndpointErrors.startFailed('endpoint-1', 'Socket error');
expect(error.code).toBe(index_2.ErrorCode.ENDPOINT_START_FAILED);
expect(error.message).toContain("Failed to start endpoint 'endpoint-1': Socket error");
expect(getErrorDetail(error, 'endpointId')).toBe('endpoint-1');
expect(getErrorDetail(error, 'reason')).toBe('Socket error');
});
it('should create already active error', () => {
const error = index_1.EndpointErrors.alreadyActive('endpoint-1');
expect(error.code).toBe(index_2.ErrorCode.ENDPOINT_ALREADY_EXISTS);
expect(error.message).toContain("Endpoint 'endpoint-1' is already active");
expect(getErrorDetail(error, 'endpointId')).toBe('endpoint-1');
});
it('should create already stopped error', () => {
const error = index_1.EndpointErrors.alreadyStopped('endpoint-1');
expect(error.code).toBe(index_2.ErrorCode.ENDPOINT_NOT_FOUND);
expect(error.message).toContain("Endpoint 'endpoint-1' is already stopped");
expect(getErrorDetail(error, 'endpointId')).toBe('endpoint-1');
});
});
describe('MessageErrors', () => {
it('should create parse error', () => {
const error = index_1.MessageErrors.parseError('Invalid format', { offset: 10 });
expect(error.code).toBe(index_2.ErrorCode.MESSAGE_PARSE_ERROR);
expect(error.message).toBe('Failed to parse OSC message: Invalid format');
expect(getErrorDetail(error, 'offset')).toBe(10);
});
it('should create invalid message error', () => {
const error = index_1.MessageErrors.invalidMessage('Missing address');
expect(error.code).toBe(index_2.ErrorCode.INVALID_OSC_MESSAGE);
expect(error.message).toBe('Invalid OSC message format: Missing address');
expect(getErrorDetail(error, 'reason')).toBe('Missing address');
});
it('should create unsupported type error', () => {
const error = index_1.MessageErrors.unsupportedType('x');
expect(error.code).toBe(index_2.ErrorCode.MESSAGE_PARSE_ERROR);
expect(error.message).toContain("Unsupported OSC type tag 'x'");
expect(getErrorDetail(error, 'unsupportedType')).toBe('x');
expect(getErrorDetail(error, 'supportedTypes')).toEqual(['i', 'f', 's', 'b']);
});
});
describe('ValidationErrors', () => {
it('should create missing parameter error', () => {
const error = index_1.ValidationErrors.missingParameter('port');
expect(error.code).toBe(index_2.ErrorCode.MISSING_REQUIRED_PARAMETER);
expect(error.message).toBe("Missing required parameter: 'port'");
expect(getErrorDetail(error, 'paramName')).toBe('port');
});
it('should create invalid parameter error', () => {
const error = index_1.ValidationErrors.invalidParameter('port', 'abc', 'number');
expect(error.code).toBe(index_2.ErrorCode.INVALID_PARAMETERS);
expect(error.message).toContain("Invalid parameter 'port': expected number, got string");
expect(getErrorDetail(error, 'paramName')).toBe('port');
expect(getErrorDetail(error, 'providedValue')).toBe('abc');
expect(getErrorDetail(error, 'expectedType')).toBe('number');
});
it('should create parameter out of range error', () => {
const error = index_1.ValidationErrors.parameterOutOfRange('port', 100, 1024, 65535);
expect(error.code).toBe(index_2.ErrorCode.INVALID_PARAMETERS);
expect(error.message).toContain("Parameter 'port' value 100 is out of range");
expect(getErrorDetail(error, 'paramName')).toBe('port');
expect(getErrorDetail(error, 'value')).toBe(100);
expect(getErrorDetail(error, 'validRange')).toEqual({ min: 1024, max: 65535 });
});
it('should create invalid address pattern error', () => {
const error = index_1.ValidationErrors.invalidAddressPattern('invalid');
expect(error.code).toBe(index_2.ErrorCode.INVALID_PARAMETERS);
expect(error.message).toContain("Invalid OSC address pattern: 'invalid'");
expect(getErrorDetail(error, 'pattern')).toBe('invalid');
});
});
describe('OperationErrors', () => {
it('should create internal error', () => {
const error = index_1.OperationErrors.internalError('Database connection failed', { db: 'main' });
expect(error.code).toBe(index_2.ErrorCode.INTERNAL_ERROR);
expect(error.message).toBe('Internal error: Database connection failed');
expect(getErrorDetail(error, 'db')).toBe('main');
});
it('should create operation failed error', () => {
const error = index_1.OperationErrors.operationFailed('createEndpoint', 'Port unavailable');
expect(error.code).toBe(index_2.ErrorCode.OPERATION_FAILED);
expect(error.message).toBe("Operation 'createEndpoint' failed: Port unavailable");
expect(getErrorDetail(error, 'operation')).toBe('createEndpoint');
expect(getErrorDetail(error, 'reason')).toBe('Port unavailable');
});
});
describe('ErrorUtils', () => {
it('should convert Error to OSCError', () => {
const originalError = new Error('Test error');
const oscError = index_1.ErrorUtils.fromError(originalError);
expect(oscError.code).toBe(index_2.ErrorCode.INTERNAL_ERROR);
expect(oscError.message).toBe('Test error');
expect(getErrorDetail(oscError, 'originalError')).toBe('Error');
});
it('should convert Error to OSCError with custom code', () => {
const originalError = new Error('Network error');
const oscError = index_1.ErrorUtils.fromError(originalError, index_2.ErrorCode.NETWORK_ERROR);
expect(oscError.code).toBe(index_2.ErrorCode.NETWORK_ERROR);
expect(oscError.message).toBe('Network error');
});
it('should identify network errors', () => {
const networkError = index_1.NetworkErrors.portInUse(8000);
const otherError = index_1.ValidationErrors.missingParameter('port');
expect(index_1.ErrorUtils.isNetworkError(networkError)).toBe(true);
expect(index_1.ErrorUtils.isNetworkError(otherError)).toBe(false);
});
it('should identify recoverable errors', () => {
const recoverableError = index_1.NetworkErrors.portInUse(8000);
const nonRecoverableError = index_1.OperationErrors.internalError('System failure');
expect(index_1.ErrorUtils.isRecoverable(recoverableError)).toBe(true);
expect(index_1.ErrorUtils.isRecoverable(nonRecoverableError)).toBe(false);
});
it('should provide suggestions for port in use error', () => {
const error = index_1.NetworkErrors.portInUse(8000, [8001, 8002]);
const suggestions = index_1.ErrorUtils.getSuggestions(error);
expect(suggestions).toContain('Try using a different port number');
expect(suggestions.some(s => s.includes('8001, 8002'))).toBe(true);
});
it('should provide suggestions for invalid port error', () => {
const error = index_1.NetworkErrors.portInvalid(100);
const suggestions = index_1.ErrorUtils.getSuggestions(error);
expect(suggestions).toContain('Use a port number between 1024 and 65535');
});
it('should provide suggestions for permission denied error', () => {
const error = index_1.NetworkErrors.permissionDenied(80);
const suggestions = index_1.ErrorUtils.getSuggestions(error);
expect(suggestions).toContain('Use a port number above 1024');
expect(suggestions).toContain('Run the application with appropriate privileges');
});
it('should provide suggestions for endpoint not found error', () => {
const error = index_1.EndpointErrors.notFound('endpoint-1');
const suggestions = index_1.ErrorUtils.getSuggestions(error);
expect(suggestions).toContain('Check that the endpoint ID is correct');
expect(suggestions).toContain('Use get_endpoint_status to see available endpoints');
});
});
describe('formatErrorResponse', () => {
it('should format error response with suggestions', () => {
const error = index_1.NetworkErrors.portInUse(8000, [8001, 8002]);
const response = (0, index_1.formatErrorResponse)(error);
expect(response.error.code).toBe(index_2.ErrorCode.PORT_IN_USE);
expect(response.error.message).toContain('Port 8000 is already in use');
expect(response.error.details).toBeDefined();
expect(response.error.suggestions).toBeDefined();
expect(response.error.suggestions.length).toBeGreaterThan(0);
});
});
});
//# sourceMappingURL=index.test.js.map