@@ -32,11 +32,17 @@ class TestExecutionService implements ITestExecutionService {
3232 private $options : IOptions ,
3333 private $pluginsService : IPluginsService ,
3434 private $errors : IErrors ,
35- private $devicesService : Mobile . IDevicesService ) {
35+ private $androidDebugService :IDebugService ,
36+ private $iOSDebugService : IDebugService ,
37+ private $devicesService : Mobile . IDevicesService ,
38+ private $childProcess : IChildProcess ) {
3639 }
3740
41+ public platform : string ;
42+
3843 public startTestRunner ( platform : string ) : IFuture < void > {
3944 return ( ( ) => {
45+ this . platform = platform ;
4046 this . $options . justlaunch = true ;
4147 let blockingOperationFuture = new Future < void > ( ) ;
4248 process . on ( 'message' , ( launcherConfig : any ) => {
@@ -50,7 +56,7 @@ class TestExecutionService implements ITestExecutionService {
5056 let configOptions : IKarmaConfigOptions = JSON . parse ( launcherConfig ) ;
5157 this . $options . debugBrk = configOptions . debugBrk ;
5258 this . $options . debugTransport = configOptions . debugTransport ;
53- let configJs = this . generateConfig ( configOptions ) ;
59+ let configJs = this . generateConfig ( this . $options . port . toString ( ) , configOptions ) ;
5460 this . $fs . writeFile ( path . join ( projectDir , TestExecutionService . CONFIG_FILE_NAME ) , configJs ) . wait ( ) ;
5561
5662 let socketIoJsUrl = `http://localhost:${ this . $options . port } /socket.io/socket.io.js` ;
@@ -93,37 +99,47 @@ class TestExecutionService implements ITestExecutionService {
9399 public startKarmaServer ( platform : string ) : IFuture < void > {
94100 return ( ( ) => {
95101 platform = platform . toLowerCase ( ) ;
96- this . $pluginsService . ensureAllDependenciesAreInstalled ( ) . wait ( ) ;
97- let pathToKarma = path . join ( this . $projectData . projectDir , 'node_modules/karma' ) ;
98- let KarmaServer = require ( path . join ( pathToKarma , 'lib/server' ) ) ;
99- if ( platform === 'ios' && this . $options . emulator ) {
100- platform = 'ios_simulator' ;
101- }
102- let karmaConfig : any = {
103- browsers : [ platform ] ,
104- configFile : path . join ( this . $projectData . projectDir , 'karma.conf.js' ) ,
105- _NS : {
106- log : this . $logger . getLevel ( ) ,
107- path : this . $options . path ,
108- tns : process . argv [ 1 ] ,
109- node : process . execPath ,
110- options : {
111- debugTransport : this . $options . debugTransport ,
112- debugBrk : this . $options . debugBrk ,
113- }
114- } ,
115- } ;
116- if ( this . $config . DEBUG || this . $logger . getLevel ( ) === 'TRACE' ) {
117- karmaConfig . logLevel = 'DEBUG' ;
118- }
119- if ( ! this . $options . watch ) {
120- karmaConfig . singleRun = true ;
102+ this . platform = platform ;
103+
104+ if ( this . $options . debugBrk && this . $options . watch ) {
105+ this . $errors . failWithoutHelp ( "You cannot use --watch and --debug-brk simultaneously. Remove one of the flags and try again." ) ;
121106 }
122- if ( this . $options . debugBrk ) {
123- karmaConfig . browserNoActivityTimeout = 1000000000 ;
107+
108+ if ( ! this . $platformService . preparePlatform ( platform ) . wait ( ) ) {
109+ this . $errors . failWithoutHelp ( "Verify that listed files are well-formed and try again the operation." ) ;
124110 }
125- this . $logger . debug ( JSON . stringify ( karmaConfig , null , 4 ) ) ;
126- new KarmaServer ( karmaConfig ) . start ( ) ;
111+
112+ let projectDir = this . $projectData . projectDir ;
113+ this . $devicesService . initialize ( { platform : platform , deviceId : this . $options . device } ) . wait ( ) ;
114+
115+ let karmaConfig = this . getKarmaConfiguration ( platform ) ,
116+ karmaRunner = this . $childProcess . fork ( path . join ( __dirname , "karma-execution.js" ) ) ;
117+
118+ karmaRunner . send ( { karmaConfig : karmaConfig } ) ;
119+ karmaRunner . on ( "message" , ( karmaData : any ) => {
120+ fiberBootstrap . run ( ( ) => {
121+ this . $logger . trace ( "## Unit-testing: Parent process received message" , karmaData ) ;
122+ let port : string ;
123+ if ( karmaData . url ) {
124+ port = karmaData . url . port ;
125+ let socketIoJsUrl = `http://${ karmaData . url . host } /socket.io/socket.io.js` ;
126+ let socketIoJs = this . $httpClient . httpRequest ( socketIoJsUrl ) . wait ( ) . body ;
127+ this . $fs . writeFile ( path . join ( projectDir , TestExecutionService . SOCKETIO_JS_FILE_NAME ) , socketIoJs ) . wait ( ) ;
128+ }
129+
130+ if ( karmaData . launcherConfig ) {
131+ let configOptions : IKarmaConfigOptions = JSON . parse ( karmaData . launcherConfig ) ;
132+ let configJs = this . generateConfig ( port , configOptions ) ;
133+ this . $fs . writeFile ( path . join ( projectDir , TestExecutionService . CONFIG_FILE_NAME ) , configJs ) . wait ( ) ;
134+ }
135+
136+ if ( this . $options . debugBrk ) {
137+ this . getDebugService ( platform ) . debug ( ) . wait ( ) ;
138+ } else {
139+ this . liveSyncProject ( platform ) . wait ( ) ;
140+ }
141+ } ) ;
142+ } ) ;
127143 } ) . future < void > ( ) ( ) ;
128144 }
129145
@@ -138,8 +154,7 @@ class TestExecutionService implements ITestExecutionService {
138154 } ) . future < void > ( ) ( ) ;
139155 }
140156
141- private generateConfig ( options : any ) : string {
142- let port = this . $options . port ;
157+ private generateConfig ( port : string , options : any ) : string {
143158 let nics = os . networkInterfaces ( ) ;
144159 let ips = Object . keys ( nics )
145160 . map ( nicName => nics [ nicName ] . filter ( ( binding : any ) => binding . family === 'IPv4' && ! binding . internal ) [ 0 ] )
@@ -154,5 +169,65 @@ class TestExecutionService implements ITestExecutionService {
154169
155170 return 'module.exports = ' + JSON . stringify ( config ) ;
156171 }
172+
173+ private getDebugService ( platform : string ) : IDebugService {
174+ let lowerCasedPlatform = platform . toLowerCase ( ) ;
175+ if ( lowerCasedPlatform === this . $devicePlatformsConstants . iOS . toLowerCase ( ) ) {
176+ return this . $iOSDebugService ;
177+ } else if ( lowerCasedPlatform === this . $devicePlatformsConstants . Android . toLowerCase ( ) ) {
178+ return this . $androidDebugService ;
179+ }
180+
181+ throw new Error ( `Invalid platform ${ platform } . Valid platforms are ${ this . $devicePlatformsConstants . iOS } and ${ this . $devicePlatformsConstants . Android } ` ) ;
182+ }
183+
184+ private getKarmaConfiguration ( platform : string ) : any {
185+ let karmaConfig : any = {
186+ browsers : [ platform ] ,
187+ configFile : path . join ( this . $projectData . projectDir , 'karma.conf.js' ) ,
188+ _NS : {
189+ log : this . $logger . getLevel ( ) ,
190+ path : this . $options . path ,
191+ tns : process . argv [ 1 ] ,
192+ node : process . execPath ,
193+ options : {
194+ debugTransport : this . $options . debugTransport ,
195+ debugBrk : this . $options . debugBrk ,
196+ }
197+ } ,
198+ } ;
199+ if ( this . $config . DEBUG || this . $logger . getLevel ( ) === 'TRACE' ) {
200+ karmaConfig . logLevel = 'DEBUG' ;
201+ }
202+ if ( ! this . $options . watch ) {
203+ karmaConfig . singleRun = true ;
204+ }
205+ if ( this . $options . debugBrk ) {
206+ karmaConfig . browserNoActivityTimeout = 1000000000 ;
207+ }
208+
209+ karmaConfig . projectDir = this . $projectData . projectDir ;
210+ this . $logger . debug ( JSON . stringify ( karmaConfig , null , 4 ) ) ;
211+
212+ return karmaConfig ;
213+ }
214+
215+ private liveSyncProject ( platform : string ) : IFuture < void > {
216+ return ( ( ) => {
217+ let platformData = this . $platformsData . getPlatformData ( platform . toLowerCase ( ) ) ,
218+ projectFilesPath = path . join ( platformData . appDestinationDirectoryPath , constants . APP_FOLDER_NAME ) ;
219+
220+ let liveSyncData : ILiveSyncData = {
221+ platform : platform ,
222+ appIdentifier : this . $projectData . projectId ,
223+ projectFilesPath : projectFilesPath ,
224+ syncWorkingDirectory : path . join ( this . $projectData . projectDir , constants . APP_FOLDER_NAME ) ,
225+ canExecuteFastSync : false , // Always restart the application when change is detected, so tests will be rerun.
226+ excludedProjectDirsAndFiles : constants . LIVESYNC_EXCLUDED_FILE_PATTERNS
227+ } ;
228+
229+ this . $liveSyncServiceBase . sync ( liveSyncData ) . wait ( ) ;
230+ } ) . future < void > ( ) ( ) ;
231+ }
157232}
158233$injector . register ( 'testExecutionService' , TestExecutionService ) ;
0 commit comments