Skip to main content
Glama

n8n-MCP

by 88-888
validation-service-error.test.tsβ€’11.5 kB
import { describe, it, expect, vi, beforeEach } from 'vitest'; import { ValidationServiceError } from '@/errors/validation-service-error'; describe('ValidationServiceError', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('constructor', () => { it('should create error with basic message', () => { const error = new ValidationServiceError('Test error message'); expect(error.name).toBe('ValidationServiceError'); expect(error.message).toBe('Test error message'); expect(error.nodeType).toBeUndefined(); expect(error.property).toBeUndefined(); expect(error.cause).toBeUndefined(); }); it('should create error with all parameters', () => { const cause = new Error('Original error'); const error = new ValidationServiceError( 'Validation failed', 'nodes-base.slack', 'channel', cause ); expect(error.name).toBe('ValidationServiceError'); expect(error.message).toBe('Validation failed'); expect(error.nodeType).toBe('nodes-base.slack'); expect(error.property).toBe('channel'); expect(error.cause).toBe(cause); }); it('should maintain proper inheritance from Error', () => { const error = new ValidationServiceError('Test message'); expect(error).toBeInstanceOf(Error); expect(error).toBeInstanceOf(ValidationServiceError); }); it('should capture stack trace when Error.captureStackTrace is available', () => { const originalCaptureStackTrace = Error.captureStackTrace; const mockCaptureStackTrace = vi.fn(); Error.captureStackTrace = mockCaptureStackTrace; const error = new ValidationServiceError('Test message'); expect(mockCaptureStackTrace).toHaveBeenCalledWith(error, ValidationServiceError); // Restore original Error.captureStackTrace = originalCaptureStackTrace; }); it('should handle missing Error.captureStackTrace gracefully', () => { const originalCaptureStackTrace = Error.captureStackTrace; // @ts-ignore - testing edge case delete Error.captureStackTrace; expect(() => { new ValidationServiceError('Test message'); }).not.toThrow(); // Restore original Error.captureStackTrace = originalCaptureStackTrace; }); }); describe('jsonParseError factory', () => { it('should create error for JSON parsing failure', () => { const cause = new SyntaxError('Unexpected token'); const error = ValidationServiceError.jsonParseError('nodes-base.slack', cause); expect(error.name).toBe('ValidationServiceError'); expect(error.message).toBe('Failed to parse JSON data for node nodes-base.slack'); expect(error.nodeType).toBe('nodes-base.slack'); expect(error.property).toBeUndefined(); expect(error.cause).toBe(cause); }); it('should handle different error types as cause', () => { const cause = new TypeError('Cannot read property'); const error = ValidationServiceError.jsonParseError('nodes-base.webhook', cause); expect(error.cause).toBe(cause); expect(error.message).toContain('nodes-base.webhook'); }); it('should work with Error instances', () => { const cause = new Error('Generic parsing error'); const error = ValidationServiceError.jsonParseError('nodes-base.httpRequest', cause); expect(error.cause).toBe(cause); expect(error.nodeType).toBe('nodes-base.httpRequest'); }); }); describe('nodeNotFound factory', () => { it('should create error for missing node type', () => { const error = ValidationServiceError.nodeNotFound('nodes-base.nonexistent'); expect(error.name).toBe('ValidationServiceError'); expect(error.message).toBe('Node type nodes-base.nonexistent not found in repository'); expect(error.nodeType).toBe('nodes-base.nonexistent'); expect(error.property).toBeUndefined(); expect(error.cause).toBeUndefined(); }); it('should work with various node type formats', () => { const nodeTypes = [ 'nodes-base.slack', '@n8n/n8n-nodes-langchain.chatOpenAI', 'custom-node', '' ]; nodeTypes.forEach(nodeType => { const error = ValidationServiceError.nodeNotFound(nodeType); expect(error.nodeType).toBe(nodeType); expect(error.message).toBe(`Node type ${nodeType} not found in repository`); }); }); }); describe('dataExtractionError factory', () => { it('should create error for data extraction failure with cause', () => { const cause = new Error('Database connection failed'); const error = ValidationServiceError.dataExtractionError( 'nodes-base.postgres', 'operations', cause ); expect(error.name).toBe('ValidationServiceError'); expect(error.message).toBe('Failed to extract operations for node nodes-base.postgres'); expect(error.nodeType).toBe('nodes-base.postgres'); expect(error.property).toBe('operations'); expect(error.cause).toBe(cause); }); it('should create error for data extraction failure without cause', () => { const error = ValidationServiceError.dataExtractionError( 'nodes-base.googleSheets', 'resources' ); expect(error.name).toBe('ValidationServiceError'); expect(error.message).toBe('Failed to extract resources for node nodes-base.googleSheets'); expect(error.nodeType).toBe('nodes-base.googleSheets'); expect(error.property).toBe('resources'); expect(error.cause).toBeUndefined(); }); it('should handle various data types', () => { const dataTypes = ['operations', 'resources', 'properties', 'credentials', 'schema']; dataTypes.forEach(dataType => { const error = ValidationServiceError.dataExtractionError( 'nodes-base.test', dataType ); expect(error.property).toBe(dataType); expect(error.message).toBe(`Failed to extract ${dataType} for node nodes-base.test`); }); }); it('should handle empty strings and special characters', () => { const error = ValidationServiceError.dataExtractionError( 'nodes-base.test-node', 'special/property:name' ); expect(error.property).toBe('special/property:name'); expect(error.message).toBe('Failed to extract special/property:name for node nodes-base.test-node'); }); }); describe('error properties and serialization', () => { it('should maintain all properties when stringified', () => { const cause = new Error('Root cause'); const error = ValidationServiceError.dataExtractionError( 'nodes-base.mysql', 'tables', cause ); // JSON.stringify doesn't include message by default for Error objects const serialized = { name: error.name, message: error.message, nodeType: error.nodeType, property: error.property }; expect(serialized.name).toBe('ValidationServiceError'); expect(serialized.message).toBe('Failed to extract tables for node nodes-base.mysql'); expect(serialized.nodeType).toBe('nodes-base.mysql'); expect(serialized.property).toBe('tables'); }); it('should work with toString method', () => { const error = ValidationServiceError.nodeNotFound('nodes-base.missing'); const string = error.toString(); expect(string).toBe('ValidationServiceError: Node type nodes-base.missing not found in repository'); }); it('should preserve stack trace', () => { const error = new ValidationServiceError('Test error'); expect(error.stack).toBeDefined(); expect(error.stack).toContain('ValidationServiceError'); }); }); describe('error chaining and nested causes', () => { it('should handle nested error causes', () => { const rootCause = new Error('Database unavailable'); const intermediateCause = new ValidationServiceError('Connection failed', 'nodes-base.db', undefined, rootCause); const finalError = ValidationServiceError.jsonParseError('nodes-base.slack', intermediateCause); expect(finalError.cause).toBe(intermediateCause); expect((finalError.cause as ValidationServiceError).cause).toBe(rootCause); }); it('should work with different error types in chain', () => { const syntaxError = new SyntaxError('Invalid JSON'); const typeError = new TypeError('Property access failed'); const validationError = ValidationServiceError.dataExtractionError('nodes-base.test', 'props', syntaxError); const finalError = ValidationServiceError.jsonParseError('nodes-base.final', typeError); expect(validationError.cause).toBe(syntaxError); expect(finalError.cause).toBe(typeError); }); }); describe('edge cases and boundary conditions', () => { it('should handle undefined and null values gracefully', () => { // @ts-ignore - testing edge case const error1 = new ValidationServiceError(undefined); // @ts-ignore - testing edge case const error2 = new ValidationServiceError(null); // Test that constructor handles these values without throwing expect(error1).toBeInstanceOf(ValidationServiceError); expect(error2).toBeInstanceOf(ValidationServiceError); expect(error1.name).toBe('ValidationServiceError'); expect(error2.name).toBe('ValidationServiceError'); }); it('should handle very long messages', () => { const longMessage = 'a'.repeat(10000); const error = new ValidationServiceError(longMessage); expect(error.message).toBe(longMessage); expect(error.message.length).toBe(10000); }); it('should handle special characters in node types', () => { const nodeType = 'nodes-base.test-node@1.0.0/special:version'; const error = ValidationServiceError.nodeNotFound(nodeType); expect(error.nodeType).toBe(nodeType); expect(error.message).toContain(nodeType); }); it('should handle circular references in cause chain safely', () => { const error1 = new ValidationServiceError('Error 1'); const error2 = new ValidationServiceError('Error 2', 'test', 'prop', error1); // Don't actually create circular reference as it would break JSON.stringify // Just verify the structure is set up correctly expect(error2.cause).toBe(error1); expect(error1.cause).toBeUndefined(); }); }); describe('factory method edge cases', () => { it('should handle empty strings in factory methods', () => { const jsonError = ValidationServiceError.jsonParseError('', new Error('')); const notFoundError = ValidationServiceError.nodeNotFound(''); const extractionError = ValidationServiceError.dataExtractionError('', ''); expect(jsonError.nodeType).toBe(''); expect(notFoundError.nodeType).toBe(''); expect(extractionError.nodeType).toBe(''); expect(extractionError.property).toBe(''); }); it('should handle null-like values in cause parameter', () => { // @ts-ignore - testing edge case const error1 = ValidationServiceError.jsonParseError('test', null); // @ts-ignore - testing edge case const error2 = ValidationServiceError.dataExtractionError('test', 'prop', undefined); expect(error1.cause).toBe(null); expect(error2.cause).toBeUndefined(); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/88-888/n8n-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server