haste-server/node_modules/mocha/lib/reporters/html.js

155 lines
3.5 KiB
JavaScript
Raw Permalink Normal View History

2012-02-06 20:09:01 +01:00
/**
* Module dependencies.
*/
var Base = require('./base')
, utils = require('../utils')
, Progress = require('../browser/progress')
, escape = utils.escape;
/**
* Expose `Doc`.
*/
exports = module.exports = HTML;
/**
* Stats template.
*/
var statsTemplate = '<ul id="stats">'
+ '<li class="progress"><canvas width="40" height="40"></canvas></li>'
+ '<li class="passes">passes: <em>0</em></li>'
+ '<li class="failures">failures: <em>0</em></li>'
+ '<li class="duration">duration: <em>0</em>s</li>'
+ '</ul>';
/**
* Initialize a new `Doc` reporter.
*
* @param {Runner} runner
* @api public
*/
function HTML(runner) {
Base.call(this, runner);
// TODO: clean up
var self = this
, stats = this.stats
, total = runner.total
, root = $('#mocha')
, stack = [root]
, stat = $(statsTemplate).appendTo(root)
, canvas = stat.find('canvas').get(0)
, progress
, ctx
if (canvas.getContext) {
ctx = canvas.getContext('2d');
progress = new Progress;
}
if (!root.length) return error('#mocha div missing, add it to your document');
if (progress) progress.size(40);
runner.on('suite', function(suite){
if (suite.root) return;
// suite
var el = $('<div class="suite"><h1>' + suite.title + '</h1></div>');
// container
stack[0].append(el);
stack.unshift($('<div>'));
el.append(stack[0]);
});
runner.on('suite end', function(suite){
if (suite.root) return;
stack.shift();
});
runner.on('fail', function(test, err){
if (err.uncaught) runner.emit('test end', test);
});
runner.on('test end', function(test){
// TODO: add to stats
var percent = stats.tests / total * 100 | 0;
if (progress) {
progress.update(percent).draw(ctx);
}
// update stats
var ms = new Date - stats.start;
stat.find('.passes em').text(stats.passes);
stat.find('.failures em').text(stats.failures);
stat.find('.duration em').text((ms / 1000).toFixed(2));
// test
if (test.passed) {
var el = $('<div class="test pass"><h2>' + escape(test.title) + '</h2></div>')
} else if (test.pending) {
var el = $('<div class="test pass pending"><h2>' + escape(test.title) + '</h2></div>')
} else {
var el = $('<div class="test fail"><h2>' + escape(test.title) + '</h2></div>');
var str = test.err.stack || test.err;
// <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
// check for the result of the stringifying.
if ('[object Error]' == str) str = test.err.message;
$('<pre class="error">' + escape(str) + '</pre>').appendTo(el);
}
// toggle code
el.find('h2').toggle(function(){
pre && pre.slideDown('fast');
}, function(){
pre && pre.slideUp('fast');
});
// code
// TODO: defer
if (!test.pending) {
var code = escape(clean(test.fn.toString()));
var pre = $('<pre><code>' + code + '</code></pre>');
pre.appendTo(el).hide();
}
stack[0].append(el);
});
}
/**
* Display error `msg`.
*/
function error(msg) {
$('<div id="error">' + msg + '</div>').appendTo('body');
}
/**
* Strip the function definition from `str`,
* and re-indent for pre whitespace.
*/
function clean(str) {
str = str
.replace(/^function *\(.*\) *{/, '')
.replace(/\s+\}$/, '');
var spaces = str.match(/^\n?( *)/)[1].length
, re = new RegExp('^ {' + spaces + '}', 'gm');
str = str
.replace(re, '')
.replace(/^\s+/, '');
return str;
}