@@ -5,9 +5,18 @@ import { JWProxy } from '@appium/base-driver';
55import type { PortForwardCallback , PortReleaseCallback } from './types' ;
66import type { AppiumFlutterDriver } from './driver' ;
77import _ from 'lodash' ;
8+ import type { StringRecord } from '@appium/types' ;
9+ import { node } from 'appium/support' ;
10+ import path from 'node:path' ;
11+ import fs from 'node:fs' ;
12+ import semver from 'semver' ;
813
914const DEVICE_PORT_RANGE = [ 9000 , 9020 ] ;
1015const SYSTEM_PORT_RANGE = [ 10000 , 11000 ] ;
16+ const {
17+ appium : { flutterServerVersion : FLUTTER_SERVER_VERSION_REQ } ,
18+ version : PACKAGE_VERSION ,
19+ } = readManifest ( ) ;
1120
1221export async function getProxyDriver (
1322 this : AppiumFlutterDriver ,
@@ -61,27 +70,16 @@ export async function waitForFlutterServerToBeActive(
6170) : Promise < void > {
6271 await waitForCondition (
6372 async ( ) => {
73+ let response : unknown ;
6474 try {
65- const response : any = await proxy . command ( '/status' , 'GET' ) ;
66- if ( ! response ) {
67- return false ;
68- }
69- if ( response ?. appInfo ?. packageName === packageName ) {
70- this . log . info (
71- `Flutter server version the application is build with ${ response . serverVersion } ` ,
72- ) ;
73- return true ;
74- } else {
75- this . log . error (
76- `Looking for flutter server with package ${ packageName } . But found ${ response . appInfo ?. packageName } ` ,
77- ) ;
78- }
75+ response = await proxy . command ( '/status' , 'GET' ) ;
7976 } catch ( err : any ) {
8077 this . log . info (
8178 `FlutterServer not reachable on port ${ flutterPort } , Retrying..` ,
8279 ) ;
8380 return false ;
8481 }
82+ return validateServerStatus . bind ( this ) ( response , packageName ) ;
8583 } ,
8684 {
8785 waitMs : this . opts . flutterServerLaunchTimeout ?? 5000 ,
@@ -240,8 +238,73 @@ export function attachAppLaunchArguments(
240238 ] ) ;
241239
242240 this . log . info (
243- `iOS platform detected and flutterSystemPort capability is present.
241+ `iOS platform detected and flutterSystemPort capability is present.
244242 So attaching processArguments: ${ JSON . stringify ( capsToUpdate [ 'appium:processArguments' ] ) } ` ,
245243 ) ;
246244 }
247245}
246+
247+ function validateServerStatus (
248+ this : AppiumFlutterDriver ,
249+ status : unknown ,
250+ packageName : string ,
251+ ) : boolean {
252+ const compatibilityMessage =
253+ `Please check the driver readme to ensure the compatibility ` +
254+ `between the server module integrated into the application under test ` +
255+ `and the current driver version ${ PACKAGE_VERSION } .` ;
256+ const formattedStatus = _ . truncate ( JSON . stringify ( status ) , { length : 200 } ) ;
257+ const logAndThrow = ( errMsg : string ) => {
258+ this . log . info ( errMsg ) ;
259+ throw new Error ( errMsg ) ;
260+ } ;
261+ if ( ! _ . isPlainObject ( status ) ) {
262+ logAndThrow (
263+ `The server response ${ formattedStatus } ` +
264+ `is not a valid object. ${ compatibilityMessage } ` ,
265+ ) ;
266+ }
267+ const statusMap = status as StringRecord ;
268+ if ( ! statusMap . appInfo || ! statusMap . appInfo ?. packageName ) {
269+ logAndThrow (
270+ `The server response ${ formattedStatus } ` +
271+ `does not contain a package name. ${ compatibilityMessage } ` ,
272+ ) ;
273+ }
274+ if ( statusMap . appInfo . packageName !== packageName ) {
275+ logAndThrow (
276+ `The server response ` +
277+ `contains an unexpected package name (${ statusMap . appInfo . packageName } != ${ packageName } ). ` +
278+ `Does this server belong to another app?` ,
279+ ) ;
280+ }
281+ if ( ! statusMap . serverVersion ) {
282+ logAndThrow (
283+ `The server response ${ formattedStatus } ` +
284+ `does not contain a valid server version. ${ compatibilityMessage } ` ,
285+ ) ;
286+ }
287+ if ( ! semver . satisfies ( statusMap . serverVersion , FLUTTER_SERVER_VERSION_REQ ) ) {
288+ logAndThrow (
289+ `The server version ${ statusMap . serverVersion } does not satisfy the driver ` +
290+ `version requirement '${ FLUTTER_SERVER_VERSION_REQ } '. ` +
291+ compatibilityMessage ,
292+ ) ;
293+ }
294+ return true ;
295+ }
296+
297+ function readManifest ( ) : StringRecord {
298+ return JSON . parse (
299+ fs . readFileSync (
300+ path . join (
301+ node . getModuleRootSync (
302+ 'appium-flutter-integration-driver' ,
303+ __filename ,
304+ ) ! ,
305+ 'package.json' ,
306+ ) ,
307+ { encoding : 'utf8' } ,
308+ ) ,
309+ ) ;
310+ }
0 commit comments