155 lines
3.5 KiB
JavaScript
155 lines
3.5 KiB
JavaScript
|
|
||
|
/**
|
||
|
* 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;
|
||
|
}
|