/**
* MCP Server with Custom Port E2E Test
*
* Tests the MCP server with configurable port functionality.
*/
import { spawn, ChildProcess } from 'child_process';
import { join } from 'path';
describe('MCP Server with Custom Port', () => {
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 with default port (unique test)', (done) => {
// Use a unique port instead of default 3000 to avoid conflicts
serverProcess = spawn('node', [serverPath, '--port', '8004'], {
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);
serverProcess.stderr!.on('data', (data) => {
const message = data.toString();
console.log('Server output:', message);
if (message.includes('Browser bridge listening on http://localhost:8004')) {
expect(message).toContain('8004'); // Test port
clearTimeout(timeout);
serverReady = true;
done();
} else if (message.includes('EADDRINUSE')) {
clearTimeout(timeout);
done(new Error('Port 8004 already in use'));
}
});
serverProcess.on('error', (error) => {
clearTimeout(timeout);
done(error);
});
}, 15000);
test('should start server with custom port --port 8005', (done) => {
serverProcess = spawn('node', [serverPath, '--port', '8005'], {
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);
serverProcess.stderr!.on('data', (data) => {
const message = data.toString();
console.log('Server output:', message);
if (message.includes('Browser bridge listening on http://localhost:8005')) {
expect(message).toContain('8005'); // Custom port
clearTimeout(timeout);
serverReady = true;
done();
} else if (message.includes('EADDRINUSE')) {
clearTimeout(timeout);
done(new Error('Port 8005 already in use'));
}
});
serverProcess.on('error', (error) => {
clearTimeout(timeout);
done(error);
});
}, 15000);
test('should start server with short flag -p 8006', (done) => {
serverProcess = spawn('node', [serverPath, '-p', '8006'], {
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);
serverProcess.stderr!.on('data', (data) => {
const message = data.toString();
console.log('Server output:', message);
if (message.includes('Browser bridge listening on http://localhost:8006')) {
expect(message).toContain('8006'); // Custom port with short flag
clearTimeout(timeout);
serverReady = true;
done();
} else if (message.includes('EADDRINUSE')) {
clearTimeout(timeout);
done(new Error('Port 8006 already in use'));
}
});
serverProcess.on('error', (error) => {
clearTimeout(timeout);
done(error);
});
}, 15000);
test('should show help with --help flag', (done) => {
serverProcess = spawn('node', [serverPath, '--help'], {
stdio: ['pipe', 'pipe', 'pipe'],
env: {
...process.env,
ASK_ME_MCP_DEBUG: '1' // Enable debug logging for tests
}
});
let helpShown = false;
const timeout = setTimeout(() => {
if (!helpShown) {
done(new Error('Help message not shown within 5 seconds'));
}
}, 5000);
serverProcess.stderr!.on('data', (data) => {
const message = data.toString();
console.log('Help output:', message);
if (message.includes('Ask-Me MCP Server') && message.includes('Usage:')) {
expect(message).toContain('--port');
expect(message).toContain('--help');
expect(message).toContain('Examples:');
clearTimeout(timeout);
helpShown = true;
done();
}
});
serverProcess.on('exit', (code) => {
if (!helpShown && code === 0) {
clearTimeout(timeout);
helpShown = true;
done();
}
});
serverProcess.on('error', (error) => {
clearTimeout(timeout);
done(error);
});
}, 10000);
test('should show error with invalid port', (done) => {
serverProcess = spawn('node', [serverPath, '--port', 'invalid'], {
stdio: ['pipe', 'pipe', 'pipe'],
env: {
...process.env,
ASK_ME_MCP_DEBUG: '1' // Enable debug logging for tests
}
});
let errorShown = false;
const timeout = setTimeout(() => {
if (!errorShown) {
done(new Error('Error message not shown within 5 seconds'));
}
}, 5000);
serverProcess.stderr!.on('data', (data) => {
const message = data.toString();
console.log('Error output:', message);
if (message.includes('Error: --port requires a valid port number')) {
clearTimeout(timeout);
errorShown = true;
done();
}
});
serverProcess.on('exit', (code) => {
if (!errorShown && code === 1) {
clearTimeout(timeout);
errorShown = true;
done();
}
});
serverProcess.on('error', (error) => {
clearTimeout(timeout);
done(error);
});
}, 10000);
test('should show error with port out of range', (done) => {
serverProcess = spawn('node', [serverPath, '--port', '70000'], {
stdio: ['pipe', 'pipe', 'pipe'],
env: {
...process.env,
ASK_ME_MCP_DEBUG: '1' // Enable debug logging for tests
}
});
let errorShown = false;
const timeout = setTimeout(() => {
if (!errorShown) {
done(new Error('Error message not shown within 5 seconds'));
}
}, 5000);
serverProcess.stderr!.on('data', (data) => {
const message = data.toString();
console.log('Error output:', message);
if (message.includes('Error: Port must be between 1 and 65535')) {
clearTimeout(timeout);
errorShown = true;
done();
}
});
serverProcess.on('exit', (code) => {
if (!errorShown && code === 1) {
clearTimeout(timeout);
errorShown = true;
done();
}
});
serverProcess.on('error', (error) => {
clearTimeout(timeout);
done(error);
});
}, 10000);
test('should show error with unknown argument', (done) => {
serverProcess = spawn('node', [serverPath, '--unknown'], {
stdio: ['pipe', 'pipe', 'pipe'],
env: {
...process.env,
ASK_ME_MCP_DEBUG: '1' // Enable debug logging for tests
}
});
let errorShown = false;
const timeout = setTimeout(() => {
if (!errorShown) {
done(new Error('Error message not shown within 5 seconds'));
}
}, 5000);
serverProcess.stderr!.on('data', (data) => {
const message = data.toString();
console.log('Error output:', message);
if (message.includes('Error: Unknown argument: --unknown')) {
clearTimeout(timeout);
errorShown = true;
done();
}
});
serverProcess.on('exit', (code) => {
if (!errorShown && code === 1) {
clearTimeout(timeout);
errorShown = true;
done();
}
});
serverProcess.on('error', (error) => {
clearTimeout(timeout);
done(error);
});
}, 10000);
});