Skip to main content
Glama
modern-fixtures.js8.43 kB
import { vi } from 'vitest'; /** * Modern Test Fixtures for New Modular Architecture * * These fixtures are designed to work with: * - Handler-based architecture (DatabaseToolsHandler, etc.) * - Dependency injection * - Proper mocking patterns * - Environment variable handling via vi.resetModules() */ // ============================================================================ // Mock Data // ============================================================================ export const mockData = { databases: [ { database_name: 'TestDB1', database_id: 5, create_date: '2024-01-01T00:00:00.000Z', collation_name: 'SQL_Latin1_General_CP1_CI_AS', state: 'ONLINE' }, { database_name: 'TestDB2', database_id: 6, create_date: '2024-01-02T00:00:00.000Z', collation_name: 'SQL_Latin1_General_CP1_CI_AS', state: 'ONLINE' } ], tables: [ { schema_name: 'dbo', table_name: 'Users', table_type: 'BASE TABLE' }, { schema_name: 'dbo', table_name: 'Orders', table_type: 'BASE TABLE' } ], tableSchema: [ { column_name: 'id', data_type: 'int', is_nullable: 'NO', column_default: null, max_length: null, precision: 10, scale: 0, is_primary_key: 'YES' }, { column_name: 'name', data_type: 'varchar', is_nullable: 'YES', column_default: null, max_length: 100, precision: null, scale: null, is_primary_key: 'NO' } ], tableData: [ { id: 1, name: 'John Doe', email: 'john@example.com' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com' }, { id: 3, name: 'Bob Johnson', email: 'bob@example.com' } ] }; // ============================================================================ // Mock Database Components // ============================================================================ export const createMockRequest = () => ({ query: vi.fn().mockResolvedValue({ recordset: [], recordsets: [[]], rowsAffected: [0] }), timeout: 30000 }); export const createMockPool = (mockRequest = createMockRequest()) => ({ request: vi.fn(() => mockRequest), connected: true, close: vi.fn().mockResolvedValue() }); export const createMockConnectionManager = (mockPool = createMockPool()) => ({ connect: vi.fn().mockResolvedValue(mockPool), getPool: vi.fn().mockReturnValue(mockPool), isConnectionActive: vi.fn().mockReturnValue(true), close: vi.fn().mockResolvedValue(), getConnectionHealth: vi.fn().mockReturnValue({ connected: true, status: 'Connected', pool: { size: 5, available: 3, pending: 0, borrowed: 2 } }) }); export const createMockPerformanceMonitor = () => ({ recordQuery: vi.fn(), getStats: vi.fn().mockReturnValue({ totalQueries: 100, avgDuration: 150.5, slowQueries: 5, errorRate: 0.02 }), getQueryStats: vi.fn().mockReturnValue([]), getPoolStats: vi.fn().mockReturnValue({ size: 5, available: 3, pending: 0, borrowed: 2 }), reset: vi.fn() }); // ============================================================================ // Environment Setup Utilities // ============================================================================ const originalEnv = process.env; export const createTestEnvironment = (customEnv = {}) => ({ ...originalEnv, SQL_SERVER_HOST: 'localhost', SQL_SERVER_PORT: '1433', SQL_SERVER_DATABASE: 'master', SQL_SERVER_USER: 'testuser', SQL_SERVER_PASSWORD: 'testpass', NODE_ENV: 'test', ...customEnv }); export const setupEnvironment = (customEnv = {}) => { process.env = createTestEnvironment(customEnv); }; export const resetEnvironment = () => { process.env = originalEnv; }; // ============================================================================ // Modern Server Creation Utilities // ============================================================================ /** * Creates a properly mocked SqlServerMCP instance for testing * Uses the new architecture with dependency injection */ export const createMockMcpServer = async (envOverrides = {}, mocks = {}) => { // Set up environment setupEnvironment(envOverrides); // Clear module cache to pick up new environment variables vi.resetModules(); // Default mocks const mockConnectionManager = mocks.connectionManager || createMockConnectionManager(); const mockPerformanceMonitor = mocks.performanceMonitor || createMockPerformanceMonitor(); // Mock the dependencies vi.doMock('../../lib/database/connection-manager.js', () => ({ ConnectionManager: vi.fn().mockImplementation(() => mockConnectionManager) })); vi.doMock('../../lib/utils/performance-monitor.js', () => ({ PerformanceMonitor: vi.fn().mockImplementation(() => mockPerformanceMonitor) })); // Import after mocking const { SqlServerMCP } = await import('../../index.js'); const { serverConfig } = await import('../../lib/config/server-config.js'); // Reload config to pick up environment changes serverConfig.reload(); // Mock tool handlers setup to prevent actual MCP initialization vi.spyOn(SqlServerMCP.prototype, 'setupToolHandlers').mockImplementation(() => {}); vi.spyOn(serverConfig, 'logConfiguration').mockImplementation(() => {}); const server = new SqlServerMCP(); // Expose mocks for testing server.__mocks = { connectionManager: mockConnectionManager, performanceMonitor: mockPerformanceMonitor }; return server; }; // ============================================================================ // Handler Testing Utilities // ============================================================================ /** * Creates a mock DatabaseToolsHandler for testing */ export const createMockDatabaseToolsHandler = (mockConnectionManager, mockPerformanceMonitor) => { const { DatabaseToolsHandler } = vi.importActual('../../lib/tools/handlers/database-tools.js'); const handler = new DatabaseToolsHandler(mockConnectionManager, mockPerformanceMonitor); // Override executeQuery for testing handler.executeQuery = vi.fn().mockImplementation(async _query => { return { recordset: mockData.databases }; }); return handler; }; // ============================================================================ // Response Validation Utilities // ============================================================================ // These functions return objects for test files to validate against // They don't use expect() directly to avoid global dependency issues export const expectValidToolResponse = result => { if (!result || !Array.isArray(result) || result.length === 0) { throw new Error('Invalid tool response structure'); } if (!result[0] || result[0].type !== 'text' || !result[0].text) { throw new Error('Invalid tool response content'); } // Validate JSON structure const data = JSON.parse(result[0].text); if (!Object.prototype.hasOwnProperty.call(data, 'success')) { throw new Error('Response missing success property'); } return data; }; export const expectToolSuccess = (result, expectedData = {}) => { const data = expectValidToolResponse(result); if (!data.success) { throw new Error('Expected successful result but got failure'); } // Simple property checking instead of expect.toMatchObject for (const [key, value] of Object.entries(expectedData)) { if (data[key] !== value) { throw new Error(`Expected ${key} to be ${value} but got ${data[key]}`); } } return data; }; export const expectToolError = (result, expectedErrorMessage = null) => { const data = expectValidToolResponse(result); if (data.success) { throw new Error('Expected error result but got success'); } if (!data.error) { throw new Error('Expected error property in failed result'); } if (expectedErrorMessage && !data.error.message.includes(expectedErrorMessage)) { throw new Error( `Expected error message to contain '${expectedErrorMessage}' but got '${data.error.message}'` ); } return data; }; // ============================================================================ // Cleanup Utilities // ============================================================================ export const cleanupMocks = () => { vi.clearAllMocks(); vi.restoreAllMocks(); resetEnvironment(); };

Latest Blog Posts

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/egarcia74/warp-sql-server-mcp'

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