Skip to content

Commit 25ca840

Browse files
committed
add unit test for good server
1 parent b377251 commit 25ca840

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { spawn, ChildProcess } from 'child_process';
2+
import { listClientScenarios, getClientScenario } from '../index.js';
3+
import path from 'path';
4+
5+
describe('Server Scenarios', () => {
6+
let serverProcess: ChildProcess;
7+
const TEST_PORT = 3001;
8+
const SERVER_URL = `http://localhost:${TEST_PORT}/mcp`;
9+
const SERVER_STARTUP_TIMEOUT = 10000; // 10 seconds to start
10+
11+
beforeAll(async () => {
12+
// Start the everything-server once for all scenarios
13+
const serverPath = path.join(process.cwd(), 'examples/servers/typescript/everything-server.ts');
14+
15+
serverProcess = spawn('npx', ['tsx', serverPath], {
16+
env: { ...process.env, PORT: TEST_PORT.toString() },
17+
stdio: ['ignore', 'pipe', 'pipe']
18+
});
19+
20+
// Wait for server to be ready
21+
await new Promise<void>((resolve, reject) => {
22+
const timeout = setTimeout(() => {
23+
reject(new Error(`Server failed to start within ${SERVER_STARTUP_TIMEOUT}ms`));
24+
}, SERVER_STARTUP_TIMEOUT);
25+
26+
serverProcess.stdout?.on('data', data => {
27+
const output = data.toString();
28+
if (output.includes('running on')) {
29+
clearTimeout(timeout);
30+
resolve();
31+
}
32+
});
33+
34+
serverProcess.on('error', error => {
35+
clearTimeout(timeout);
36+
reject(new Error(`Failed to start server: ${error.message}`));
37+
});
38+
39+
serverProcess.on('exit', code => {
40+
if (code !== null && code !== 0) {
41+
clearTimeout(timeout);
42+
reject(new Error(`Server exited prematurely with code ${code}`));
43+
}
44+
});
45+
});
46+
}, SERVER_STARTUP_TIMEOUT + 5000);
47+
48+
afterAll(async () => {
49+
// Stop the server
50+
if (serverProcess) {
51+
serverProcess.kill('SIGTERM');
52+
53+
// Wait for graceful shutdown
54+
await new Promise<void>(resolve => {
55+
const timeoutHandle = setTimeout(() => {
56+
if (!serverProcess.killed) {
57+
serverProcess.kill('SIGKILL');
58+
}
59+
resolve();
60+
}, 5000);
61+
62+
const cleanUp = () => {
63+
clearTimeout(timeoutHandle);
64+
serverProcess.removeListener('exit', cleanUp);
65+
resolve();
66+
};
67+
68+
serverProcess.on('exit', cleanUp);
69+
});
70+
}
71+
});
72+
73+
// Generate individual test for each scenario
74+
const scenarios = listClientScenarios();
75+
76+
for (const scenarioName of scenarios) {
77+
it(`${scenarioName}`, async () => {
78+
const scenario = getClientScenario(scenarioName);
79+
expect(scenario).toBeDefined();
80+
81+
if (!scenario) {
82+
throw new Error(`Scenario ${scenarioName} not found`);
83+
}
84+
85+
const checks = await scenario.run(SERVER_URL);
86+
87+
// Verify checks were returned
88+
expect(checks.length).toBeGreaterThan(0);
89+
90+
// Verify all checks passed
91+
const failures = checks.filter(c => c.status === 'FAILURE');
92+
if (failures.length > 0) {
93+
const failureMessages = failures.map(c => `${c.name}: ${c.errorMessage || c.description}`).join('\n ');
94+
throw new Error(`Scenario failed with checks:\n ${failureMessages}`);
95+
}
96+
97+
// All checks should be SUCCESS
98+
const successes = checks.filter(c => c.status === 'SUCCESS');
99+
expect(successes.length).toBe(checks.length);
100+
}, 10000); // 10 second timeout per scenario
101+
}
102+
});

0 commit comments

Comments
 (0)