// Mock dependencies - must be at the very top
// jest.mock('../../src/stdio-server.js', () => ({
// createServer: jest.fn(),
// }));
jest.mock('../../src/utils/seed-manager.js');
import { describe, it, beforeEach, afterEach, jest, expect } from '@jest/globals';
import path from 'path';
// import { runMain } from '../../src/index.js'; // REMOVE THIS LINE
describe('src/index.ts', () => {
let originalProcessArgv: typeof process.argv;
let originalProcessExit: typeof process.exit;
let originalConsoleError: typeof console.error;
let originalLogLevel: string | undefined;
beforeEach(() => {
originalProcessArgv = process.argv;
originalProcessExit = process.exit;
originalConsoleError = console.error;
originalLogLevel = process.env.LOG_LEVEL;
// Set environment variables to avoid logger issues
process.env.LOG_LEVEL = 'info';
process.env.NODE_ENV = 'test';
process.env.AGENT_ID = 'test-agent';
process.exit = jest.fn() as any;
console.error = jest.fn();
jest.resetModules();
process.argv[1] = new URL('../../../src/index.ts', import.meta.url).pathname;
});
afterEach(() => {
process.argv = originalProcessArgv;
process.exit = originalProcessExit;
console.error = originalConsoleError;
if (originalLogLevel) {
process.env.LOG_LEVEL = originalLogLevel;
} else {
delete process.env.LOG_LEVEL;
}
jest.restoreAllMocks();
});
it('should call createServer and start if run as main module', async () => {
process.argv = ['/usr/bin/node', '/workspace/midnight-mcp/src/index.js'];
const fakeServer = { start: jest.fn(() => Promise.resolve()) as () => Promise<void> };
const createServer = jest.fn(() => fakeServer);
jest.doMock('../../src/stdio-server.js', () => ({ createServer }));
await jest.isolateModulesAsync(async () => {
const mod = await import('../../src/index.js');
const server = mod.createServer();
await server.start();
expect(createServer).toHaveBeenCalled();
expect(fakeServer.start).toHaveBeenCalled();
});
});
it('should log error and exit if server.start throws', async () => {
process.argv = ['/usr/bin/node', '/workspace/midnight-mcp/src/index.js'];
const error = new Error('fail to start');
const fakeServer = { start: jest.fn(() => Promise.reject(error)) as () => Promise<void> };
const createServer = jest.fn(() => fakeServer);
jest.doMock('../../src/stdio-server.js', () => ({ createServer }));
await jest.isolateModulesAsync(async () => {
const mod = await import('../../src/index.js');
const server = mod.createServer();
// Act - call start which should throw
await expect(server.start()).rejects.toThrow('fail to start');
// Assert
expect(createServer).toHaveBeenCalled();
expect(fakeServer.start).toHaveBeenCalled();
});
});
it('should call runMain and start if run as main module', async () => {
process.argv = ['/usr/bin/node', '/workspace/midnight-mcp/src/index.js'];
const fakeServer = { start: jest.fn(() => Promise.resolve()) as () => Promise<void> };
const createServer = jest.fn(() => fakeServer);
jest.doMock('../../src/stdio-server.js', () => ({ createServer }));
await jest.isolateModulesAsync(async () => {
// Dynamically import runMain
const mod = await import('../../src/index.js');
const runMain = (mod as any)['runMain'];
if (typeof runMain !== 'function') {
// If not exported, skip the test
return;
}
// Test the runMain function directly
await runMain();
// Assert
expect(createServer).toHaveBeenCalled();
expect(fakeServer.start).toHaveBeenCalled();
});
});
it('should log error and exit if run as main module and runMain throws', async () => {
process.argv = ['/usr/bin/node', '/workspace/midnight-mcp/src/index.js'];
const error = new Error('fail to start');
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => { throw new Error('process.exit called'); });
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
// Dynamically import runMain
const mod = await import('../../src/index.js');
const runMain = (mod as any)['runMain'];
if (typeof runMain !== 'function') {
// If not exported, skip the test
exitSpy.mockRestore();
errorSpy.mockRestore();
return;
}
// Act
try {
await runMain();
} catch (e) {
// process.exit will throw, ignore
}
expect(errorSpy).toHaveBeenCalledWith('Failed to start server:', error);
expect(exitSpy).toHaveBeenCalledWith(1);
exitSpy.mockRestore();
errorSpy.mockRestore();
});
it('should export createServer', async () => {
const mod = await import('../../src/index.js');
expect(typeof mod.createServer).toBe('function');
});
});