@@ -15,24 +15,24 @@ export interface IPlatform {
15
15
* Gets the Cordova specific platform name. (e.g. "android" for the Android platform).
16
16
*/
17
17
getCordovaName ( ) : string ;
18
-
18
+
19
19
/**
20
20
* Gets the server url used for testing.
21
21
*/
22
22
getServerUrl ( ) : string ;
23
-
23
+
24
24
/**
25
25
* Gets the root of the platform www folder used for creating update packages.
26
26
*/
27
27
getPlatformWwwPath ( projectDirectory : string ) : string ;
28
-
28
+
29
29
/**
30
30
* Gets an optional IEmulatorManager for platforms for which "cordova run --nobuild" rebuilds the application for this platform anyway.
31
31
* IOS needs special handling here, since ios-sim touches the app every time and changes the app timestamp.
32
32
* This challenges the tests since we rely on the app timestamp in our logic for finding out if the application was updated through the app store.
33
33
*/
34
34
getEmulatorManager ( ) : IEmulatorManager ;
35
-
35
+
36
36
/**
37
37
* Gets the default deployment key.
38
38
*/
@@ -47,32 +47,32 @@ export interface IEmulatorManager {
47
47
* Boots the target emulator.
48
48
*/
49
49
bootEmulator ( restartEmulators : boolean ) : Q . Promise < string > ;
50
-
50
+
51
51
/**
52
52
* Launches an already installed application by app id.
53
53
*/
54
54
launchInstalledApplication ( appId : string ) : Q . Promise < string > ;
55
-
55
+
56
56
/**
57
57
* Ends a running application given its app id.
58
58
*/
59
59
endRunningApplication ( appId : string ) : Q . Promise < string > ;
60
-
60
+
61
61
/**
62
62
* Restarts an already installed application by app id.
63
63
*/
64
64
restartApplication ( appId : string ) : Q . Promise < string > ;
65
-
65
+
66
66
/**
67
67
* Navigates away from the current app, waits for a delay (defaults to 1 second), then navigates to the specified app.
68
68
*/
69
69
resumeApplication ( appId : string , delayBeforeResumingMs : number ) : Q . Promise < string > ;
70
-
70
+
71
71
/**
72
72
* Prepares the emulator for a test.
73
73
*/
74
74
prepareEmulatorForTest ( appId : string ) : Q . Promise < string > ;
75
-
75
+
76
76
/**
77
77
* Uninstalls the app from the emulator.
78
78
*/
@@ -86,7 +86,7 @@ export class Android implements IPlatform {
86
86
private static instance : Android ;
87
87
private emulatorManager : IEmulatorManager ;
88
88
private serverUrl : string ;
89
-
89
+
90
90
constructor ( emulatorManager : IEmulatorManager ) {
91
91
this . emulatorManager = emulatorManager ;
92
92
}
@@ -102,7 +102,7 @@ export class Android implements IPlatform {
102
102
public getCordovaName ( ) : string {
103
103
return "android" ;
104
104
}
105
-
105
+
106
106
/**
107
107
* Gets the server url used for testing.
108
108
*/
@@ -112,7 +112,7 @@ export class Android implements IPlatform {
112
112
}
113
113
114
114
public getPlatformWwwPath ( projectDirectory : string ) : string {
115
- return path . join ( projectDirectory , "platforms/android/assets/www" ) ;
115
+ return path . join ( projectDirectory , "platforms/android/app/src/main/ assets/www" ) ;
116
116
}
117
117
118
118
public getEmulatorManager ( ) : IEmulatorManager {
@@ -147,7 +147,7 @@ export class IOS implements IPlatform {
147
147
public getCordovaName ( ) : string {
148
148
return "ios" ;
149
149
}
150
-
150
+
151
151
/**
152
152
* Gets the server url used for testing.
153
153
*/
@@ -177,7 +177,7 @@ function bootEmulatorInternal(platformName: string, restartEmulators: boolean, t
177
177
checkEmulator : ( ) => Q . Promise < string > , startEmulator : ( targetEmulator : string ) => Q . Promise < string > , killEmulator : ( ) => Q . Promise < string > ) : Q . Promise < string > {
178
178
var deferred = Q . defer < string > ( ) ;
179
179
console . log ( "Setting up " + platformName + " emulator." ) ;
180
-
180
+
181
181
function onEmulatorReady ( ) : Q . Promise < string > {
182
182
console . log ( platformName + " emulator is ready!" ) ;
183
183
deferred . resolve ( undefined ) ;
@@ -187,7 +187,7 @@ function bootEmulatorInternal(platformName: string, restartEmulators: boolean, t
187
187
// Called to check if the emulator for the platform is initialized.
188
188
function checkEmulatorReady ( ) : Q . Promise < string > {
189
189
var checkDeferred = Q . defer < string > ( ) ;
190
-
190
+
191
191
console . log ( "Checking if " + platformName + " emulator is ready yet..." ) ;
192
192
// Dummy command that succeeds if emulator is ready and fails otherwise.
193
193
checkEmulator ( )
@@ -197,10 +197,10 @@ function bootEmulatorInternal(platformName: string, restartEmulators: boolean, t
197
197
console . log ( platformName + " emulator is not ready yet!" ) ;
198
198
checkDeferred . reject ( error ) ;
199
199
} ) ;
200
-
200
+
201
201
return checkDeferred . promise ;
202
202
}
203
-
203
+
204
204
var emulatorReadyAttempts = 0 ;
205
205
// Loops checks to see if the emulator is ready and eventually fails after surpassing emulatorMaxReadyAttempts.
206
206
function checkEmulatorReadyLooper ( ) : Q . Promise < string > {
@@ -212,17 +212,17 @@ function bootEmulatorInternal(platformName: string, restartEmulators: boolean, t
212
212
looperDeferred . resolve ( undefined ) ;
213
213
}
214
214
setTimeout ( ( ) => {
215
- checkEmulatorReady ( )
216
- . then ( ( ) => {
217
- looperDeferred . resolve ( undefined ) ;
218
- onEmulatorReady ( ) ;
219
- } , ( ) => {
220
- return checkEmulatorReadyLooper ( ) . then ( ( ) => { looperDeferred . resolve ( undefined ) ; } , ( ) => { looperDeferred . reject ( undefined ) ; } ) ;
221
- } ) ;
222
- } , emulatorReadyCheckDelayMs ) ;
215
+ checkEmulatorReady ( )
216
+ . then ( ( ) => {
217
+ looperDeferred . resolve ( undefined ) ;
218
+ onEmulatorReady ( ) ;
219
+ } , ( ) => {
220
+ return checkEmulatorReadyLooper ( ) . then ( ( ) => { looperDeferred . resolve ( undefined ) ; } , ( ) => { looperDeferred . reject ( undefined ) ; } ) ;
221
+ } ) ;
222
+ } , emulatorReadyCheckDelayMs ) ;
223
223
return looperDeferred . promise ;
224
224
}
225
-
225
+
226
226
// Starts and loops the emulator.
227
227
function startEmulatorAndLoop ( ) : Q . Promise < string > {
228
228
console . log ( "Booting " + platformName + " emulator named " + targetEmulator + "." ) ;
@@ -236,7 +236,7 @@ function bootEmulatorInternal(platformName: string, restartEmulators: boolean, t
236
236
} else {
237
237
promise = checkEmulatorReady ( ) . then ( onEmulatorReady , startEmulatorAndLoop ) ;
238
238
}
239
-
239
+
240
240
return deferred . promise ;
241
241
}
242
242
@@ -257,20 +257,20 @@ export class IOSEmulatorManager implements IEmulatorManager {
257
257
function killIOSEmulator ( ) : Q . Promise < string > {
258
258
return tu . TestUtil . getProcessOutput ( "killall Simulator" ) ;
259
259
}
260
-
260
+
261
261
return tu . TestUtil . readIOSEmulator ( )
262
262
. then ( ( iOSEmulatorName : string ) => {
263
263
return bootEmulatorInternal ( "iOS" , restartEmulators , iOSEmulatorName , checkIOSEmulator , startIOSEmulator , killIOSEmulator ) ;
264
264
} ) ;
265
265
}
266
-
266
+
267
267
/**
268
268
* Launches an already installed application by app id.
269
269
*/
270
270
launchInstalledApplication ( appId : string ) : Q . Promise < string > {
271
271
return tu . TestUtil . getProcessOutput ( "xcrun simctl launch booted " + appId , undefined ) ;
272
272
}
273
-
273
+
274
274
/**
275
275
* Ends a running application given its app id.
276
276
*/
@@ -295,7 +295,7 @@ export class IOSEmulatorManager implements IEmulatorManager {
295
295
return Q . resolve ( error ) ;
296
296
} ) ;
297
297
}
298
-
298
+
299
299
/**
300
300
* Restarts an already installed application by app id.
301
301
*/
@@ -307,13 +307,13 @@ export class IOSEmulatorManager implements IEmulatorManager {
307
307
} )
308
308
. then ( ( ) => this . launchInstalledApplication ( appId ) ) ;
309
309
}
310
-
310
+
311
311
/**
312
312
* Navigates away from the current app, waits for a delay (defaults to 1 second), then navigates to the specified app.
313
313
*/
314
314
resumeApplication ( appId : string , delayBeforeResumingMs : number = 1000 ) : Q . Promise < string > {
315
315
// open a default iOS app (for example, camera)
316
- return this . launchInstalledApplication ( "com.apple.camera " )
316
+ return this . launchInstalledApplication ( "com.apple.Preferences " )
317
317
. then < void > ( ( ) => {
318
318
console . log ( "Waiting for " + delayBeforeResumingMs + "ms before resuming the test application." ) ;
319
319
return Q . delay ( delayBeforeResumingMs ) ;
@@ -323,14 +323,14 @@ export class IOSEmulatorManager implements IEmulatorManager {
323
323
return this . launchInstalledApplication ( appId ) ;
324
324
} ) ;
325
325
}
326
-
326
+
327
327
/**
328
328
* Prepares the emulator for a test.
329
329
*/
330
330
prepareEmulatorForTest ( appId : string ) : Q . Promise < string > {
331
331
return this . endRunningApplication ( appId ) ;
332
332
}
333
-
333
+
334
334
/**
335
335
* Uninstalls the app from the emulator.
336
336
*/
@@ -349,30 +349,42 @@ export class AndroidEmulatorManager implements IEmulatorManager {
349
349
// List all of the packages on the device.
350
350
return tu . TestUtil . getProcessOutput ( "adb shell pm list packages" ) ;
351
351
}
352
+
352
353
function startAndroidEmulator ( androidEmulatorName : string ) : Q . Promise < string > {
353
- return tu . TestUtil . getProcessOutput ( "emulator @" + androidEmulatorName ) ;
354
+ const androidEmulatorCommand = `emulator @${ androidEmulatorName } ` ;
355
+ let osSpecificCommand = "" ;
356
+ if ( process . platform === "darwin" ) {
357
+ osSpecificCommand = `${ androidEmulatorCommand } &` ;
358
+ } else {
359
+ osSpecificCommand = `START /B ${ androidEmulatorCommand } ` ;
360
+ }
361
+ return tu . TestUtil . getProcessOutput ( osSpecificCommand , { timeout : 5000 } , false ) ;
354
362
}
363
+
355
364
function killAndroidEmulator ( ) : Q . Promise < string > {
356
365
return tu . TestUtil . getProcessOutput ( "adb emu kill" ) ;
357
366
}
358
-
359
- return bootEmulatorInternal ( "Android" , restartEmulators , tu . TestUtil . readAndroidEmulator ( ) , checkAndroidEmulator , startAndroidEmulator , killAndroidEmulator ) ;
367
+
368
+ return tu . TestUtil . readAndroidEmulator ( )
369
+ . then ( ( AndroidEmulatorName : string ) => {
370
+ return bootEmulatorInternal ( "Android" , restartEmulators , AndroidEmulatorName , checkAndroidEmulator , startAndroidEmulator , killAndroidEmulator ) ;
371
+ } ) ;
360
372
}
361
-
373
+
362
374
/**
363
375
* Launches an already installed application by app id.
364
376
*/
365
377
launchInstalledApplication ( appId : string ) : Q . Promise < string > {
366
378
return ProjectManager . ProjectManager . execChildProcess ( "adb shell monkey -p " + appId + " -c android.intent.category.LAUNCHER 1" ) ;
367
379
}
368
-
380
+
369
381
/**
370
382
* Ends a running application given its app id.
371
383
*/
372
384
endRunningApplication ( appId : string ) : Q . Promise < string > {
373
385
return ProjectManager . ProjectManager . execChildProcess ( "adb shell am force-stop " + appId ) ;
374
386
}
375
-
387
+
376
388
/**
377
389
* Restarts an already installed application by app id.
378
390
*/
@@ -383,10 +395,10 @@ export class AndroidEmulatorManager implements IEmulatorManager {
383
395
return Q . delay ( 1000 ) ;
384
396
} )
385
397
. then < string > ( ( ) => {
386
- return this . launchInstalledApplication ( appId ) ;
387
- } ) ;
398
+ return this . launchInstalledApplication ( appId ) ;
399
+ } ) ;
388
400
}
389
-
401
+
390
402
/**
391
403
* Navigates away from the current app, waits for a delay (defaults to 1 second), then navigates to the specified app.
392
404
*/
@@ -402,20 +414,20 @@ export class AndroidEmulatorManager implements IEmulatorManager {
402
414
return this . launchInstalledApplication ( appId ) ;
403
415
} ) ;
404
416
}
405
-
417
+
406
418
/**
407
419
* Prepares the emulator for a test.
408
420
*/
409
421
prepareEmulatorForTest ( appId : string ) : Q . Promise < string > {
410
422
return this . endRunningApplication ( appId )
411
- . then ( ( ) => { return ProjectManager . ProjectManager . execChildProcess ( "adb shell pm clear " + appId ) ; } ) ;
423
+ . then ( ( ) => { return commandWithCheckAppExistence ( "adb shell pm clear" , appId ) ; } ) ;
412
424
}
413
-
425
+
414
426
/**
415
427
* Uninstalls the app from the emulator.
416
428
*/
417
429
uninstallApplication ( appId : string ) : Q . Promise < string > {
418
- return ProjectManager . ProjectManager . execChildProcess ( "adb uninstall " + appId ) ;
430
+ return commandWithCheckAppExistence ( "adb uninstall" , appId ) ;
419
431
}
420
432
}
421
433
@@ -441,7 +453,7 @@ export class PlatformResolver {
441
453
return undefined ;
442
454
}
443
455
}
444
-
456
+
445
457
return platforms ;
446
458
}
447
459
@@ -454,9 +466,22 @@ export class PlatformResolver {
454
466
return this . supportedPlatforms [ i ] ;
455
467
}
456
468
}
457
-
469
+
458
470
// we could not find this platform in the list of platforms, so abort
459
471
console . error ( "Unsupported platform: " + cordovaPlatformName ) ;
460
472
return undefined ;
461
473
}
462
- }
474
+ }
475
+
476
+ function commandWithCheckAppExistence ( command : string , appId : string ) {
477
+ return ProjectManager . ProjectManager . execChildProcess ( "adb shell pm list packages" )
478
+ . then ( ( output ) => {
479
+ return output . includes ( appId ) ;
480
+ } ) . then ( ( isAppExist ) => {
481
+ if ( isAppExist ) {
482
+ return ProjectManager . ProjectManager . execChildProcess ( `${ command } ${ appId } ` ) . then ( function ( ) { return null ; } ) ;
483
+ }
484
+ console . log ( `Command "${ command } " is skipped because the application has not yet been installed` ) ;
485
+ return null ;
486
+ } ) ;
487
+ }
0 commit comments