/** * 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 = ''; /** * 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 = $('

' + suite.title + '

'); // container stack[0].append(el); stack.unshift($('
')); 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 = $('

' + escape(test.title) + '

') } else if (test.pending) { var el = $('

' + escape(test.title) + '

') } else { var el = $('

' + escape(test.title) + '

'); 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; $('
' + escape(str) + '
').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 = $('
' + code + '
'); pre.appendTo(el).hide(); } stack[0].append(el); }); } /** * Display error `msg`. */ function error(msg) { $('
' + msg + '
').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; }