UNPKG

@boundless-oss/atlas

Version:

Atlas - MCP Server for comprehensive startup project management

162 lines (139 loc) 6.1 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { AtlasServer } from '../server.js'; import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js'; import { Client } from '@modelcontextprotocol/sdk/client/index.js'; // Mock the dashboard server module to prevent database initialization vi.mock('../web-dashboard/server.js', () => ({ DashboardServer: vi.fn().mockImplementation(() => ({ start: vi.fn().mockResolvedValue(undefined), stop: vi.fn().mockResolvedValue(undefined), getUrl: vi.fn().mockReturnValue('http://localhost:3001'), isHealthy: vi.fn().mockReturnValue(true), getConfig: vi.fn().mockReturnValue({ enabled: false, port: 3001, host: 'localhost' }) })) })); // Mock the SQLite manager to prevent database initialization vi.mock('../storage/sqlite-manager.js', () => ({ getSQLiteManager: vi.fn(() => ({ initialize: vi.fn().mockResolvedValue(true), close: vi.fn().mockResolvedValue(true), query: vi.fn().mockResolvedValue({ success: true, data: [] }), get: vi.fn().mockResolvedValue({ success: true, data: null }), run: vi.fn().mockResolvedValue({ success: true, data: { changes: 1 } }) })), ensureDatabaseReady: vi.fn().mockResolvedValue({ getConnectionInfo: () => ({ isInitialized: true, dbPath: ':memory:' }) }), SQLiteManager: vi.fn() })); // Mock data migration vi.mock('../storage/data-migration.js', () => ({ autoMigrateOnStartup: vi.fn().mockResolvedValue(undefined) })); describe('AtlasServer', () => { let server: AtlasServer; let client: Client; let serverTransport: InMemoryTransport; let clientTransport: InMemoryTransport; beforeEach(async () => { // Set NODE_ENV to test to ensure test configuration is used process.env.NODE_ENV = 'test'; process.env.ATLAS_DASHBOARD_ENABLED = 'false'; // Disable dashboard in tests server = new AtlasServer(); // Initialize server (this will register modules) await (server as any).initialize(); // Create in-memory transports for testing const transports = InMemoryTransport.createLinkedPair(); serverTransport = transports[0]; clientTransport = transports[1]; // Connect server with in-memory transport instead of stdio const serverReady = (server as any).server.connect(serverTransport); // Connect client client = new Client({ name: 'test-client', version: '1.0.0', }, { capabilities: {}, }); const clientReady = client.connect(clientTransport); // Wait for both to be ready await Promise.all([serverReady, clientReady]); }); afterEach(async () => { await client.close(); await (server as any).server.close(); }); describe('Initialization', () => { it('should create server with correct name and version', async () => { // Check that the server was created expect(server).toBeDefined(); expect((server as any).server).toBeDefined(); }); it('should register required capabilities', async () => { // Capabilities are registered when modules are loaded expect((server as any).server).toBeDefined(); // The actual capability check would be done through client requests }); }); describe('Tool Registration', () => { it('should register core tools', async () => { const response = await client.listTools(); expect(response.tools).toBeDefined(); expect(response.tools.length).toBeGreaterThan(0); // Check for specific tools from migrated modules const toolNames = response.tools.map((t: any) => t.name); // Tools are namespaced with module names expect(toolNames).toContain('kanban--create_kanban_board'); expect(toolNames).toContain('kanban--create_kanban_task'); expect(toolNames).toContain('workspace--create_workspace'); expect(toolNames).toContain('development--create_feature'); expect(toolNames).toContain('agile-management--create_user_story'); }); }); describe('Resource Registration', () => { it('should register core resources', async () => { const response = await client.listResources(); expect(response.resources).toBeDefined(); expect(response.resources.length).toBeGreaterThan(0); // Check for specific resources const resourceUris = response.resources.map((r: any) => r.uri); expect(resourceUris).toContain('atlas://dashboard'); expect(resourceUris).toContain('atlas://database/stats'); expect(resourceUris).toContain('atlas://tools/manifest'); }); }); describe('Prompt Registration', () => { it('should not register prompts in this architecture', async () => { // The 12-factor architecture doesn't use prompts // This is handled by the tool-based approach instead expect(true).toBe(true); }); }); describe('Module Integration', () => { it('should integrate kanban module tools', async () => { const response = await client.listTools(); // Check for kanban-specific tools const toolNames = response.tools.map((t: any) => t.name); expect(toolNames).toContain('kanban--create_kanban_board'); expect(toolNames).toContain('kanban--move_kanban_task'); }); it('should integrate development module tools', async () => { const response = await client.listTools(); // Check for development-specific tools const toolNames = response.tools.map((t: any) => t.name); expect(toolNames).toContain('development--create_feature'); // from development module expect(toolNames).toContain('developer-workflow--start_feature'); // from developer-workflow module expect(toolNames).toContain('development--write_test'); // from development module expect(toolNames).toContain('development--run_tests'); // from development module expect(toolNames).toContain('development--enforce_tdd'); // from development module }); }); });