Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 44 additions & 8 deletions lib/winappdriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getWADExecutablePath } from './installer';
import { waitForCondition } from 'asyncbox';
import { execSync } from 'child_process';
import { util } from 'appium/support';
import { findAPortNotInUse } from 'portscanner';
import { findAPortNotInUse, checkPortStatus } from 'portscanner';


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

class WADProxy extends JWProxy {
/** @type {boolean|undefined} */
didProcessExit;

async isListening() {
const url = this.getUrlForProxy('/status');
const parsedUrl = new URL(url);
const defaultPort = parsedUrl.protocol === 'https:' ? 443 : 80;
try {
await checkPortStatus(parseInt(parsedUrl.port, 10) || defaultPort, parsedUrl.hostname);
return true;
} catch {
return false;
}
}

/**
* @override
*/
Expand Down Expand Up @@ -183,6 +196,8 @@ export class WinAppDriver {
}
});

/** @type {Error | undefined} */
let lastError;
try {
await waitForCondition(async () => {
try {
Expand All @@ -194,20 +209,32 @@ export class WinAppDriver {
if (this.proxy?.didProcessExit) {
throw new Error(err.message);
}
lastError = err;
return false;
}
}, {
waitMs: STARTUP_TIMEOUT_MS,
intervalMs: 1000,
});
} catch (e) {
if (/Condition unmet/.test(e.message)) {
throw new Error(
`WinAppDriver server is not listening within ${STARTUP_TIMEOUT_MS}ms timeout. ` +
`Make sure it could be started manually`
if (!lastError || this.proxy.didProcessExit) {
throw e;
}

const serverUrl = this.proxy.getUrlForProxy('/status');
let errorMessage = (
`WinAppDriver server '${executablePath}' is not listening at ${serverUrl} ` +
`after ${STARTUP_TIMEOUT_MS}ms timeout. Make sure it could be started manually.`
);
if (await this.proxy.isListening()) {
errorMessage = (
`WinAppDriver server '${executablePath}' is listening at ${serverUrl}, ` +
`but fails to respond with a proper status. It is an issue with the server itself. ` +
`Consider checking the troubleshooting guide at ${TROUBLESHOOTING_LINK}. ` +
`Original error: ${(lastError ?? e).message}`
);
}
throw e;
throw new Error(errorMessage);
}
const pid = this.process.proc?.pid;
RUNNING_PROCESS_IDS.push(pid);
Expand Down Expand Up @@ -246,11 +273,20 @@ export class WinAppDriver {

try {
await this.proxy.command('/status', 'GET');
} catch {
throw new Error(
} catch (e) {
let errorMessage = (
`WinAppDriver server is not listening at ${url}. ` +
`Make sure it is running and the provided wadUrl is correct`
);
if (await this.proxy.isListening()) {
errorMessage = (
`WinAppDriver server is listening at ${url}, but fails to respond with a proper status. ` +
`It is an issue with the server itself. ` +
`Consider checking the troubleshooting guide at ${TROUBLESHOOTING_LINK}. ` +
`Original error: ${e.message}`
);
}
throw new Error(errorMessage);
}
}

Expand Down