Skip to content

Commit 69376a2

Browse files
committed
Inline YUITest CLI to standardize output
- Based on the YUITest Node CLI with minor colourization customizations
1 parent 38e9215 commit 69376a2

File tree

1 file changed

+119
-21
lines changed

1 file changed

+119
-21
lines changed

Gruntfile.js

Lines changed: 119 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -219,42 +219,140 @@ module.exports = function(grunt) {
219219
var files = this.filesSrc;
220220
var TestRunner = YUITest.TestRunner;
221221
var done = this.async();
222+
var errors = [],
223+
failures = [],
224+
stack = [];
222225

223226
//Eval each file so the tests are brought into this scope were CSSLint and YUITest are loaded already
224227
files.forEach(function(filepath) {
225228
eval(grunt.file.read(filepath));
226229
});
227230

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+
231302
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+
233309
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+
236317
break;
318+
237319
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;
239325
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
240341
}
241-
}
242342

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);
252344
}
253345
//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);
258356
TestRunner.run();
259357
});
260358

0 commit comments

Comments
 (0)