vendor/assets/javascripts/mocha.js in mocha_rails-0.0.3 vs vendor/assets/javascripts/mocha.js in mocha_rails-0.0.4
- old
+ new
@@ -55,10 +55,14 @@
}
};
}); // module: browser/debug.js
+require.register("browser/diff.js", function(module, exports, require){
+
+}); // module: browser/diff.js
+
require.register("browser/events.js", function(module, exports, require){
/**
* Module exports.
*/
@@ -511,10 +515,15 @@
module.exports = function(suite){
var suites = [suite];
suite.on('pre-require', function(context){
+ // noop variants
+
+ context.xdescribe = function(){};
+ context.xit = function(){};
+
/**
* Execute before running tests.
*/
context.before = function(fn){
@@ -844,34 +853,189 @@
* Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
+ * Module dependencies.
+ */
+
+var path = require('browser/path');
+
+/**
+ * Expose `Mocha`.
+ */
+
+exports = module.exports = Mocha;
+
+/**
* Library version.
*/
-exports.version = '0.12.0';
+exports.version = '1.0.0';
+/**
+ * Expose internals.
+ */
+
exports.utils = require('./utils');
exports.interfaces = require('./interfaces');
exports.reporters = require('./reporters');
exports.Runnable = require('./runnable');
exports.Context = require('./context');
exports.Runner = require('./runner');
exports.Suite = require('./suite');
exports.Hook = require('./hook');
exports.Test = require('./test');
+/**
+ * Return image `name` path.
+ *
+ * @param {String} name
+ * @return {String}
+ * @api private
+ */
+
+function image(name) {
+ return __dirname + '/../images/' + name + '.png';
+}
+
+/**
+ * Setup mocha with `options`.
+ *
+ * Options:
+ *
+ * - `ui` name "bdd", "tdd", "exports" etc
+ * - `reporter` reporter instance, defaults to `mocha.reporters.Dot`
+ * - `globals` array of accepted globals
+ * - `timeout` timeout in milliseconds
+ * - `ignoreLeaks` ignore global leaks
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+function Mocha(options) {
+ options = options || {};
+ this.files = [];
+ this.options = options;
+ this.suite = new exports.Suite('', new exports.Context);
+ this.ui(options.ui);
+ this.reporter(options.reporter);
+ if (options.timeout) this.suite.timeout(options.timeout);
+}
+
+/**
+ * Add test `file`.
+ *
+ * @param {String} file
+ * @api public
+ */
+
+Mocha.prototype.addFile = function(file){
+ this.files.push(file);
+ return this;
+};
+
+/**
+ * Set reporter to `name`, defaults to "dot".
+ *
+ * @param {String} name
+ * @api public
+ */
+
+Mocha.prototype.reporter = function(name){
+ name = name || 'dot';
+ this._reporter = require('./reporters/' + name);
+ if (!this._reporter) throw new Error('invalid reporter "' + name + '"');
+ return this;
+};
+
+/**
+ * Set test UI `name`, defaults to "bdd".
+ *
+ * @param {String} bdd
+ * @api public
+ */
+
+Mocha.prototype.ui = function(name){
+ name = name || 'bdd';
+ this._ui = exports.interfaces[name];
+ if (!this._ui) throw new Error('invalid interface "' + name + '"');
+ this._ui = this._ui(this.suite);
+ return this;
+};
+
+/**
+ * Load registered files.
+ *
+ * @api private
+ */
+
+Mocha.prototype.loadFiles = function(){
+ var suite = this.suite;
+ this.files.forEach(function(file){
+ file = path.resolve(file);
+ suite.emit('pre-require', global, file);
+ suite.emit('require', require(file), file);
+ suite.emit('post-require', global, file);
+ });
+};
+
+/**
+ * Enable growl support.
+ *
+ * @api private
+ */
+
+Mocha.prototype.growl = function(runner, reporter) {
+ var notify = require('growl');
+
+ runner.on('end', function(){
+ var stats = reporter.stats;
+ if (stats.failures) {
+ var msg = stats.failures + ' of ' + runner.total + ' tests failed';
+ notify(msg, { title: 'Failed', image: image('fail') });
+ } else {
+ notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
+ title: 'Passed'
+ , image: image('pass')
+ });
+ }
+ });
+};
+
+/**
+ * Run tests and invoke `fn()` when complete.
+ *
+ * @param {Function} fn
+ * @return {Runner}
+ * @api public
+ */
+
+Mocha.prototype.run = function(fn){
+ this.loadFiles();
+ var suite = this.suite;
+ var options = this.options;
+ var runner = new exports.Runner(suite);
+ var reporter = new this._reporter(runner);
+ runner.ignoreLeaks = options.ignoreLeaks;
+ if (options.grep) runner.grep(options.grep);
+ if (options.globals) runner.globals(options.globals);
+ if (options.growl) this.growl(runner, reporter);
+ return runner.run(fn);
+};
+
}); // module: mocha.js
require.register("reporters/base.js", function(module, exports, require){
/**
* Module dependencies.
*/
-var tty = require('browser/tty');
+var tty = require('browser/tty')
+ , diff = require('browser/diff');
/**
* Check if both stdio streams are associated with a tty.
*/
@@ -908,10 +1072,13 @@
, 'fast': 90
, 'medium': 33
, 'slow': 31
, 'green': 32
, 'light': 90
+ , 'diff gutter': 90
+ , 'diff added': 42
+ , 'diff removed': 41
};
/**
* Color `str` with the given `type`,
* allowing colors to be disabled,
@@ -995,14 +1162,48 @@
// msg
var err = test.err
, message = err.message || ''
, stack = err.stack || message
, index = stack.indexOf(message) + message.length
- , msg = stack.slice(0, index);
+ , msg = stack.slice(0, index)
+ , actual = err.actual
+ , expected = err.expected;
+ // actual / expected diff
+ if ('string' == typeof actual && 'string' == typeof expected) {
+ var len = Math.max(actual.length, expected.length);
+
+ if (len < 20) msg = errorDiff(err, 'Chars');
+ else msg = errorDiff(err, 'Words');
+
+ // linenos
+ var lines = msg.split('\n');
+ if (lines.length > 4) {
+ var width = String(lines.length).length;
+ msg = lines.map(function(str, i){
+ return pad(++i, width) + ' |' + ' ' + str;
+ }).join('\n');
+ }
+
+ // legend
+ msg = '\n'
+ + color('diff removed', 'actual')
+ + ' '
+ + color('diff added', 'expected')
+ + '\n\n'
+ + msg
+ + '\n';
+
+ // indent
+ msg = msg.replace(/^/gm, ' ');
+
+ fmt = color('error title', ' %s) %s:\n%s')
+ + color('error stack', '\n%s\n');
+ }
+
// indent stack trace without msg
- stack = stack.slice(index + 1)
+ stack = stack.slice(index ? index + 1 : index)
.replace(/^/gm, ' ');
console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
});
};
@@ -1099,10 +1300,55 @@
console.log(fmt, stats.tests || 0, stats.duration);
console.log();
};
+/**
+ * Pad the given `str` to `len`.
+ *
+ * @param {String} str
+ * @param {String} len
+ * @return {String}
+ * @api private
+ */
+
+function pad(str, len) {
+ str = String(str);
+ return Array(len - str.length + 1).join(' ') + str;
+}
+
+/**
+ * Return a character diff for `err`.
+ *
+ * @param {Error} err
+ * @return {String}
+ * @api private
+ */
+
+function errorDiff(err, type) {
+ return diff['diff' + type](err.actual, err.expected).map(function(str){
+ if (str.added) return colorLines('diff added', str.value);
+ if (str.removed) return colorLines('diff removed', str.value);
+ return str.value;
+ }).join('');
+}
+
+/**
+ * Color lines for `str`, using the color `name`.
+ *
+ * @param {String} name
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+function colorLines(name, str) {
+ return str.split('\n').map(function(str){
+ return color(name, str);
+ }).join('\n');
+}
+
}); // module: reporters/base.js
require.register("reporters/doc.js", function(module, exports, require){
/**
@@ -1245,10 +1491,57 @@
Dot.prototype = new Base;
Dot.prototype.constructor = Dot;
}); // module: reporters/dot.js
+require.register("reporters/html-cov.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var JSONCov = require('./json-cov')
+ , fs = require('browser/fs');
+
+/**
+ * Expose `HTMLCov`.
+ */
+
+exports = module.exports = HTMLCov;
+
+/**
+ * Initialize a new `JsCoverage` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function HTMLCov(runner) {
+ var jade = require('jade')
+ , file = __dirname + '/templates/coverage.jade'
+ , str = fs.readFileSync(file, 'utf8')
+ , fn = jade.compile(str, { filename: file })
+ , self = this;
+
+ JSONCov.call(this, runner, false);
+
+ runner.on('end', function(){
+ process.stdout.write(fn({
+ cov: self.cov
+ , coverageClass: coverageClass
+ }));
+ });
+}
+
+function coverageClass(n) {
+ if (n >= 75) return 'high';
+ if (n >= 50) return 'medium';
+ if (n >= 25) return 'low';
+ return 'terrible';
+}
+}); // module: reporters/html-cov.js
+
require.register("reporters/html.js", function(module, exports, require){
/**
* Module dependencies.
*/
@@ -1283,41 +1576,45 @@
*/
function HTML(runner) {
Base.call(this, runner);
- // TODO: clean up
-
var self = this
, stats = this.stats
, total = runner.total
- , root = $('#mocha')
+ , root = document.getElementById('mocha')
+ , stat = fragment(statsTemplate)
+ , items = stat.getElementsByTagName('li')
+ , passes = items[1].getElementsByTagName('em')[0]
+ , failures = items[2].getElementsByTagName('em')[0]
+ , duration = items[3].getElementsByTagName('em')[0]
+ , canvas = stat.getElementsByTagName('canvas')[0]
, 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 (!root) return error('#mocha div missing, add it to your document');
+ root.appendChild(stat);
+
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>');
+ var el = fragment('<div class="suite"><h1>%s</h1></div>', suite.title);
// container
- stack[0].append(el);
- stack.unshift($('<div>'));
- el.append(stack[0]);
+ stack[0].appendChild(el);
+ stack.unshift(document.createElement('div'));
+ el.appendChild(stack[0]);
});
runner.on('suite end', function(suite){
if (suite.root) return;
stack.shift();
@@ -1328,64 +1625,117 @@
});
runner.on('test end', function(test){
// TODO: add to stats
var percent = stats.tests / total * 100 | 0;
+ if (progress) progress.update(percent).draw(ctx);
- 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));
+ text(passes, stats.passes);
+ text(failures, stats.failures);
+ text(duration, (ms / 1000).toFixed(2));
// test
- if (test.passed) {
- var el = $('<div class="test pass"><h2>' + escape(test.title) + '</h2></div>')
+ if ('passed' == test.state) {
+ var el = fragment('<div class="test pass"><h2>%e</h2></div>', test.title);
} else if (test.pending) {
- var el = $('<div class="test pass pending"><h2>' + escape(test.title) + '</h2></div>')
+ var el = fragment('<div class="test pass pending"><h2>%e</h2></div>', test.title);
} else {
- var el = $('<div class="test fail"><h2>' + escape(test.title) + '</h2></div>');
- var str = test.err.stack || test.err;
+ var el = fragment('<div class="test fail"><h2>%e</h2></div>', test.title);
+ var str = test.err.stack || test.err.toString();
+ // FF / Opera do not add the message
+ if (!~str.indexOf(test.err.message)) {
+ str = test.err.message + '\n' + str;
+ }
+
// <=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);
+ // Safari doesn't give you a stack. Let's at least provide a source line.
+ if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
+ str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
+ }
+
+ el.appendChild(fragment('<pre class="error">%e</pre>', str));
}
// toggle code
- el.find('h2').toggle(function(){
- pre && pre.slideDown('fast');
- }, function(){
- pre && pre.slideUp('fast');
+ var h2 = el.getElementsByTagName('h2')[0];
+
+ on(h2, 'click', function(){
+ pre.style.display = 'none' == pre.style.display
+ ? 'block'
+ : 'none';
});
// code
// TODO: defer
if (!test.pending) {
- var code = escape(clean(test.fn.toString()));
- var pre = $('<pre><code>' + code + '</code></pre>');
- pre.appendTo(el).hide();
+ var pre = fragment('<pre><code>%e</code></pre>', clean(test.fn.toString()));
+ el.appendChild(pre);
+ pre.style.display = 'none';
}
- stack[0].append(el);
+
+ stack[0].appendChild(el);
});
}
/**
* Display error `msg`.
*/
function error(msg) {
- $('<div id="error">' + msg + '</div>').appendTo('body');
+ document.body.appendChild(fragment('<div id="error">%s</div>', msg));
}
/**
+ * Return a DOM fragment from `html`.
+ */
+
+function fragment(html) {
+ var args = arguments
+ , div = document.createElement('div')
+ , i = 1;
+
+ div.innerHTML = html.replace(/%([se])/g, function(_, type){
+ switch (type) {
+ case 's': return String(args[i++]);
+ case 'e': return escape(args[i++]);
+ }
+ });
+
+ return div.firstChild;
+}
+
+/**
+ * Set `el` text to `str`.
+ */
+
+function text(el, str) {
+ if (el.textContent) {
+ el.textContent = str;
+ } else {
+ el.innerText = str;
+ }
+}
+
+/**
+ * Listen on `event` with callback `fn`.
+ */
+
+function on(el, event, fn) {
+ if (el.addEventListener) {
+ el.addEventListener(event, fn, false);
+ } else {
+ el.attachEvent('on' + event, fn);
+ }
+}
+
+/**
* Strip the function definition from `str`,
* and re-indent for pre whitespace.
*/
function clean(str) {
@@ -1412,18 +1762,175 @@
exports.Doc = require('./doc');
exports.TAP = require('./tap');
exports.JSON = require('./json');
exports.HTML = require('./html');
exports.List = require('./list');
+exports.Min = require('./min');
exports.Spec = require('./spec');
exports.Progress = require('./progress');
exports.Landing = require('./landing');
+exports.JSONCov = require('./json-cov');
+exports.HTMLCov = require('./html-cov');
exports.JSONStream = require('./json-stream');
exports.XUnit = require('./xunit')
+exports.Teamcity = require('./teamcity')
}); // module: reporters/index.js
+require.register("reporters/json-cov.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `JSONCov`.
+ */
+
+exports = module.exports = JSONCov;
+
+/**
+ * Initialize a new `JsCoverage` reporter.
+ *
+ * @param {Runner} runner
+ * @param {Boolean} output
+ * @api public
+ */
+
+function JSONCov(runner, output) {
+ var self = this
+ , output = 1 == arguments.length ? true : output;
+
+ Base.call(this, runner);
+
+ var tests = []
+ , failures = []
+ , passes = [];
+
+ runner.on('test end', function(test){
+ tests.push(test);
+ });
+
+ runner.on('pass', function(test){
+ passes.push(test);
+ });
+
+ runner.on('fail', function(test){
+ failures.push(test);
+ });
+
+ runner.on('end', function(){
+ var cov = global._$jscoverage || {};
+ var result = self.cov = map(cov);
+ result.stats = self.stats;
+ result.tests = tests.map(clean);
+ result.failures = failures.map(clean);
+ result.passes = passes.map(clean);
+ if (!output) return;
+ process.stdout.write(JSON.stringify(result, null, 2 ));
+ });
+}
+
+/**
+ * Map jscoverage data to a JSON structure
+ * suitable for reporting.
+ *
+ * @param {Object} cov
+ * @return {Object}
+ * @api private
+ */
+
+function map(cov) {
+ var ret = {
+ instrumentation: 'node-jscoverage'
+ , sloc: 0
+ , hits: 0
+ , misses: 0
+ , coverage: 0
+ , files: []
+ };
+
+ for (var filename in cov) {
+ var data = coverage(filename, cov[filename]);
+ ret.files.push(data);
+ ret.hits += data.hits;
+ ret.misses += data.misses;
+ ret.sloc += data.sloc;
+ }
+
+ if (ret.sloc > 0) {
+ ret.coverage = (ret.hits / ret.sloc) * 100;
+ }
+
+ return ret;
+};
+
+/**
+ * Map jscoverage data for a single source file
+ * to a JSON structure suitable for reporting.
+ *
+ * @param {String} filename name of the source file
+ * @param {Object} data jscoverage coverage data
+ * @return {Object}
+ * @api private
+ */
+
+function coverage(filename, data) {
+ var ret = {
+ filename: filename,
+ coverage: 0,
+ hits: 0,
+ misses: 0,
+ sloc: 0,
+ source: {}
+ };
+
+ data.source.forEach(function(line, num){
+ num++;
+
+ if (data[num] === 0) {
+ ret.misses++;
+ ret.sloc++;
+ } else if (data[num] !== undefined) {
+ ret.hits++;
+ ret.sloc++;
+ }
+
+ ret.source[num] = {
+ source: line
+ , coverage: data[num] === undefined
+ ? ''
+ : data[num]
+ };
+ });
+
+ ret.coverage = ret.hits / ret.sloc * 100;
+
+ return ret;
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+ return {
+ title: test.title
+ , fullTitle: test.fullTitle()
+ , duration: test.duration
+ }
+}
+
+}); // module: reporters/json-cov.js
+
require.register("reporters/json-stream.js", function(module, exports, require){
/**
* Module dependencies.
*/
@@ -1535,11 +2042,11 @@
, tests: tests.map(clean)
, failures: failures.map(clean)
, passes: passes.map(clean)
};
- process.stdout.write(JSON.stringify(obj));
+ process.stdout.write(JSON.stringify(obj, null, 2));
});
}
/**
* Return a plain-object representation of `test`
@@ -1627,11 +2134,11 @@
var col = -1 == crashed
? width * ++n / total | 0
: crashed;
// show the crash
- if (test.failed) {
+ if ('failed' == test.state) {
plane = color('plane crash', '✈');
crashed = col;
}
// render landing strip
@@ -1729,10 +2236,166 @@
List.prototype.constructor = List;
}); // module: reporters/list.js
+require.register("reporters/markdown.js", function(module, exports, require){
+
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , utils = require('../utils');
+
+/**
+ * Expose `Markdown`.
+ */
+
+exports = module.exports = Markdown;
+
+/**
+ * Initialize a new `Markdown` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Markdown(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , total = runner.total
+ , level = 0
+ , buf = '';
+
+ function title(str) {
+ return Array(level).join('#') + ' ' + str;
+ }
+
+ function indent() {
+ return Array(level).join(' ');
+ }
+
+ function mapTOC(suite, obj) {
+ var ret = obj;
+ obj = obj[suite.title] = obj[suite.title] || { suite: suite };
+ suite.suites.forEach(function(suite){
+ mapTOC(suite, obj);
+ });
+ return ret;
+ }
+
+ function stringifyTOC(obj, level) {
+ ++level;
+ var buf = '';
+ var link;
+ for (var key in obj) {
+ if ('suite' == key) continue;
+ if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
+ if (key) buf += Array(level).join(' ') + link;
+ buf += stringifyTOC(obj[key], level);
+ }
+ --level;
+ return buf;
+ }
+
+ function generateTOC(suite) {
+ var obj = mapTOC(suite, {});
+ return stringifyTOC(obj, 0);
+ }
+
+ generateTOC(runner.suite);
+
+ runner.on('suite', function(suite){
+ ++level;
+ var slug = utils.slug(suite.fullTitle());
+ buf += '<a name="' + slug + '" />' + '\n';
+ buf += title(suite.title) + '\n';
+ });
+
+ runner.on('suite end', function(suite){
+ --level;
+ });
+
+ runner.on('pass', function(test){
+ var code = clean(test.fn.toString());
+ buf += test.title + '.\n';
+ buf += '\n```js';
+ buf += code + '\n';
+ buf += '```\n\n';
+ });
+
+ runner.on('end', function(){
+ process.stdout.write('# TOC\n');
+ process.stdout.write(generateTOC(runner.suite));
+ process.stdout.write(buf);
+ });
+}
+
+/**
+ * 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, '');
+
+ return str;
+}
+}); // module: reporters/markdown.js
+
+require.register("reporters/min.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `Min`.
+ */
+
+exports = module.exports = Min;
+
+/**
+ * Initialize a new `Min` minimal test reporter (best used with --watch).
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Min(runner) {
+ Base.call(this, runner);
+
+ runner.on('start', function(){
+ // clear screen
+ process.stdout.write('\033[2J');
+ // set cursor position
+ process.stdout.write('\033[1;3H');
+ });
+
+ runner.on('end', this.epilogue.bind(this));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+Min.prototype = new Base;
+Min.prototype.constructor = Min;
+
+}); // module: reporters/min.js
+
require.register("reporters/progress.js", function(module, exports, require){
/**
* Module dependencies.
*/
@@ -2107,11 +2770,11 @@
classname: test.parent.fullTitle()
, name: test.title
, time: test.duration / 1000
};
- if (test.failed) {
+ if ('failed' == test.state) {
var err = test.err;
attrs.message = escape(err.message);
console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
} else if (test.pending) {
console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
@@ -2434,11 +3097,11 @@
* @api private
*/
Runner.prototype.fail = function(test, err){
++this.failures;
- test.failed = true;
+ test.state = 'failed';
this.emit('fail', test, err);
};
/**
* Fail the given `hook` with `err`.
@@ -2641,11 +3304,11 @@
self.fail(test, err);
self.emit('test end', test);
return self.hookUp('afterEach', next);
}
- test.passed = true;
+ test.state = 'passed';
self.emit('pass', test);
self.emit('test end', test);
self.hookUp('afterEach', next);
});
});
@@ -2698,11 +3361,11 @@
*/
Runner.prototype.uncaught = function(err){
debug('uncaught exception');
var runnable = this.currentRunnable;
- if (runnable.failed) return;
+ if ('failed' == runnable.state) return;
runnable.clearTimeout();
err.uncaught = true;
this.fail(runnable, err);
// recover from test
@@ -2832,10 +3495,11 @@
*/
Suite.prototype.clone = function(){
var suite = new Suite(this.title);
debug('clone');
+ suite.ctx = this.ctx;
suite.timeout(this.timeout());
suite.bail(this.bail());
return suite;
};
@@ -3176,13 +3840,13 @@
exports.keys = Object.keys || function(obj) {
var keys = []
, has = Object.prototype.hasOwnProperty // for `window` on <=IE8
- for (var i in obj) {
- if (has.call(obj, i)) {
- keys.push(i);
+ for (var key in obj) {
+ if (has.call(obj, key)) {
+ keys.push(key);
}
}
return keys;
};
@@ -3216,11 +3880,11 @@
/**
* Lookup files in the given `dir`.
*
* @return {Array}
- * @api public
+ * @api private
*/
exports.files = function(dir, ret){
ret = ret || [];
@@ -3235,10 +3899,24 @@
}
});
return ret;
};
+
+/**
+ * Compute a slug from the given `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ */
+
+exports.slug = function(str){
+ return str
+ .toLowerCase()
+ .replace(/ +/g, '-')
+ .replace(/[^-\w]/g, '');
+};
}); // module: utils.js
/**
* Node shims.
*
@@ -3308,35 +3986,40 @@
// boot
;(function(){
var suite = new mocha.Suite('', new mocha.Context)
, utils = mocha.utils
- , Reporter = mocha.reporters.HTML
+ , options = {}
- $(function(){
- $('code').each(function(){
- $(this).html(highlight($(this).text()));
- });
- });
-
/**
* Highlight the given string of `js`.
*/
function highlight(js) {
return js
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
- .replace(/('.*')/gm, '<span class="string">$1</span>')
+ .replace(/('.*?')/gm, '<span class="string">$1</span>')
.replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
.replace(/(\d+)/gm, '<span class="number">$1</span>')
.replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
.replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
}
/**
+ * Highlight code contents.
+ */
+
+ function highlightCode() {
+ var code = document.getElementsByTagName('code');
+ for (var i = 0, len = code.length; i < len; ++i) {
+ code[i].innerHTML = highlight(code[i].innerHTML);
+ }
+ }
+
+ /**
* Parse the given `qs`.
*/
function parse(qs) {
return utils.reduce(qs.replace('?', '').split('&'), function(obj, pair){
@@ -3348,16 +4031,20 @@
return obj;
}, {});
}
/**
- * Setup mocha with the give `ui` name.
+ * Setup mocha with the given setting options.
*/
- mocha.setup = function(ui){
- ui = mocha.interfaces[ui];
+ mocha.setup = function(opts){
+ if ('string' === typeof opts) options.ui = opts;
+ else options = opts;
+
+ ui = mocha.interfaces[options.ui];
if (!ui) throw new Error('invalid mocha interface "' + ui + '"');
+ if (options.timeout) suite.timeout(options.timeout);
ui(suite);
suite.emit('pre-require', window);
};
/**
@@ -3365,17 +4052,17 @@
*/
mocha.run = function(){
suite.emit('run');
var runner = new mocha.Runner(suite);
+ var Reporter = options.reporter || mocha.reporters.HTML;
var reporter = new Reporter(runner);
var query = parse(window.location.search || "");
if (query.grep) runner.grep(new RegExp(query.grep));
- runner.on('end', function(){
- $('code').each(function(){
- $(this).html(highlight($(this).text()));
- });
- });
+ if (options.ignoreLeaks) runner.ignoreLeaks = true;
+ if (options.globals) runner.globals(options.globals);
+ runner.globals(['location']);
+ runner.on('end', highlightCode);
return runner.run();
};
})();
})();
\ No newline at end of file