@@ -7,7 +7,7 @@ import { getWADExecutablePath } from './installer';
77import { waitForCondition } from 'asyncbox' ;
88import { execSync } from 'child_process' ;
99import { util } from 'appium/support' ;
10- import { findAPortNotInUse } from 'portscanner' ;
10+ import { findAPortNotInUse , checkPortStatus } from 'portscanner' ;
1111
1212
1313const 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
2526class 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 ( / C o n d i t i o n u n m e t / . 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