Skip to content

Commit bd1d89d

Browse files
committed
refactor(tests): enhance server startup handling with error catching and retry logic
1 parent 848fcd1 commit bd1d89d

File tree

2 files changed

+86
-54
lines changed

2 files changed

+86
-54
lines changed

packages/android-mcp/tests/http-server.test.ts

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,45 +21,61 @@ describe('AndroidMCPServer HTTP mode', () => {
2121
}) as any);
2222

2323
try {
24-
// Start server in background
24+
// Start server in background and handle potential errors
2525
const serverPromise = server.launchHttp({
2626
port: testPort,
2727
host: testHost,
2828
});
2929

30-
// Give server time to start
31-
await new Promise((resolve) => setTimeout(resolve, 1500));
30+
// Catch any errors from server startup without blocking
31+
serverPromise.catch((error) => {
32+
console.error('Server startup error:', error);
33+
});
3234

33-
// Simply verify the server is listening by trying to connect
34-
const response = await fetch(`http://${testHost}:${testPort}/mcp`, {
35-
method: 'POST',
36-
headers: {
37-
'Content-Type': 'application/json',
38-
},
39-
body: JSON.stringify({
40-
jsonrpc: '2.0',
41-
method: 'initialize',
42-
params: {
43-
protocolVersion: '2024-11-05',
44-
capabilities: {},
45-
clientInfo: {
46-
name: 'test-client',
47-
version: '1.0.0',
35+
// Wait for server to start with retries (up to 5 seconds)
36+
let connected = false;
37+
for (let i = 0; i < 10; i++) {
38+
await new Promise((resolve) => setTimeout(resolve, 500));
39+
try {
40+
const response = await fetch(`http://${testHost}:${testPort}/mcp`, {
41+
method: 'POST',
42+
headers: {
43+
'Content-Type': 'application/json',
4844
},
49-
},
50-
id: 1,
51-
}),
52-
});
45+
body: JSON.stringify({
46+
jsonrpc: '2.0',
47+
method: 'initialize',
48+
params: {
49+
protocolVersion: '2024-11-05',
50+
capabilities: {},
51+
clientInfo: {
52+
name: 'test-client',
53+
version: '1.0.0',
54+
},
55+
},
56+
id: 1,
57+
}),
58+
});
5359

54-
// Server should respond (even if initialization fails without device)
55-
expect(response.status).toBeGreaterThanOrEqual(200);
56-
expect(response.status).toBeLessThan(600);
60+
// Server should respond (even if initialization fails without device)
61+
expect(response.status).toBeGreaterThanOrEqual(200);
62+
expect(response.status).toBeLessThan(600);
63+
connected = true;
64+
console.log(`✓ Android MCP server started and responding (attempt ${i + 1})`);
65+
break;
66+
} catch (error) {
67+
if (i === 9) {
68+
throw error; // Throw on last attempt
69+
}
70+
// Otherwise continue retrying
71+
}
72+
}
5773

58-
console.log('✓ Android MCP server started and responding');
74+
expect(connected).toBe(true);
5975
} finally {
6076
exitSpy.mockRestore();
6177
}
62-
}, 10000);
78+
}, 15000); // Increase timeout for CI
6379

6480
it('should reject invalid port numbers', async () => {
6581
const invalidServer = new AndroidMCPServer();

packages/ios-mcp/tests/http-server.test.ts

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,45 +21,61 @@ describe('IOSMCPServer HTTP mode', () => {
2121
}) as any);
2222

2323
try {
24-
// Start server in background
24+
// Start server in background and handle potential errors
2525
const serverPromise = server.launchHttp({
2626
port: testPort,
2727
host: testHost,
2828
});
2929

30-
// Give server time to start
31-
await new Promise((resolve) => setTimeout(resolve, 1500));
30+
// Catch any errors from server startup without blocking
31+
serverPromise.catch((error) => {
32+
console.error('Server startup error:', error);
33+
});
3234

33-
// Simply verify the server is listening by trying to connect
34-
const response = await fetch(`http://${testHost}:${testPort}/mcp`, {
35-
method: 'POST',
36-
headers: {
37-
'Content-Type': 'application/json',
38-
},
39-
body: JSON.stringify({
40-
jsonrpc: '2.0',
41-
method: 'initialize',
42-
params: {
43-
protocolVersion: '2024-11-05',
44-
capabilities: {},
45-
clientInfo: {
46-
name: 'test-client',
47-
version: '1.0.0',
35+
// Wait for server to start with retries (up to 5 seconds)
36+
let connected = false;
37+
for (let i = 0; i < 10; i++) {
38+
await new Promise((resolve) => setTimeout(resolve, 500));
39+
try {
40+
const response = await fetch(`http://${testHost}:${testPort}/mcp`, {
41+
method: 'POST',
42+
headers: {
43+
'Content-Type': 'application/json',
4844
},
49-
},
50-
id: 1,
51-
}),
52-
});
45+
body: JSON.stringify({
46+
jsonrpc: '2.0',
47+
method: 'initialize',
48+
params: {
49+
protocolVersion: '2024-11-05',
50+
capabilities: {},
51+
clientInfo: {
52+
name: 'test-client',
53+
version: '1.0.0',
54+
},
55+
},
56+
id: 1,
57+
}),
58+
});
5359

54-
// Server should respond (even if initialization fails without device)
55-
expect(response.status).toBeGreaterThanOrEqual(200);
56-
expect(response.status).toBeLessThan(600);
60+
// Server should respond (even if initialization fails without device)
61+
expect(response.status).toBeGreaterThanOrEqual(200);
62+
expect(response.status).toBeLessThan(600);
63+
connected = true;
64+
console.log(`✓ iOS MCP server started and responding (attempt ${i + 1})`);
65+
break;
66+
} catch (error) {
67+
if (i === 9) {
68+
throw error; // Throw on last attempt
69+
}
70+
// Otherwise continue retrying
71+
}
72+
}
5773

58-
console.log('✓ iOS MCP server started and responding');
74+
expect(connected).toBe(true);
5975
} finally {
6076
exitSpy.mockRestore();
6177
}
62-
}, 10000);
78+
}, 15000); // Increase timeout for CI
6379

6480
it('should reject invalid port numbers', async () => {
6581
const invalidServer = new IOSMCPServer();

0 commit comments

Comments
 (0)