/**
* Server Startup E2E Test
*
* Simple test to verify the MCP server can start and stop properly.
*/
import { spawn, ChildProcess } from 'child_process';
import { join } from 'path';
describe('MCP Server Startup', () => {
let serverProcess: ChildProcess | null = null;
const serverPath = join(__dirname, '../../../dist/askme-server/main.js');
afterEach(async () => {
if (serverProcess) {
serverProcess.kill('SIGTERM');
// Wait for process to exit
await new Promise<void>((resolve) => {
const timeout = setTimeout(() => {
if (serverProcess) {
serverProcess.kill('SIGKILL');
}
resolve();
}, 5000);
serverProcess!.once('exit', () => {
clearTimeout(timeout);
resolve();
});
});
serverProcess = null;
}
});
test('should start server successfully', (done) => {
expect(serverPath).toBeTruthy();
// Spawn the server process with unique port
serverProcess = spawn('node', [serverPath, '--port', '8002'], {
stdio: ['pipe', 'pipe', 'pipe'],
env: {
...process.env,
ASK_ME_MCP_DEBUG: '1' // Enable debug logging for tests
}
});
let serverReady = false;
const timeout = setTimeout(() => {
if (!serverReady) {
done(new Error('Server failed to start within 10 seconds'));
}
}, 10000);
// Handle process errors
serverProcess.on('error', (error) => {
clearTimeout(timeout);
done(error);
});
serverProcess.on('exit', (code, signal) => {
if (!serverReady) {
clearTimeout(timeout);
done(new Error(`Server exited early with code ${code}, signal ${signal}`));
}
});
// Check stderr for server ready message
serverProcess.stderr!.on('data', (data) => {
const message = data.toString();
console.log('Server output:', message);
if (message.includes('Server ready for connections')) {
serverReady = true;
clearTimeout(timeout);
done();
} else if (message.includes('Error:') || message.includes('EADDRINUSE')) {
clearTimeout(timeout);
done(new Error(`Server startup error: ${message}`));
}
});
// Send initial data to stdin to test stdio communication
setTimeout(() => {
if (serverProcess && serverProcess.stdin) {
serverProcess.stdin.write('{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}\n');
}
}, 1000);
}, 15000);
test('should handle server shutdown gracefully', (done) => {
// Spawn the server process with unique port
serverProcess = spawn('node', [serverPath, '--port', '8003'], {
stdio: ['pipe', 'pipe', 'pipe'],
env: {
...process.env,
ASK_ME_MCP_DEBUG: '1' // Enable debug logging for tests
}
});
let serverStarted = false;
serverProcess.stderr!.on('data', (data) => {
const message = data.toString();
if (message.includes('Server ready for connections') && !serverStarted) {
serverStarted = true;
// Send SIGTERM to test graceful shutdown
setTimeout(() => {
serverProcess!.kill('SIGTERM');
}, 100);
}
});
serverProcess.on('exit', (code, signal) => {
if (serverStarted) {
// Accept either SIGTERM or normal exit (code 0)
expect(code === 0 || signal === 'SIGTERM').toBe(true);
done();
}
});
setTimeout(() => {
if (!serverStarted) {
done(new Error('Server did not start within timeout'));
}
}, 10000);
}, 15000);
test('should create necessary server artifacts', () => {
const fs = require('fs');
// Check that the built server file exists
expect(fs.existsSync(serverPath)).toBe(true);
// Check that it's executable (has the shebang line)
const content = fs.readFileSync(serverPath, 'utf8');
expect(content).toContain('ask-me-mcp');
});
});