Skip to content

Commit ee93bf0

Browse files
chore: Raise more user-friendly error if WAD server connection fails (#317)
1 parent 4d9fd1c commit ee93bf0

File tree

1 file changed

+44
-8
lines changed

1 file changed

+44
-8
lines changed

lib/winappdriver.js

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { getWADExecutablePath } from './installer';
77
import { waitForCondition } from 'asyncbox';
88
import { execSync } from 'child_process';
99
import { util } from 'appium/support';
10-
import { findAPortNotInUse } from 'portscanner';
10+
import { findAPortNotInUse, checkPortStatus } from 'portscanner';
1111

1212

1313
const DEFAULT_BASE_PATH = '/wd/hub';
@@ -21,11 +21,24 @@ const PORT_ALLOCATION_GUARD = util.getLockFileGuard(path.resolve(os.tmpdir(), 'w
2121
timeout: 5,
2222
tryRecovery: true,
2323
});
24+
const TROUBLESHOOTING_LINK = 'https://github.com/appium/appium-windows-driver?tab=readme-ov-file#troubleshooting';
2425

2526
class WADProxy extends JWProxy {
2627
/** @type {boolean|undefined} */
2728
didProcessExit;
2829

30+
async isListening() {
31+
const url = this.getUrlForProxy('/status');
32+
const parsedUrl = new URL(url);
33+
const defaultPort = parsedUrl.protocol === 'https:' ? 443 : 80;
34+
try {
35+
await checkPortStatus(parseInt(parsedUrl.port, 10) || defaultPort, parsedUrl.hostname);
36+
return true;
37+
} catch {
38+
return false;
39+
}
40+
}
41+
2942
/**
3043
* @override
3144
*/
@@ -183,6 +196,8 @@ export class WinAppDriver {
183196
}
184197
});
185198

199+
/** @type {Error | undefined} */
200+
let lastError;
186201
try {
187202
await waitForCondition(async () => {
188203
try {
@@ -194,20 +209,32 @@ export class WinAppDriver {
194209
if (this.proxy?.didProcessExit) {
195210
throw new Error(err.message);
196211
}
212+
lastError = err;
197213
return false;
198214
}
199215
}, {
200216
waitMs: STARTUP_TIMEOUT_MS,
201217
intervalMs: 1000,
202218
});
203219
} catch (e) {
204-
if (/Condition unmet/.test(e.message)) {
205-
throw new Error(
206-
`WinAppDriver server is not listening within ${STARTUP_TIMEOUT_MS}ms timeout. ` +
207-
`Make sure it could be started manually`
220+
if (!lastError || this.proxy.didProcessExit) {
221+
throw e;
222+
}
223+
224+
const serverUrl = this.proxy.getUrlForProxy('/status');
225+
let errorMessage = (
226+
`WinAppDriver server '${executablePath}' is not listening at ${serverUrl} ` +
227+
`after ${STARTUP_TIMEOUT_MS}ms timeout. Make sure it could be started manually.`
228+
);
229+
if (await this.proxy.isListening()) {
230+
errorMessage = (
231+
`WinAppDriver server '${executablePath}' is listening at ${serverUrl}, ` +
232+
`but fails to respond with a proper status. It is an issue with the server itself. ` +
233+
`Consider checking the troubleshooting guide at ${TROUBLESHOOTING_LINK}. ` +
234+
`Original error: ${(lastError ?? e).message}`
208235
);
209236
}
210-
throw e;
237+
throw new Error(errorMessage);
211238
}
212239
const pid = this.process.proc?.pid;
213240
RUNNING_PROCESS_IDS.push(pid);
@@ -246,11 +273,20 @@ export class WinAppDriver {
246273

247274
try {
248275
await this.proxy.command('/status', 'GET');
249-
} catch {
250-
throw new Error(
276+
} catch (e) {
277+
let errorMessage = (
251278
`WinAppDriver server is not listening at ${url}. ` +
252279
`Make sure it is running and the provided wadUrl is correct`
253280
);
281+
if (await this.proxy.isListening()) {
282+
errorMessage = (
283+
`WinAppDriver server is listening at ${url}, but fails to respond with a proper status. ` +
284+
`It is an issue with the server itself. ` +
285+
`Consider checking the troubleshooting guide at ${TROUBLESHOOTING_LINK}. ` +
286+
`Original error: ${e.message}`
287+
);
288+
}
289+
throw new Error(errorMessage);
254290
}
255291
}
256292

0 commit comments

Comments
 (0)