@@ -219,42 +219,140 @@ module.exports = function(grunt) {
219
219
var files = this . filesSrc ;
220
220
var TestRunner = YUITest . TestRunner ;
221
221
var done = this . async ( ) ;
222
+ var errors = [ ] ,
223
+ failures = [ ] ,
224
+ stack = [ ] ;
222
225
223
226
//Eval each file so the tests are brought into this scope were CSSLint and YUITest are loaded already
224
227
files . forEach ( function ( filepath ) {
225
228
eval ( grunt . file . read ( filepath ) ) ;
226
229
} ) ;
227
230
228
- //Generic test event handler for individual test
229
- function handleTestResult ( data ) {
230
- switch ( data . type ) {
231
+ // From YUITest Node CLI
232
+ function filterStackTrace ( stackTrace ) {
233
+ if ( stackTrace ) {
234
+ var lines = stackTrace . split ( "\n" ) ,
235
+ result = [ ] ,
236
+ i , len ;
237
+
238
+ //skip first line, it's the error
239
+ for ( i = 1 , len = lines . length ; i < len ; i ++ ) {
240
+ if ( lines [ i ] . indexOf ( "yuitest-node" ) > - 1 ) {
241
+ break ;
242
+ } else {
243
+ result . push ( lines [ i ] ) ;
244
+ }
245
+ }
246
+
247
+ return result . join ( "\n" ) ;
248
+ } else {
249
+ return "Unavailable." ;
250
+ }
251
+ }
252
+
253
+ // From YUITest Node CLI with minor colourization changes
254
+ function handleEvent ( event ) {
255
+
256
+ var message = "" ,
257
+ results = event . results ,
258
+ i , len ;
259
+
260
+ switch ( event . type ) {
261
+ case TestRunner . BEGIN_EVENT :
262
+ message = "YUITest for Node.js\n" ;
263
+
264
+ if ( TestRunner . _groups ) {
265
+ message += "Filtering on groups '" + TestRunner . _groups . slice ( 1 , - 1 ) + "'\n" ;
266
+ }
267
+ break ;
268
+
269
+ case TestRunner . COMPLETE_EVENT :
270
+ message = "\nTotal tests: " + results . total + ", " +
271
+ ( "Failures: " + results . failed ) . red + ", " +
272
+ ( "Skipped: " + results . ignored ) . yellow +
273
+ ", Time: " + ( results . duration / 1000 ) + " seconds\n" ;
274
+
275
+ if ( failures . length ) {
276
+ message += "\nTests failed:\n" . red ;
277
+
278
+ for ( i = 0 , len = failures . length ; i < len ; i ++ ) {
279
+ message += "\n" + ( i + 1 ) + ") " + failures [ i ] . name + " : " + failures [ i ] . error . getMessage ( ) + "\n" ;
280
+ message += "Stack trace:\n" + filterStackTrace ( failures [ i ] . error . stack ) + "\n" ;
281
+ }
282
+
283
+ message += "\n" ;
284
+ }
285
+
286
+ if ( errors . length ) {
287
+ message += "\nErrors:\n" . red ;
288
+
289
+ for ( i = 0 , len = errors . length ; i < len ; i ++ ) {
290
+ message += "\n" + ( i + 1 ) + ") " + errors [ i ] . name + " : " + errors [ i ] . error . message + "\n" ;
291
+ message += "Stack trace:\n" + filterStackTrace ( errors [ i ] . error . stack ) + "\n" ;
292
+ }
293
+
294
+ message += "\n" ;
295
+ }
296
+
297
+ message += "\n\n" ;
298
+ //Tell grunt we're done the async operation
299
+ done ( ) ;
300
+ break ;
301
+
231
302
case TestRunner . TEST_FAIL_EVENT :
232
- grunt . verbose . fail ( "Test named '" + data . testName + "' failed with message: '" + data . error . message + "'." ) . or . write ( "." . red ) ;
303
+ message = "F" . red ;
304
+ failures . push ( {
305
+ name : stack . concat ( [ event . testName ] ) . join ( " > " ) ,
306
+ error : event . error
307
+ } ) ;
308
+
233
309
break ;
234
- case TestRunner . TEST_PASS_EVENT :
235
- grunt . verbose . ok ( "Test named '" + data . testName + "' passed." ) . or . write ( "." . green ) ;
310
+
311
+ case TestRunner . ERROR_EVENT :
312
+ errors . push ( {
313
+ name : stack . concat ( [ event . methodName ] ) . join ( " > " ) ,
314
+ error : event . error
315
+ } ) ;
316
+
236
317
break ;
318
+
237
319
case TestRunner . TEST_IGNORE_EVENT :
238
- grunt . verbose . warn ( "Test named '" + data . testName + "' was ignored." ) . or . write ( "." . yellow ) ;
320
+ message = "S" . yellow ;
321
+ break ;
322
+
323
+ case TestRunner . TEST_PASS_EVENT :
324
+ message = "." . green ;
239
325
break ;
326
+
327
+ case TestRunner . TEST_SUITE_BEGIN_EVENT :
328
+ stack . push ( event . testSuite . name ) ;
329
+ break ;
330
+
331
+ case TestRunner . TEST_CASE_COMPLETE_EVENT :
332
+ case TestRunner . TEST_SUITE_COMPLETE_EVENT :
333
+ stack . pop ( ) ;
334
+ break ;
335
+
336
+ case TestRunner . TEST_CASE_BEGIN_EVENT :
337
+ stack . push ( event . testCase . name ) ;
338
+ break ;
339
+
340
+ //no default
240
341
}
241
- }
242
342
243
- //Event to execute after all tests suites are finished
244
- function reportResults ( allsuites ) {
245
- var results = allsuites . results ;
246
- grunt . log . write ( "\nTotal tests: " + results . total + ", Failures: " +
247
- results . failed + ", Skipped: " + results . ignored +
248
- ", Time: " + ( results . duration / 1000 ) + " seconds\n" ) ;
249
-
250
- //Tell grunt we're done the async testing
251
- done ( ) ;
343
+ grunt . log . write ( message ) ;
252
344
}
253
345
//Add event listeners
254
- TestRunner . subscribe ( TestRunner . TEST_FAIL_EVENT , handleTestResult ) ;
255
- TestRunner . subscribe ( TestRunner . TEST_IGNORE_EVENT , handleTestResult ) ;
256
- TestRunner . subscribe ( TestRunner . TEST_PASS_EVENT , handleTestResult ) ;
257
- TestRunner . subscribe ( TestRunner . COMPLETE_EVENT , reportResults ) ;
346
+ TestRunner . subscribe ( TestRunner . BEGIN_EVENT , handleEvent ) ;
347
+ TestRunner . subscribe ( TestRunner . TEST_FAIL_EVENT , handleEvent ) ;
348
+ TestRunner . subscribe ( TestRunner . TEST_PASS_EVENT , handleEvent ) ;
349
+ TestRunner . subscribe ( TestRunner . ERROR_EVENT , handleEvent ) ;
350
+ TestRunner . subscribe ( TestRunner . TEST_IGNORE_EVENT , handleEvent ) ;
351
+ TestRunner . subscribe ( TestRunner . TEST_CASE_BEGIN_EVENT , handleEvent ) ;
352
+ TestRunner . subscribe ( TestRunner . TEST_CASE_COMPLETE_EVENT , handleEvent ) ;
353
+ TestRunner . subscribe ( TestRunner . TEST_SUITE_BEGIN_EVENT , handleEvent ) ;
354
+ TestRunner . subscribe ( TestRunner . TEST_SUITE_COMPLETE_EVENT , handleEvent ) ;
355
+ TestRunner . subscribe ( TestRunner . COMPLETE_EVENT , handleEvent ) ;
258
356
TestRunner . run ( ) ;
259
357
} ) ;
260
358
0 commit comments