You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
3.5 KiB
154 lines
3.5 KiB
|
|
/** |
|
* 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; |
|
}
|
|
|