2
2
3
3
var BrowserStack = require ( 'browserstack' ) ,
4
4
fs = require ( 'fs' ) ,
5
+ chalk = require ( 'chalk' ) ,
5
6
utils = require ( '../lib/utils' ) ,
6
7
Server = require ( '../lib/server' ) . Server ,
7
8
config = require ( '../lib/config' ) ,
8
9
Tunnel = require ( '../lib/local' ) . Tunnel ,
9
10
ConfigParser = require ( '../lib/configParser' ) . ConfigParser ,
10
11
serverPort = 8888 ,
12
+ timeout = null ,
13
+ activityTimeout = null ,
11
14
tunnel ;
12
15
13
16
var client = BrowserStack . createClient ( {
@@ -19,7 +22,8 @@ var pid_file = process.cwd() + '/browserstack-run.pid';
19
22
fs . writeFileSync ( pid_file , process . pid , 'utf-8' )
20
23
21
24
var workers = { } ;
22
- var cleanUp = function cleanUp ( ) {
25
+ var workerKeys = { } ;
26
+ var cleanUp = function ( signal ) {
23
27
try {
24
28
server . close ( ) ;
25
29
} catch ( e ) {
@@ -29,33 +33,39 @@ var cleanUp = function cleanUp () {
29
33
console . log ( "Exiting" ) ;
30
34
31
35
for ( var key in workers ) {
36
+ var worker = workers [ key ] ;
32
37
if ( workers . hasOwnProperty ( key ) ) {
33
- client . terminateWorker ( workers [ key ] . id , function ( ) {
38
+ client . terminateWorker ( worker . id , function ( ) {
34
39
if ( ! workers [ key ] ) {
35
40
return ;
36
41
}
37
42
38
- console . log ( '[%s] Terminated' , workers [ key ] . string ) ;
39
- clearTimeout ( workers [ key ] . activityTimeout ) ;
40
- delete workers [ key ]
43
+ console . log ( '[%s] Terminated' , worker . string ) ;
44
+ clearTimeout ( worker . activityTimeout ) ;
45
+ delete workers [ key ] ;
46
+ delete workerKeys [ worker . id ] ;
41
47
} ) ;
42
48
}
43
49
}
50
+ if ( statusPoller ) statusPoller . stop ( ) ;
44
51
45
52
try {
46
53
process . kill ( tunnel . process . pid , 'SIGKILL' ) ;
47
54
} catch ( e ) {
48
55
console . log ( "Non existent tunnel" ) ;
49
56
}
50
57
try {
51
- fs . unlink ( pid_file ) ;
58
+ fs . unlinkSync ( pid_file ) ;
52
59
} catch ( e ) {
53
60
console . log ( "Non existent pid file." ) ;
54
61
}
62
+ if ( signal ) {
63
+ process . kill ( process . pid , 'SIGTERM' ) ;
64
+ }
55
65
} ;
56
66
57
- process . on ( 'exit' , cleanUp ) ;
58
- process . on ( 'SIGINT' , cleanUp ) ;
67
+ process . on ( 'exit' , function ( ) { cleanUp ( false ) } ) ;
68
+ process . on ( 'SIGINT' , function ( ) { cleanUp ( true ) } ) ;
59
69
60
70
console . log ( "Launching server on port:" , serverPort ) ;
61
71
@@ -88,13 +98,13 @@ function launchBrowser(browser, url) {
88
98
browser [ "tunnel_identifier" ] = config . tunnelIdentifier ;
89
99
}
90
100
91
- var timeout = parseInt ( config . timeout ) ;
101
+ timeout = parseInt ( config . timeout ) ;
92
102
if ( ! isNaN ( timeout ) ) {
93
103
browser . timeout = timeout ;
94
104
} else {
95
105
timeout = 300 ;
96
106
}
97
- var activityTimeout = timeout - 10 ;
107
+ activityTimeout = timeout - 10 ;
98
108
99
109
client . createWorker ( browser , function ( err , worker ) {
100
110
if ( err || typeof worker !== 'object' ) {
@@ -110,47 +120,9 @@ function launchBrowser(browser, url) {
110
120
worker . config = browser ;
111
121
worker . string = browserString ;
112
122
workers [ key ] = worker ;
113
-
114
- var statusPoller = setInterval ( function ( ) {
115
- client . getWorker ( worker . id , function ( err , _worker ) {
116
- if ( worker . launched ) {
117
- return ;
118
- }
119
-
120
- if ( _worker . status === 'running' ) {
121
- clearInterval ( statusPoller ) ;
122
- console . log ( '[%s] Launched' , worker . string ) ;
123
- worker . launched = true ;
124
-
125
- worker . activityTimeout = setTimeout ( function ( ) {
126
- if ( ! worker . acknowledged ) {
127
- var subject = "Worker inactive for too long: " + worker . string ;
128
- var content = "Worker details:\n" + JSON . stringify ( worker . config , null , 4 ) ;
129
- client . takeScreenshot ( worker . id , function ( error , screenshot ) {
130
- if ( ! error && screenshot . url ) {
131
- console . log ( '[%s] Screenshot: %s' , worker . string , screenshot . url ) ;
132
- }
133
- utils . alertBrowserStack ( subject , content ) ;
134
- } ) ;
135
- }
136
- } , activityTimeout * 1000 ) ;
137
-
138
- setTimeout ( function ( ) {
139
- if ( workers [ key ] ) {
140
- var subject = "Tests timed out on: " + worker . string ;
141
- var content = "Worker details:\n" + JSON . stringify ( worker . config , null , 4 ) ;
142
- client . takeScreenshot ( worker . id , function ( error , screenshot ) {
143
- if ( ! error && screenshot . url ) {
144
- console . log ( '[%s] Screenshot: %s' , worker . string , screenshot . url ) ;
145
- }
146
- utils . alertBrowserStack ( subject , content ) ;
147
- } ) ;
148
- }
149
- } , ( activityTimeout * 1000 ) ) ;
150
- }
151
- } ) ;
152
- } , 2000 ) ;
123
+ workerKeys [ worker . id ] = { key : key , marked : false } ;
153
124
} ) ;
125
+
154
126
}
155
127
156
128
var launchBrowsers = function ( config , browser ) {
@@ -167,6 +139,81 @@ var launchBrowsers = function(config, browser) {
167
139
} , 100 ) ;
168
140
}
169
141
142
+ var statusPoller = {
143
+ poller : null ,
144
+
145
+ start : function ( ) {
146
+ statusPoller . poller = setInterval ( function ( ) {
147
+ client . getWorkers ( function ( err , _workers ) {
148
+ _workers = _workers . filter ( function ( currentValue , index , array ) {
149
+ return currentValue . status == 'running' && workerKeys [ currentValue . id ] && ! workerKeys [ currentValue . id ] . marked ;
150
+ } ) ;
151
+ for ( var i in _workers ) {
152
+ var _worker = _workers [ i ] ;
153
+ var workerData = workerKeys [ _worker . id ] ;
154
+ var worker = workers [ workerData . key ] ;
155
+ if ( worker . launched ) {
156
+ return ;
157
+ }
158
+
159
+ if ( _worker . status === 'running' ) {
160
+ //clearInterval(statusPoller);
161
+ console . log ( '[%s] Launched' , worker . string ) ;
162
+ worker . launched = true ;
163
+ workerData . marked = true ;
164
+
165
+ worker . activityTimeout = setTimeout ( function ( ) {
166
+ if ( ! worker . acknowledged ) {
167
+ var subject = "Worker inactive for too long: " + worker . string ;
168
+ var content = "Worker details:\n" + JSON . stringify ( worker . config , null , 4 ) ;
169
+ utils . alertBrowserStack ( subject , content , null , function ( ) { } ) ;
170
+ delete workers [ workerData . key ] ;
171
+ delete workerKeys [ worker . id ] ;
172
+ config . status += 1 ;
173
+ if ( utils . objectSize ( workers ) === 0 ) {
174
+ var color = config . status > 0 ? "red" : "green" ;
175
+ console . log ( chalk [ color ] ( "All tests done, failures: %d." ) , config . status ) ;
176
+
177
+ if ( config . status > 0 ) {
178
+ config . status = 1 ;
179
+ }
180
+
181
+ process . exit ( config . status ) ;
182
+ }
183
+ }
184
+ } , activityTimeout * 1000 ) ;
185
+
186
+ setTimeout ( function ( ) {
187
+ if ( worker . acknowledged ) {
188
+ var subject = "Tests timed out on: " + worker . string ;
189
+ var content = "Worker details:\n" + JSON . stringify ( worker . config , null , 4 ) ;
190
+ utils . alertBrowserStack ( subject , content , null , function ( ) { } ) ;
191
+ delete workers [ workerData . key ] ;
192
+ delete workerKeys [ worker . id ] ;
193
+ config . status += 1 ;
194
+ if ( utils . objectSize ( workers ) === 0 ) {
195
+ var color = config . status > 0 ? "red" : "green" ;
196
+ console . log ( chalk [ color ] ( "All tests done, failures: %d." ) , config . status ) ;
197
+
198
+ if ( config . status > 0 ) {
199
+ config . status = 1 ;
200
+ }
201
+
202
+ process . exit ( config . status ) ;
203
+ }
204
+ }
205
+ } , ( activityTimeout * 1000 ) ) ;
206
+ }
207
+ }
208
+ } ) ;
209
+ } , 2000 ) ;
210
+ } ,
211
+
212
+ stop : function ( ) {
213
+ clearInterval ( statusPoller . poller ) ;
214
+ }
215
+ } ;
216
+
170
217
if ( config . browsers && config . browsers . length > 0 ) {
171
218
ConfigParser . parse ( client , config . browsers , function ( browsers ) {
172
219
tunnel = new Tunnel ( config . key , serverPort , config . tunnelIdentifier , function ( ) {
@@ -187,5 +234,6 @@ if (config.browsers && config.browsers.length > 0) {
187
234
}
188
235
} ) ;
189
236
} ) ;
237
+ statusPoller . start ( ) ;
190
238
} ) ;
191
239
}
0 commit comments