1
1
/*eslint-env node*/
2
2
'use strict' ;
3
3
var LIBS = {
4
+ clc : require ( 'cli-color' ) ,
5
+ CLI : require ( 'clui' ) ,
4
6
Sauce : require ( 'sauce-tunnel' ) ,
5
7
http : require ( 'http' ) ,
6
8
serve : require ( 'serve-static' ) ,
@@ -71,10 +73,21 @@ var LIBS = {
71
73
}
72
74
] ,
73
75
76
+ // Fancy CLI output
77
+ Line = LIBS . CLI . Line ,
78
+ oldConsoleLog = console . log ,
79
+ consoleLogAllowed = false ,
80
+
81
+ lastTunnelMessage ,
82
+ lastErrorMessages = [ ] ,
83
+ lastOutputLines = 0 ,
74
84
tunnel = process . env . TRAVIS_BUILD_NUMBER ? null : new LIBS . Sauce ( process . env . SAUCE_USERNAME , process . env . SAUCE_ACCESS_KEY ) ,
75
85
serveStatic = LIBS . serve ( LIBS . path . resolve ( __dirname , '../' ) ) ,
76
86
testBaseURL = 'http://localhost:8000/tests/test262/pages/' ,
77
87
88
+ // Get the tests together
89
+ tests = listTests ( ) ,
90
+
78
91
// A list of tests that ES3 environments can't pass, either because they
79
92
// use accessors or they test for behaviour achievable only in ES5 environments
80
93
es3blacklist = [
@@ -88,6 +101,69 @@ LIBS.http.createServer(function(req, res) {
88
101
serveStatic ( req , res , done ) ;
89
102
} ) . listen ( 8000 ) ;
90
103
104
+ function drawStatus ( ) {
105
+ // Don't draw fancy updates in Travis' log
106
+ if ( process . env . TRAVIS_JOB_NUMBER ) {
107
+ return ;
108
+ }
109
+
110
+ var clc = LIBS . clc ,
111
+ maxWidth = LIBS . clc . windowSize . width ,
112
+ blankLine = new Line ( ) . fill ( ) ;
113
+
114
+ if ( lastOutputLines ) {
115
+ process . stdout . write ( '\x1b[' + lastOutputLines + 'A' ) ;
116
+ lastOutputLines = 0 ;
117
+ }
118
+
119
+ // Draw header
120
+ blankLine . output ( ) ;
121
+ new Line ( )
122
+ . padding ( 2 )
123
+ . column ( 'Browser' , 22 , [ clc . cyan ] )
124
+ . column ( 'Passed (Failed)' , tests . length + 2 , [ clc . cyan ] )
125
+ . fill ( )
126
+ . output ( ) ;
127
+
128
+ // Draw status
129
+ blankLine . output ( ) ;
130
+ lastOutputLines += 3 ;
131
+ for ( var k in BROWSERS ) {
132
+ var results = BROWSERS [ k ] . results || { failCount : 0 , passCount : 0 } ;
133
+ new Line ( )
134
+ . padding ( 2 )
135
+ . column ( BROWSERS [ k ] . browserName + ' ' + BROWSERS [ k ] . version , 22 , [ clc . blue ] )
136
+ . column ( results . passCount + ' (' + results . failCount + ') ' , undefined , [ results . failCount ? clc . red : clc . green ] )
137
+ . column ( results . currentTest || 'Waiting...' , 100 , [ clc . blackBright ] )
138
+ . fill ( )
139
+ . output ( ) ;
140
+
141
+ lastOutputLines ++ ;
142
+ }
143
+
144
+ blankLine . output ( ) ;
145
+ lastOutputLines ++ ;
146
+
147
+ if ( lastTunnelMessage ) {
148
+ new Line ( ) . column ( 'Sauce Connect status:' , maxWidth , [ clc . cyan ] ) . fill ( ) . output ( ) ;
149
+ new Line ( ) . padding ( 2 ) . column ( lastTunnelMessage ) . fill ( ) . output ( ) ;
150
+ lastOutputLines += 2 ;
151
+ }
152
+
153
+ if ( lastErrorMessages . length ) {
154
+ blankLine . output ( ) ;
155
+ new Line ( ) . column ( 'Recent failures:' , maxWidth , [ clc . cyan ] ) . fill ( ) . output ( ) ;
156
+ lastOutputLines += 2 ;
157
+
158
+ lastErrorMessages . forEach ( function ( m ) {
159
+ new Line ( ) . column ( ' ' + m . split ( '\n' ) . shift ( ) , maxWidth , [ clc . red ] ) . fill ( ) . output ( ) ;
160
+ lastOutputLines ++ ;
161
+ } ) ;
162
+ }
163
+ blankLine . output ( ) ;
164
+ lastOutputLines ++ ;
165
+ }
166
+
91
167
function listTests ( ) {
92
168
var tests = [ ] ,
93
169
todo = [ '.' ] ,
@@ -119,7 +195,8 @@ function runTestsInBrowser(state, browserConfig, done) {
119
195
browserString = LIBS . util . inspect ( browserConfig , { depth : null } ) . replace ( / \n \s * / g, ' ' ) ,
120
196
browser ,
121
197
failures = 0 ;
122
- console . log ( '================================================ START' , browserString ) ;
198
+
199
+ console . log ( LIBS . clc . cyan ( '================================================ START' ) , browserString ) ;
123
200
124
201
Object . keys ( state . capabilities ) . forEach ( function ( key ) {
125
202
caps [ key ] = state . capabilities [ key ] ;
@@ -149,12 +226,21 @@ function runTestsInBrowser(state, browserConfig, done) {
149
226
browser . init ( caps , taskDone ) ;
150
227
} ) ;
151
228
229
+ // Setup progress and results
230
+ browserConfig . results = {
231
+ failCount : 0 ,
232
+ passCount : 0 ,
233
+ errors : [ ]
234
+ } ;
235
+
152
236
// for each page, get and test page
153
237
state . tests . forEach ( function ( test ) {
154
238
tasks . push ( function ( taskDone ) {
155
239
var url = testBaseURL + test ,
156
240
ie8 = browserConfig . browserName === 'internet explorer' && browserConfig . version === '8' ;
157
241
242
+ browserConfig . results . currentTest = test ;
243
+
158
244
//- Skip impassable tests in IE 8
159
245
if ( ie8 && ( test . slice ( - 9 ) === '_L15.html' || es3blacklist . indexOf ( test . split ( '/' ) . pop ( ) ) > - 1 ) ) {
160
246
console . log ( '--SKIPPED--' , test , browserString , 'Not passable from ES3 environments' ) ;
@@ -171,20 +257,30 @@ function runTestsInBrowser(state, browserConfig, done) {
171
257
if ( cookedErr . message ) { cookedErr = cookedErr . message ; }
172
258
cookedErr = cookedErr . toString ( ) . split ( '\n' ) [ 0 ] ;
173
259
cookedErr = cookedErr || out || 'FAILED no results' ;
174
- console . log ( '--ERROR--' , err ) ;
260
+ console . log ( LIBS . clc . red ( '--ERROR--' ) , LIBS . clc . red ( err ) ) ;
175
261
}
176
262
if ( out ) {
177
263
state . results . passCount ++ ;
264
+ browserConfig . results . passCount ++ ;
178
265
console . log ( '--PASSED--' , test , browserString ) ;
179
266
} else {
180
267
failures ++ ;
268
+ browserConfig . results . failCount ++ ;
181
269
state . results . failCount ++ ;
182
270
if ( ! state . results . failures [ test ] ) {
183
271
state . results . failures [ test ] = { } ;
184
272
}
185
273
state . results . failures [ test ] [ browserString ] = cookedErr ;
186
- console . log ( '--FAILED--' , test , browserString , cookedErr ) ;
274
+ if ( lastErrorMessages . length > 4 ) {
275
+ lastErrorMessages . length = 4 ;
276
+ }
277
+ lastErrorMessages . push ( browserConfig . browserName + ' ' + browserConfig . version + ' – ' + cookedErr ) ;
278
+ console . log ( LIBS . clc . red ( '--FAILED--' ) , LIBS . clc . red ( test ) , LIBS . clc . red ( browserString ) , LIBS . clc . red ( cookedErr ) ) ;
187
279
}
280
+
281
+ // Update display
282
+ drawStatus ( ) ;
283
+
188
284
// This sometimes signifies a suacelabs browser that has gone awawy.
189
285
if ( 'ERROR Internal Server Error' === cookedErr ) {
190
286
taskDone ( err ) ;
@@ -251,10 +347,10 @@ function runTestsInBrowser(state, browserConfig, done) {
251
347
} ) ;
252
348
253
349
LIBS . async . series ( tasks , function ( err ) {
254
- console . log ( '================================================ DONE' , browserString ) ;
350
+ console . log ( LIBS . clc . cyan ( '================================================ DONE' ) , browserString ) ;
255
351
if ( err ) {
256
- console . log ( '--BROWSER FAILED--' ) ;
257
- console . log ( err ) ;
352
+ console . log ( LIBS . clc . red ( '--BROWSER FAILED--' ) ) ;
353
+ console . log ( LIBS . clc . red ( err ) ) ;
258
354
}
259
355
done ( err ) ;
260
356
} ) ;
@@ -268,7 +364,7 @@ function runTests(state, done) {
268
364
q = LIBS . async . queue ( function ( browser , browserDone ) {
269
365
runTestsInBrowser ( state , browser , function ( err ) {
270
366
if ( err ) {
271
- console . log ( err . message ) ;
367
+ console . log ( LIBS . clc . red ( err . message ) ) ;
272
368
browserFailures ++ ;
273
369
}
274
370
browserDone ( ) ;
@@ -306,6 +402,12 @@ function main(tunnelReady) {
306
402
tags : [ ]
307
403
} ;
308
404
state . capabilities [ 'tunnel-identifier' ] = process . env . TRAVIS_JOB_NUMBER || tunnel . identifier ;
405
+
406
+ // Override console log for local
407
+ if ( ! process . env . TRAVIS_JOB_NUMBER ) {
408
+ console . log = function ( ) { } ;
409
+ }
410
+
309
411
if ( process . env . TRAVIS_JOB_NUMBER ) {
310
412
// we only need one of these to run on travis
311
413
if ( '.1' !== process . env . TRAVIS_JOB_NUMBER . substr ( - 2 ) ) {
@@ -319,12 +421,15 @@ function main(tunnelReady) {
319
421
state . capabilities . build = process . env . TRAVIS_BUILD_NUMBER || process . pid ;
320
422
console . log ( JSON . stringify ( state . capabilities , null , 4 ) ) ;
321
423
322
- console . log ( '================================================ START' ) ;
424
+ console . log ( LIBS . clc . cyan ( '================================================ START' ) ) ;
323
425
runTests ( state , function ( err ) {
324
426
if ( tunnel ) {
325
427
tunnel . stop ( function ( ) { } ) ;
326
428
}
327
- console . log ( '================================================ DONE' ) ;
429
+ console . log ( LIBS . clc . cyan ( '================================================ DONE' ) ) ;
430
+
431
+ console . log = oldConsoleLog ;
432
+
328
433
if ( err ) {
329
434
console . error ( err ) ;
330
435
process . exit ( 2 ) ;
@@ -338,10 +443,15 @@ function main(tunnelReady) {
338
443
} ) ;
339
444
}
340
445
446
+ // Save the current cursor position for redraws
447
+ drawStatus ( ) ;
448
+
341
449
if ( tunnel ) {
342
- console . log ( 'Starting SauceTunnel...' ) ;
343
450
tunnel . start ( main ) ;
344
- tunnel . proc . stdout . pipe ( process . stdout ) ;
451
+ tunnel . proc . stdout . on ( 'data' , function ( msg ) {
452
+ lastTunnelMessage = String ( msg ) . split ( '\n' ) . shift ( ) ;
453
+ drawStatus ( ) ;
454
+ } ) ;
345
455
}
346
456
else {
347
457
main ( true ) ;
0 commit comments