Merge branch 'hotfix/21.56.9' into master
[gitter.git] / public / repo / mocha / mocha.js
blob48297491cba2c62aadbcd3e2b28a4b4f71a6e8e5
1 define([], function() {
2 (function() {
3 // CommonJS require()
5 function require(p) {
6 var path = require.resolve(p),
7 mod = require.modules[path];
8 if (!mod) throw new Error('failed to require "' + p + '"');
9 if (!mod.exports) {
10 mod.exports = {};
11 mod.call(mod.exports, mod, mod.exports, require.relative(path));
13 return mod.exports;
16 require.modules = {};
18 require.resolve = function(path) {
19 var orig = path,
20 reg = path + '.js',
21 index = path + '/index.js';
22 return (require.modules[reg] && reg) || (require.modules[index] && index) || orig;
25 require.register = function(path, fn) {
26 require.modules[path] = fn;
29 require.relative = function(parent) {
30 return function(p) {
31 if ('.' != p.charAt(0)) return require(p);
33 var path = parent.split('/'),
34 segs = p.split('/');
35 path.pop();
37 for (var i = 0; i < segs.length; i++) {
38 var seg = segs[i];
39 if ('..' == seg) path.pop();
40 else if ('.' != seg) path.push(seg);
43 return require(path.join('/'));
47 require.register('browser/debug.js', function(module, exports, require) {
48 module.exports = function(type) {
49 return function() {};
51 }); // module: browser/debug.js
53 require.register('browser/diff.js', function(module, exports, require) {
54 /* See license.txt for terms of usage */
57 * Text diff implementation.
59 * This library supports the following APIS:
60 * JsDiff.diffChars: Character by character diff
61 * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
62 * JsDiff.diffLines: Line based diff
64 * JsDiff.diffCss: Diff targeted at CSS content
66 * These methods are based on the implementation proposed in
67 * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
68 * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
70 var JsDiff = (function() {
71 function clonePath(path) {
72 return { newPos: path.newPos, components: path.components.slice(0) };
74 function removeEmpty(array) {
75 var ret = [];
76 for (var i = 0; i < array.length; i++) {
77 if (array[i]) {
78 ret.push(array[i]);
81 return ret;
83 function escapeHTML(s) {
84 var n = s;
85 n = n.replace(/&/g, '&amp;');
86 n = n.replace(/</g, '&lt;');
87 n = n.replace(/>/g, '&gt;');
88 n = n.replace(/"/g, '&quot;');
90 return n;
93 var fbDiff = function(ignoreWhitespace) {
94 this.ignoreWhitespace = ignoreWhitespace;
96 fbDiff.prototype = {
97 diff: function(oldString, newString) {
98 // Handle the identity case (this is due to unrolling editLength == 0
99 if (newString == oldString) {
100 return [{ value: newString }];
102 if (!newString) {
103 return [{ value: oldString, removed: true }];
105 if (!oldString) {
106 return [{ value: newString, added: true }];
109 newString = this.tokenize(newString);
110 oldString = this.tokenize(oldString);
112 var newLen = newString.length,
113 oldLen = oldString.length;
114 var maxEditLength = newLen + oldLen;
115 var bestPath = [{ newPos: -1, components: [] }];
117 // Seed editLength = 0
118 var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
119 if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
120 return bestPath[0].components;
123 for (var editLength = 1; editLength <= maxEditLength; editLength++) {
124 for (
125 var diagonalPath = -1 * editLength;
126 diagonalPath <= editLength;
127 diagonalPath += 2
129 var basePath;
130 var addPath = bestPath[diagonalPath - 1],
131 removePath = bestPath[diagonalPath + 1];
132 oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
133 if (addPath) {
134 // No one else is going to attempt to use this value, clear it
135 bestPath[diagonalPath - 1] = undefined;
138 var canAdd = addPath && addPath.newPos + 1 < newLen;
139 var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
140 if (!canAdd && !canRemove) {
141 bestPath[diagonalPath] = undefined;
142 continue;
145 // Select the diagonal that we want to branch from. We select the prior
146 // path whose position in the new string is the farthest from the origin
147 // and does not pass the bounds of the diff graph
148 if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
149 basePath = clonePath(removePath);
150 this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
151 } else {
152 basePath = clonePath(addPath);
153 basePath.newPos++;
154 this.pushComponent(
155 basePath.components,
156 newString[basePath.newPos],
157 true,
158 undefined
162 var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);
164 if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
165 return basePath.components;
166 } else {
167 bestPath[diagonalPath] = basePath;
173 pushComponent: function(components, value, added, removed) {
174 var last = components[components.length - 1];
175 if (last && last.added === added && last.removed === removed) {
176 // We need to clone here as the component clone operation is just
177 // as shallow array clone
178 components[components.length - 1] = {
179 value: this.join(last.value, value),
180 added: added,
181 removed: removed
183 } else {
184 components.push({ value: value, added: added, removed: removed });
187 extractCommon: function(basePath, newString, oldString, diagonalPath) {
188 var newLen = newString.length,
189 oldLen = oldString.length,
190 newPos = basePath.newPos,
191 oldPos = newPos - diagonalPath;
192 while (
193 newPos + 1 < newLen &&
194 oldPos + 1 < oldLen &&
195 this.equals(newString[newPos + 1], oldString[oldPos + 1])
197 newPos++;
198 oldPos++;
200 this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
202 basePath.newPos = newPos;
203 return oldPos;
206 equals: function(left, right) {
207 var reWhitespace = /\S/;
208 if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
209 return true;
210 } else {
211 return left == right;
214 join: function(left, right) {
215 return left + right;
217 tokenize: function(value) {
218 return value;
222 var CharDiff = new fbDiff();
224 var WordDiff = new fbDiff(true);
225 WordDiff.tokenize = function(value) {
226 return removeEmpty(value.split(/(\s+|\b)/));
229 var CssDiff = new fbDiff(true);
230 CssDiff.tokenize = function(value) {
231 return removeEmpty(value.split(/([{}:;,]|\s+)/));
234 var LineDiff = new fbDiff();
235 LineDiff.tokenize = function(value) {
236 return value.split(/^/m);
239 return {
240 diffChars: function(oldStr, newStr) {
241 return CharDiff.diff(oldStr, newStr);
243 diffWords: function(oldStr, newStr) {
244 return WordDiff.diff(oldStr, newStr);
246 diffLines: function(oldStr, newStr) {
247 return LineDiff.diff(oldStr, newStr);
250 diffCss: function(oldStr, newStr) {
251 return CssDiff.diff(oldStr, newStr);
254 createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
255 var ret = [];
257 ret.push('Index: ' + fileName);
258 ret.push('===================================================================');
259 ret.push(
260 '--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader)
262 ret.push(
263 '+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader)
266 var diff = LineDiff.diff(oldStr, newStr);
267 if (!diff[diff.length - 1].value) {
268 diff.pop(); // Remove trailing newline add
270 diff.push({ value: '', lines: [] }); // Append an empty value to make cleanup easier
272 function contextLines(lines) {
273 return lines.map(function(entry) {
274 return ' ' + entry;
277 function eofNL(curRange, i, current) {
278 var last = diff[diff.length - 2],
279 isLast = i === diff.length - 2,
280 isLastOfType =
281 i === diff.length - 3 &&
282 (current.added === !last.added || current.removed === !last.removed);
284 // Figure out if this is the last line for the given file and missing NL
285 if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
286 curRange.push('\\ No newline at end of file');
290 var oldRangeStart = 0,
291 newRangeStart = 0,
292 curRange = [],
293 oldLine = 1,
294 newLine = 1;
295 for (var i = 0; i < diff.length; i++) {
296 var current = diff[i],
297 lines = current.lines || current.value.replace(/\n$/, '').split('\n');
298 current.lines = lines;
300 if (current.added || current.removed) {
301 if (!oldRangeStart) {
302 var prev = diff[i - 1];
303 oldRangeStart = oldLine;
304 newRangeStart = newLine;
306 if (prev) {
307 curRange = contextLines(prev.lines.slice(-4));
308 oldRangeStart -= curRange.length;
309 newRangeStart -= curRange.length;
312 curRange.push.apply(
313 curRange,
314 lines.map(function(entry) {
315 return (current.added ? '+' : '-') + entry;
318 eofNL(curRange, i, current);
320 if (current.added) {
321 newLine += lines.length;
322 } else {
323 oldLine += lines.length;
325 } else {
326 if (oldRangeStart) {
327 // Close out any changes that have been output (or join overlapping)
328 if (lines.length <= 8 && i < diff.length - 2) {
329 // Overlapping
330 curRange.push.apply(curRange, contextLines(lines));
331 } else {
332 // end the range and output
333 var contextSize = Math.min(lines.length, 4);
334 ret.push(
335 '@@ -' +
336 oldRangeStart +
337 ',' +
338 (oldLine - oldRangeStart + contextSize) +
339 ' +' +
340 newRangeStart +
341 ',' +
342 (newLine - newRangeStart + contextSize) +
343 ' @@'
345 ret.push.apply(ret, curRange);
346 ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
347 if (lines.length <= 4) {
348 eofNL(ret, i, current);
351 oldRangeStart = 0;
352 newRangeStart = 0;
353 curRange = [];
356 oldLine += lines.length;
357 newLine += lines.length;
361 return ret.join('\n') + '\n';
364 convertChangesToXML: function(changes) {
365 var ret = [];
366 for (var i = 0; i < changes.length; i++) {
367 var change = changes[i];
368 if (change.added) {
369 ret.push('<ins>');
370 } else if (change.removed) {
371 ret.push('<del>');
374 ret.push(escapeHTML(change.value));
376 if (change.added) {
377 ret.push('</ins>');
378 } else if (change.removed) {
379 ret.push('</del>');
382 return ret.join('');
385 })();
387 if (typeof module !== 'undefined') {
388 module.exports = JsDiff;
390 }); // module: browser/diff.js
392 require.register('browser/events.js', function(module, exports, require) {
394 * Module exports.
397 exports.EventEmitter = EventEmitter;
400 * Check if `obj` is an array.
403 function isArray(obj) {
404 return '[object Array]' == {}.toString.call(obj);
408 * Event emitter constructor.
410 * @api public
413 function EventEmitter() {}
416 * Adds a listener.
418 * @api public
421 EventEmitter.prototype.on = function(name, fn) {
422 if (!this.$events) {
423 this.$events = {};
426 if (!this.$events[name]) {
427 this.$events[name] = fn;
428 } else if (isArray(this.$events[name])) {
429 this.$events[name].push(fn);
430 } else {
431 this.$events[name] = [this.$events[name], fn];
434 return this;
437 EventEmitter.prototype.addListener = EventEmitter.prototype.on;
440 * Adds a volatile listener.
442 * @api public
445 EventEmitter.prototype.once = function(name, fn) {
446 var self = this;
448 function on() {
449 self.removeListener(name, on);
450 fn.apply(this, arguments);
453 on.listener = fn;
454 this.on(name, on);
456 return this;
460 * Removes a listener.
462 * @api public
465 EventEmitter.prototype.removeListener = function(name, fn) {
466 if (this.$events && this.$events[name]) {
467 var list = this.$events[name];
469 if (isArray(list)) {
470 var pos = -1;
472 for (var i = 0, l = list.length; i < l; i++) {
473 if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
474 pos = i;
475 break;
479 if (pos < 0) {
480 return this;
483 list.splice(pos, 1);
485 if (!list.length) {
486 delete this.$events[name];
488 } else if (list === fn || (list.listener && list.listener === fn)) {
489 delete this.$events[name];
493 return this;
497 * Removes all listeners for an event.
499 * @api public
502 EventEmitter.prototype.removeAllListeners = function(name) {
503 if (name === undefined) {
504 this.$events = {};
505 return this;
508 if (this.$events && this.$events[name]) {
509 this.$events[name] = null;
512 return this;
516 * Gets all listeners for a certain event.
518 * @api public
521 EventEmitter.prototype.listeners = function(name) {
522 if (!this.$events) {
523 this.$events = {};
526 if (!this.$events[name]) {
527 this.$events[name] = [];
530 if (!isArray(this.$events[name])) {
531 this.$events[name] = [this.$events[name]];
534 return this.$events[name];
538 * Emits an event.
540 * @api public
543 EventEmitter.prototype.emit = function(name) {
544 if (!this.$events) {
545 return false;
548 var handler = this.$events[name];
550 if (!handler) {
551 return false;
554 var args = [].slice.call(arguments, 1);
556 if ('function' == typeof handler) {
557 handler.apply(this, args);
558 } else if (isArray(handler)) {
559 var listeners = handler.slice();
561 for (var i = 0, l = listeners.length; i < l; i++) {
562 listeners[i].apply(this, args);
564 } else {
565 return false;
568 return true;
570 }); // module: browser/events.js
572 require.register('browser/fs.js', function(module, exports, require) {}); // module: browser/fs.js
574 require.register('browser/path.js', function(module, exports, require) {}); // module: browser/path.js
576 require.register('browser/progress.js', function(module, exports, require) {
578 * Expose `Progress`.
581 module.exports = Progress;
584 * Initialize a new `Progress` indicator.
587 function Progress() {
588 this.percent = 0;
589 this.size(0);
590 this.fontSize(11);
591 this.font('helvetica, arial, sans-serif');
595 * Set progress size to `n`.
597 * @param {Number} n
598 * @return {Progress} for chaining
599 * @api public
602 Progress.prototype.size = function(n) {
603 this._size = n;
604 return this;
608 * Set text to `str`.
610 * @param {String} str
611 * @return {Progress} for chaining
612 * @api public
615 Progress.prototype.text = function(str) {
616 this._text = str;
617 return this;
621 * Set font size to `n`.
623 * @param {Number} n
624 * @return {Progress} for chaining
625 * @api public
628 Progress.prototype.fontSize = function(n) {
629 this._fontSize = n;
630 return this;
634 * Set font `family`.
636 * @param {String} family
637 * @return {Progress} for chaining
640 Progress.prototype.font = function(family) {
641 this._font = family;
642 return this;
646 * Update percentage to `n`.
648 * @param {Number} n
649 * @return {Progress} for chaining
652 Progress.prototype.update = function(n) {
653 this.percent = n;
654 return this;
658 * Draw on `ctx`.
660 * @param {CanvasRenderingContext2d} ctx
661 * @return {Progress} for chaining
664 Progress.prototype.draw = function(ctx) {
665 var percent = Math.min(this.percent, 100),
666 size = this._size,
667 half = size / 2,
668 x = half,
669 y = half,
670 rad = half - 1,
671 fontSize = this._fontSize;
673 ctx.font = fontSize + 'px ' + this._font;
675 var angle = Math.PI * 2 * (percent / 100);
676 ctx.clearRect(0, 0, size, size);
678 // outer circle
679 ctx.strokeStyle = '#9f9f9f';
680 ctx.beginPath();
681 ctx.arc(x, y, rad, 0, angle, false);
682 ctx.stroke();
684 // inner circle
685 ctx.strokeStyle = '#eee';
686 ctx.beginPath();
687 ctx.arc(x, y, rad - 1, 0, angle, true);
688 ctx.stroke();
690 // text
691 var text = this._text || (percent | 0) + '%',
692 w = ctx.measureText(text).width;
694 ctx.fillText(text, x - w / 2 + 1, y + fontSize / 2 - 1);
696 return this;
698 }); // module: browser/progress.js
700 require.register('browser/tty.js', function(module, exports, require) {
701 exports.isatty = function() {
702 return true;
705 exports.getWindowSize = function() {
706 return [window.innerHeight, window.innerWidth];
708 }); // module: browser/tty.js
710 require.register('context.js', function(module, exports, require) {
712 * Expose `Context`.
715 module.exports = Context;
718 * Initialize a new `Context`.
720 * @api private
723 function Context() {}
726 * Set or get the context `Runnable` to `runnable`.
728 * @param {Runnable} runnable
729 * @return {Context}
730 * @api private
733 Context.prototype.runnable = function(runnable) {
734 if (0 == arguments.length) return this._runnable;
735 this.test = this._runnable = runnable;
736 return this;
740 * Set test timeout `ms`.
742 * @param {Number} ms
743 * @return {Context} self
744 * @api private
747 Context.prototype.timeout = function(ms) {
748 this.runnable().timeout(ms);
749 return this;
753 * Set test slowness threshold `ms`.
755 * @param {Number} ms
756 * @return {Context} self
757 * @api private
760 Context.prototype.slow = function(ms) {
761 this.runnable().slow(ms);
762 return this;
766 * Inspect the context void of `._runnable`.
768 * @return {String}
769 * @api private
772 Context.prototype.inspect = function() {
773 return JSON.stringify(
774 this,
775 function(key, val) {
776 if ('_runnable' == key) return;
777 if ('test' == key) return;
778 return val;
783 }); // module: context.js
785 require.register('hook.js', function(module, exports, require) {
787 * Module dependencies.
790 var Runnable = require('./runnable');
793 * Expose `Hook`.
796 module.exports = Hook;
799 * Initialize a new `Hook` with the given `title` and callback `fn`.
801 * @param {String} title
802 * @param {Function} fn
803 * @api private
806 function Hook(title, fn) {
807 Runnable.call(this, title, fn);
808 this.type = 'hook';
812 * Inherit from `Runnable.prototype`.
815 function F() {}
816 F.prototype = Runnable.prototype;
817 Hook.prototype = new F();
818 Hook.prototype.constructor = Hook;
821 * Get or set the test `err`.
823 * @param {Error} err
824 * @return {Error}
825 * @api public
828 Hook.prototype.error = function(err) {
829 if (0 == arguments.length) {
830 var err = this._error;
831 this._error = null;
832 return err;
835 this._error = err;
837 }); // module: hook.js
839 require.register('interfaces/bdd.js', function(module, exports, require) {
841 * Module dependencies.
844 var Suite = require('../suite'),
845 Test = require('../test');
848 * BDD-style interface:
850 * describe('Array', function(){
851 * describe('#indexOf()', function(){
852 * it('should return -1 when not present', function(){
854 * });
856 * it('should return the index when present', function(){
858 * });
859 * });
860 * });
864 module.exports = function(suite) {
865 var suites = [suite];
867 suite.on('pre-require', function(context, file, mocha) {
869 * Execute before running tests.
872 context.before = function(fn) {
873 suites[0].beforeAll(fn);
877 * Execute after running tests.
880 context.after = function(fn) {
881 suites[0].afterAll(fn);
885 * Execute before each test case.
888 context.beforeEach = function(fn) {
889 suites[0].beforeEach(fn);
893 * Execute after each test case.
896 context.afterEach = function(fn) {
897 suites[0].afterEach(fn);
901 * Describe a "suite" with the given `title`
902 * and callback `fn` containing nested suites
903 * and/or tests.
906 context.describe = context.context = function(title, fn) {
907 var suite = Suite.create(suites[0], title);
908 suites.unshift(suite);
909 fn.call(suite);
910 suites.shift();
911 return suite;
915 * Pending describe.
918 context.xdescribe = context.xcontext = context.describe.skip = function(title, fn) {
919 var suite = Suite.create(suites[0], title);
920 suite.pending = true;
921 suites.unshift(suite);
922 fn.call(suite);
923 suites.shift();
927 * Exclusive suite.
930 context.describe.only = function(title, fn) {
931 var suite = context.describe(title, fn);
932 mocha.grep(suite.fullTitle());
936 * Describe a specification or test-case
937 * with the given `title` and callback `fn`
938 * acting as a thunk.
941 context.it = context.specify = function(title, fn) {
942 var suite = suites[0];
943 if (suite.pending) var fn = null;
944 var test = new Test(title, fn);
945 suite.addTest(test);
946 return test;
950 * Exclusive test-case.
953 context.it.only = function(title, fn) {
954 var test = context.it(title, fn);
955 mocha.grep(test.fullTitle());
959 * Pending test case.
962 context.xit = context.xspecify = context.it.skip = function(title) {
963 context.it(title);
967 }); // module: interfaces/bdd.js
969 require.register('interfaces/exports.js', function(module, exports, require) {
971 * Module dependencies.
974 var Suite = require('../suite'),
975 Test = require('../test');
978 * TDD-style interface:
980 * exports.Array = {
981 * '#indexOf()': {
982 * 'should return -1 when the value is not present': function(){
984 * },
986 * 'should return the correct index when the value is present': function(){
990 * };
994 module.exports = function(suite) {
995 var suites = [suite];
997 suite.on('require', visit);
999 function visit(obj) {
1000 var suite;
1001 for (var key in obj) {
1002 if ('function' == typeof obj[key]) {
1003 var fn = obj[key];
1004 switch (key) {
1005 case 'before':
1006 suites[0].beforeAll(fn);
1007 break;
1008 case 'after':
1009 suites[0].afterAll(fn);
1010 break;
1011 case 'beforeEach':
1012 suites[0].beforeEach(fn);
1013 break;
1014 case 'afterEach':
1015 suites[0].afterEach(fn);
1016 break;
1017 default:
1018 suites[0].addTest(new Test(key, fn));
1020 } else {
1021 var suite = Suite.create(suites[0], key);
1022 suites.unshift(suite);
1023 visit(obj[key]);
1024 suites.shift();
1029 }); // module: interfaces/exports.js
1031 require.register('interfaces/index.js', function(module, exports, require) {
1032 exports.bdd = require('./bdd');
1033 exports.tdd = require('./tdd');
1034 exports.qunit = require('./qunit');
1035 exports.exports = require('./exports');
1036 }); // module: interfaces/index.js
1038 require.register('interfaces/qunit.js', function(module, exports, require) {
1040 * Module dependencies.
1043 var Suite = require('../suite'),
1044 Test = require('../test');
1047 * QUnit-style interface:
1049 * suite('Array');
1051 * test('#length', function(){
1052 * var arr = [1,2,3];
1053 * ok(arr.length == 3);
1054 * });
1056 * test('#indexOf()', function(){
1057 * var arr = [1,2,3];
1058 * ok(arr.indexOf(1) == 0);
1059 * ok(arr.indexOf(2) == 1);
1060 * ok(arr.indexOf(3) == 2);
1061 * });
1063 * suite('String');
1065 * test('#length', function(){
1066 * ok('foo'.length == 3);
1067 * });
1071 module.exports = function(suite) {
1072 var suites = [suite];
1074 suite.on('pre-require', function(context) {
1076 * Execute before running tests.
1079 context.before = function(fn) {
1080 suites[0].beforeAll(fn);
1084 * Execute after running tests.
1087 context.after = function(fn) {
1088 suites[0].afterAll(fn);
1092 * Execute before each test case.
1095 context.beforeEach = function(fn) {
1096 suites[0].beforeEach(fn);
1100 * Execute after each test case.
1103 context.afterEach = function(fn) {
1104 suites[0].afterEach(fn);
1108 * Describe a "suite" with the given `title`.
1111 context.suite = function(title) {
1112 if (suites.length > 1) suites.shift();
1113 var suite = Suite.create(suites[0], title);
1114 suites.unshift(suite);
1118 * Describe a specification or test-case
1119 * with the given `title` and callback `fn`
1120 * acting as a thunk.
1123 context.test = function(title, fn) {
1124 suites[0].addTest(new Test(title, fn));
1128 }); // module: interfaces/qunit.js
1130 require.register('interfaces/tdd.js', function(module, exports, require) {
1132 * Module dependencies.
1135 var Suite = require('../suite'),
1136 Test = require('../test');
1139 * TDD-style interface:
1141 * suite('Array', function(){
1142 * suite('#indexOf()', function(){
1143 * suiteSetup(function(){
1145 * });
1147 * test('should return -1 when not present', function(){
1149 * });
1151 * test('should return the index when present', function(){
1153 * });
1155 * suiteTeardown(function(){
1157 * });
1158 * });
1159 * });
1163 module.exports = function(suite) {
1164 var suites = [suite];
1166 suite.on('pre-require', function(context, file, mocha) {
1168 * Execute before each test case.
1171 context.setup = function(fn) {
1172 suites[0].beforeEach(fn);
1176 * Execute after each test case.
1179 context.teardown = function(fn) {
1180 suites[0].afterEach(fn);
1184 * Execute before the suite.
1187 context.suiteSetup = function(fn) {
1188 suites[0].beforeAll(fn);
1192 * Execute after the suite.
1195 context.suiteTeardown = function(fn) {
1196 suites[0].afterAll(fn);
1200 * Describe a "suite" with the given `title`
1201 * and callback `fn` containing nested suites
1202 * and/or tests.
1205 context.suite = function(title, fn) {
1206 var suite = Suite.create(suites[0], title);
1207 suites.unshift(suite);
1208 fn.call(suite);
1209 suites.shift();
1210 return suite;
1214 * Exclusive test-case.
1217 context.suite.only = function(title, fn) {
1218 var suite = context.suite(title, fn);
1219 mocha.grep(suite.fullTitle());
1223 * Describe a specification or test-case
1224 * with the given `title` and callback `fn`
1225 * acting as a thunk.
1228 context.test = function(title, fn) {
1229 var test = new Test(title, fn);
1230 suites[0].addTest(test);
1231 return test;
1235 * Exclusive test-case.
1238 context.test.only = function(title, fn) {
1239 var test = context.test(title, fn);
1240 mocha.grep(test.fullTitle());
1244 * Pending test case.
1247 context.test.skip = function(title) {
1248 context.test(title);
1252 }); // module: interfaces/tdd.js
1254 require.register('mocha.js', function(module, exports, require) {
1256 * mocha
1257 * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
1258 * MIT Licensed
1262 * Module dependencies.
1265 var path = require('browser/path'),
1266 utils = require('./utils');
1269 * Expose `Mocha`.
1272 exports = module.exports = Mocha;
1275 * Expose internals.
1278 exports.utils = utils;
1279 exports.interfaces = require('./interfaces');
1280 exports.reporters = require('./reporters');
1281 exports.Runnable = require('./runnable');
1282 exports.Context = require('./context');
1283 exports.Runner = require('./runner');
1284 exports.Suite = require('./suite');
1285 exports.Hook = require('./hook');
1286 exports.Test = require('./test');
1289 * Return image `name` path.
1291 * @param {String} name
1292 * @return {String}
1293 * @api private
1296 function image(name) {
1297 return __dirname + '/../images/' + name + '.png';
1301 * Setup mocha with `options`.
1303 * Options:
1305 * - `ui` name "bdd", "tdd", "exports" etc
1306 * - `reporter` reporter instance, defaults to `mocha.reporters.Dot`
1307 * - `globals` array of accepted globals
1308 * - `timeout` timeout in milliseconds
1309 * - `bail` bail on the first test failure
1310 * - `slow` milliseconds to wait before considering a test slow
1311 * - `ignoreLeaks` ignore global leaks
1312 * - `grep` string or regexp to filter tests with
1314 * @param {Object} options
1315 * @api public
1318 function Mocha(options) {
1319 options = options || {};
1320 this.files = [];
1321 this.options = options;
1322 this.grep(options.grep);
1323 this.suite = new exports.Suite('', new exports.Context());
1324 this.ui(options.ui);
1325 this.bail(options.bail);
1326 this.reporter(options.reporter);
1327 if (options.timeout) this.timeout(options.timeout);
1328 if (options.slow) this.slow(options.slow);
1332 * Enable or disable bailing on the first failure.
1334 * @param {Boolean} [bail]
1335 * @api public
1338 Mocha.prototype.bail = function(bail) {
1339 if (0 == arguments.length) bail = true;
1340 this.suite.bail(bail);
1341 return this;
1345 * Add test `file`.
1347 * @param {String} file
1348 * @api public
1351 Mocha.prototype.addFile = function(file) {
1352 this.files.push(file);
1353 return this;
1357 * Set reporter to `reporter`, defaults to "dot".
1359 * @param {String|Function} reporter name or constructor
1360 * @api public
1363 Mocha.prototype.reporter = function(reporter) {
1364 if ('function' == typeof reporter) {
1365 this._reporter = reporter;
1366 } else {
1367 reporter = reporter || 'dot';
1368 try {
1369 this._reporter = require('./reporters/' + reporter);
1370 } catch (err) {
1371 this._reporter = require(reporter);
1373 if (!this._reporter) throw new Error('invalid reporter "' + reporter + '"');
1375 return this;
1379 * Set test UI `name`, defaults to "bdd".
1381 * @param {String} bdd
1382 * @api public
1385 Mocha.prototype.ui = function(name) {
1386 name = name || 'bdd';
1387 this._ui = exports.interfaces[name];
1388 if (!this._ui) throw new Error('invalid interface "' + name + '"');
1389 this._ui = this._ui(this.suite);
1390 return this;
1394 * Load registered files.
1396 * @api private
1399 Mocha.prototype.loadFiles = function(fn) {
1400 var self = this;
1401 var suite = this.suite;
1402 var pending = this.files.length;
1403 this.files.forEach(function(file) {
1404 file = path.resolve(file);
1405 suite.emit('pre-require', global, file, self);
1406 suite.emit('require', require(file), file, self);
1407 suite.emit('post-require', global, file, self);
1408 --pending || (fn && fn());
1413 * Enable growl support.
1415 * @api private
1418 Mocha.prototype._growl = function(runner, reporter) {
1419 var notify = require('growl');
1421 runner.on('end', function() {
1422 var stats = reporter.stats;
1423 if (stats.failures) {
1424 var msg = stats.failures + ' of ' + runner.total + ' tests failed';
1425 notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });
1426 } else {
1427 notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
1428 name: 'mocha',
1429 title: 'Passed',
1430 image: image('ok')
1437 * Add regexp to grep, if `re` is a string it is escaped.
1439 * @param {RegExp|String} re
1440 * @return {Mocha}
1441 * @api public
1444 Mocha.prototype.grep = function(re) {
1445 this.options.grep = 'string' == typeof re ? new RegExp(utils.escapeRegexp(re)) : re;
1446 return this;
1450 * Invert `.grep()` matches.
1452 * @return {Mocha}
1453 * @api public
1456 Mocha.prototype.invert = function() {
1457 this.options.invert = true;
1458 return this;
1462 * Ignore global leaks.
1464 * @return {Mocha}
1465 * @api public
1468 Mocha.prototype.ignoreLeaks = function() {
1469 this.options.ignoreLeaks = true;
1470 return this;
1474 * Enable global leak checking.
1476 * @return {Mocha}
1477 * @api public
1480 Mocha.prototype.checkLeaks = function() {
1481 this.options.ignoreLeaks = false;
1482 return this;
1486 * Enable growl support.
1488 * @return {Mocha}
1489 * @api public
1492 Mocha.prototype.growl = function() {
1493 this.options.growl = true;
1494 return this;
1498 * Ignore `globals` array or string.
1500 * @param {Array|String} globals
1501 * @return {Mocha}
1502 * @api public
1505 Mocha.prototype.globals = function(globals) {
1506 this.options.globals = (this.options.globals || []).concat(globals);
1507 return this;
1511 * Set the timeout in milliseconds.
1513 * @param {Number} timeout
1514 * @return {Mocha}
1515 * @api public
1518 Mocha.prototype.timeout = function(timeout) {
1519 this.suite.timeout(timeout);
1520 return this;
1524 * Set slowness threshold in milliseconds.
1526 * @param {Number} slow
1527 * @return {Mocha}
1528 * @api public
1531 Mocha.prototype.slow = function(slow) {
1532 this.suite.slow(slow);
1533 return this;
1537 * Makes all tests async (accepting a callback)
1539 * @return {Mocha}
1540 * @api public
1543 Mocha.prototype.asyncOnly = function() {
1544 this.options.asyncOnly = true;
1545 return this;
1549 * Run tests and invoke `fn()` when complete.
1551 * @param {Function} fn
1552 * @return {Runner}
1553 * @api public
1556 Mocha.prototype.run = function(fn) {
1557 if (this.files.length) this.loadFiles();
1558 var suite = this.suite;
1559 var options = this.options;
1560 var runner = new exports.Runner(suite);
1561 var reporter = new this._reporter(runner);
1562 runner.ignoreLeaks = false !== options.ignoreLeaks;
1563 runner.asyncOnly = options.asyncOnly;
1564 if (options.grep) runner.grep(options.grep, options.invert);
1565 if (options.globals) runner.globals(options.globals);
1566 if (options.growl) this._growl(runner, reporter);
1567 return runner.run(fn);
1569 }); // module: mocha.js
1571 require.register('ms.js', function(module, exports, require) {
1573 * Helpers.
1576 var s = 1000;
1577 var m = s * 60;
1578 var h = m * 60;
1579 var d = h * 24;
1582 * Parse or format the given `val`.
1584 * @param {String|Number} val
1585 * @return {String|Number}
1586 * @api public
1589 module.exports = function(val) {
1590 if ('string' == typeof val) return parse(val);
1591 return format(val);
1595 * Parse the given `str` and return milliseconds.
1597 * @param {String} str
1598 * @return {Number}
1599 * @api private
1602 function parse(str) {
1603 var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(
1606 if (!m) return;
1607 var n = parseFloat(m[1]);
1608 var type = (m[2] || 'ms').toLowerCase();
1609 switch (type) {
1610 case 'years':
1611 case 'year':
1612 case 'y':
1613 return n * 31557600000;
1614 case 'days':
1615 case 'day':
1616 case 'd':
1617 return n * 86400000;
1618 case 'hours':
1619 case 'hour':
1620 case 'h':
1621 return n * 3600000;
1622 case 'minutes':
1623 case 'minute':
1624 case 'm':
1625 return n * 60000;
1626 case 'seconds':
1627 case 'second':
1628 case 's':
1629 return n * 1000;
1630 case 'ms':
1631 return n;
1636 * Format the given `ms`.
1638 * @param {Number} ms
1639 * @return {String}
1640 * @api public
1643 function format(ms) {
1644 if (ms == d) return Math.round(ms / d) + ' day';
1645 if (ms > d) return Math.round(ms / d) + ' days';
1646 if (ms == h) return Math.round(ms / h) + ' hour';
1647 if (ms > h) return Math.round(ms / h) + ' hours';
1648 if (ms == m) return Math.round(ms / m) + ' minute';
1649 if (ms > m) return Math.round(ms / m) + ' minutes';
1650 if (ms == s) return Math.round(ms / s) + ' second';
1651 if (ms > s) return Math.round(ms / s) + ' seconds';
1652 return ms + ' ms';
1654 }); // module: ms.js
1656 require.register('reporters/base.js', function(module, exports, require) {
1658 * Module dependencies.
1661 var tty = require('browser/tty'),
1662 diff = require('browser/diff'),
1663 ms = require('../ms');
1666 * Save timer references to avoid Sinon interfering (see GH-237).
1669 var Date = global.Date,
1670 setTimeout = global.setTimeout,
1671 setInterval = global.setInterval,
1672 clearTimeout = global.clearTimeout,
1673 clearInterval = global.clearInterval;
1676 * Check if both stdio streams are associated with a tty.
1679 var isatty = tty.isatty(1) && tty.isatty(2);
1682 * Expose `Base`.
1685 exports = module.exports = Base;
1688 * Enable coloring by default.
1691 exports.useColors = isatty;
1694 * Default color map.
1697 exports.colors = {
1698 pass: 90,
1699 fail: 31,
1700 'bright pass': 92,
1701 'bright fail': 91,
1702 'bright yellow': 93,
1703 pending: 36,
1704 suite: 0,
1705 'error title': 0,
1706 'error message': 31,
1707 'error stack': 90,
1708 checkmark: 32,
1709 fast: 90,
1710 medium: 33,
1711 slow: 31,
1712 green: 32,
1713 light: 90,
1714 'diff gutter': 90,
1715 'diff added': 42,
1716 'diff removed': 41
1720 * Default symbol map.
1723 exports.symbols = {
1724 ok: '✓',
1725 err: '✖',
1726 dot: '․'
1729 // With node.js on Windows: use symbols available in terminal default fonts
1730 if ('win32' == process.platform) {
1731 exports.symbols.ok = '\u221A';
1732 exports.symbols.err = '\u00D7';
1733 exports.symbols.dot = '.';
1737 * Color `str` with the given `type`,
1738 * allowing colors to be disabled,
1739 * as well as user-defined color
1740 * schemes.
1742 * @param {String} type
1743 * @param {String} str
1744 * @return {String}
1745 * @api private
1748 var color = (exports.color = function(type, str) {
1749 if (!exports.useColors) return str;
1750 return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
1754 * Expose term window size, with some
1755 * defaults for when stderr is not a tty.
1758 exports.window = {
1759 width: isatty
1760 ? process.stdout.getWindowSize
1761 ? process.stdout.getWindowSize(1)[0]
1762 : tty.getWindowSize()[1]
1763 : 75
1767 * Expose some basic cursor interactions
1768 * that are common among reporters.
1771 exports.cursor = {
1772 hide: function() {
1773 process.stdout.write('\u001b[?25l');
1776 show: function() {
1777 process.stdout.write('\u001b[?25h');
1780 deleteLine: function() {
1781 process.stdout.write('\u001b[2K');
1784 beginningOfLine: function() {
1785 process.stdout.write('\u001b[0G');
1788 CR: function() {
1789 exports.cursor.deleteLine();
1790 exports.cursor.beginningOfLine();
1795 * Outut the given `failures` as a list.
1797 * @param {Array} failures
1798 * @api public
1801 exports.list = function(failures) {
1802 console.error();
1803 failures.forEach(function(test, i) {
1804 // format
1805 var fmt =
1806 color('error title', ' %s) %s:\n') +
1807 color('error message', ' %s') +
1808 color('error stack', '\n%s\n');
1810 // msg
1811 var err = test.err,
1812 message = err.message || '',
1813 stack = err.stack || message,
1814 index = stack.indexOf(message) + message.length,
1815 msg = stack.slice(0, index),
1816 actual = err.actual,
1817 expected = err.expected,
1818 escape = true;
1820 // explicitly show diff
1821 if (err.showDiff) {
1822 escape = false;
1823 err.actual = actual = JSON.stringify(actual, null, 2);
1824 err.expected = expected = JSON.stringify(expected, null, 2);
1827 // actual / expected diff
1828 if ('string' == typeof actual && 'string' == typeof expected) {
1829 var len = Math.max(actual.length, expected.length);
1831 if (len < 20) msg = errorDiff(err, 'Chars', escape);
1832 else msg = errorDiff(err, 'Words', escape);
1834 // linenos
1835 var lines = msg.split('\n');
1836 if (lines.length > 4) {
1837 var width = String(lines.length).length;
1838 msg = lines
1839 .map(function(str, i) {
1840 return pad(++i, width) + ' |' + ' ' + str;
1842 .join('\n');
1845 // legend
1846 msg =
1847 '\n' +
1848 color('diff removed', 'actual') +
1849 ' ' +
1850 color('diff added', 'expected') +
1851 '\n\n' +
1852 msg +
1853 '\n';
1855 // indent
1856 msg = msg.replace(/^/gm, ' ');
1858 fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
1861 // indent stack trace without msg
1862 stack = stack.slice(index ? index + 1 : index).replace(/^/gm, ' ');
1864 console.error(fmt, i + 1, test.fullTitle(), msg, stack);
1869 * Initialize a new `Base` reporter.
1871 * All other reporters generally
1872 * inherit from this reporter, providing
1873 * stats such as test duration, number
1874 * of tests passed / failed etc.
1876 * @param {Runner} runner
1877 * @api public
1880 function Base(runner) {
1881 var self = this,
1882 stats = (this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }),
1883 failures = (this.failures = []);
1885 if (!runner) return;
1886 this.runner = runner;
1888 runner.stats = stats;
1890 runner.on('start', function() {
1891 stats.start = new Date();
1894 runner.on('suite', function(suite) {
1895 stats.suites = stats.suites || 0;
1896 suite.root || stats.suites++;
1899 runner.on('test end', function(test) {
1900 stats.tests = stats.tests || 0;
1901 stats.tests++;
1904 runner.on('pass', function(test) {
1905 stats.passes = stats.passes || 0;
1907 var medium = test.slow() / 2;
1908 test.speed =
1909 test.duration > test.slow() ? 'slow' : test.duration > medium ? 'medium' : 'fast';
1911 stats.passes++;
1914 runner.on('fail', function(test, err) {
1915 stats.failures = stats.failures || 0;
1916 stats.failures++;
1917 test.err = err;
1918 failures.push(test);
1921 runner.on('end', function() {
1922 stats.end = new Date();
1923 stats.duration = new Date() - stats.start;
1926 runner.on('pending', function() {
1927 stats.pending++;
1932 * Output common epilogue used by many of
1933 * the bundled reporters.
1935 * @api public
1938 Base.prototype.epilogue = function() {
1939 var stats = this.stats,
1940 fmt,
1941 tests;
1943 console.log();
1945 function pluralize(n) {
1946 return 1 == n ? 'test' : 'tests';
1949 // failure
1950 if (stats.failures) {
1951 fmt =
1952 color('bright fail', ' ' + exports.symbols.err) +
1953 color('fail', ' %d of %d %s failed') +
1954 color('light', ':');
1956 console.error(fmt, stats.failures, this.runner.total, pluralize(this.runner.total));
1958 Base.list(this.failures);
1959 console.error();
1960 return;
1963 // pass
1964 fmt =
1965 color('bright pass', ' ') + color('green', ' %d %s complete') + color('light', ' (%s)');
1967 console.log(fmt, stats.tests || 0, pluralize(stats.tests), ms(stats.duration));
1969 // pending
1970 if (stats.pending) {
1971 fmt = color('pending', ' ') + color('pending', ' %d %s pending');
1973 console.log(fmt, stats.pending, pluralize(stats.pending));
1976 console.log();
1980 * Pad the given `str` to `len`.
1982 * @param {String} str
1983 * @param {String} len
1984 * @return {String}
1985 * @api private
1988 function pad(str, len) {
1989 str = String(str);
1990 return Array(len - str.length + 1).join(' ') + str;
1994 * Return a character diff for `err`.
1996 * @param {Error} err
1997 * @return {String}
1998 * @api private
2001 function errorDiff(err, type, escape) {
2002 return diff['diff' + type](err.actual, err.expected)
2003 .map(function(str) {
2004 if (escape) {
2005 str.value = str.value
2006 .replace(/\t/g, '<tab>')
2007 .replace(/\r/g, '<CR>')
2008 .replace(/\n/g, '<LF>\n');
2010 if (str.added) return colorLines('diff added', str.value);
2011 if (str.removed) return colorLines('diff removed', str.value);
2012 return str.value;
2014 .join('');
2018 * Color lines for `str`, using the color `name`.
2020 * @param {String} name
2021 * @param {String} str
2022 * @return {String}
2023 * @api private
2026 function colorLines(name, str) {
2027 return str
2028 .split('\n')
2029 .map(function(str) {
2030 return color(name, str);
2032 .join('\n');
2034 }); // module: reporters/base.js
2036 require.register('reporters/doc.js', function(module, exports, require) {
2038 * Module dependencies.
2041 var Base = require('./base'),
2042 utils = require('../utils');
2045 * Expose `Doc`.
2048 exports = module.exports = Doc;
2051 * Initialize a new `Doc` reporter.
2053 * @param {Runner} runner
2054 * @api public
2057 function Doc(runner) {
2058 Base.call(this, runner);
2060 var self = this,
2061 stats = this.stats,
2062 total = runner.total,
2063 indents = 2;
2065 function indent() {
2066 return Array(indents).join(' ');
2069 runner.on('suite', function(suite) {
2070 if (suite.root) return;
2071 ++indents;
2072 console.log('%s<section class="suite">', indent());
2073 ++indents;
2074 console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title));
2075 console.log('%s<dl>', indent());
2078 runner.on('suite end', function(suite) {
2079 if (suite.root) return;
2080 console.log('%s</dl>', indent());
2081 --indents;
2082 console.log('%s</section>', indent());
2083 --indents;
2086 runner.on('pass', function(test) {
2087 console.log('%s <dt>%s</dt>', indent(), utils.escape(test.title));
2088 var code = utils.escape(utils.clean(test.fn.toString()));
2089 console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code);
2092 }); // module: reporters/doc.js
2094 require.register('reporters/dot.js', function(module, exports, require) {
2096 * Module dependencies.
2099 var Base = require('./base'),
2100 color = Base.color;
2103 * Expose `Dot`.
2106 exports = module.exports = Dot;
2109 * Initialize a new `Dot` matrix test reporter.
2111 * @param {Runner} runner
2112 * @api public
2115 function Dot(runner) {
2116 Base.call(this, runner);
2118 var self = this,
2119 stats = this.stats,
2120 width = (Base.window.width * 0.75) | 0,
2121 n = 0;
2123 runner.on('start', function() {
2124 process.stdout.write('\n ');
2127 runner.on('pending', function(test) {
2128 process.stdout.write(color('pending', Base.symbols.dot));
2131 runner.on('pass', function(test) {
2132 if (++n % width == 0) process.stdout.write('\n ');
2133 if ('slow' == test.speed) {
2134 process.stdout.write(color('bright yellow', Base.symbols.dot));
2135 } else {
2136 process.stdout.write(color(test.speed, Base.symbols.dot));
2140 runner.on('fail', function(test, err) {
2141 if (++n % width == 0) process.stdout.write('\n ');
2142 process.stdout.write(color('fail', Base.symbols.dot));
2145 runner.on('end', function() {
2146 console.log();
2147 self.epilogue();
2152 * Inherit from `Base.prototype`.
2155 function F() {}
2156 F.prototype = Base.prototype;
2157 Dot.prototype = new F();
2158 Dot.prototype.constructor = Dot;
2159 }); // module: reporters/dot.js
2161 require.register('reporters/html-cov.js', function(module, exports, require) {
2163 * Module dependencies.
2166 var JSONCov = require('./json-cov'),
2167 fs = require('browser/fs');
2170 * Expose `HTMLCov`.
2173 exports = module.exports = HTMLCov;
2176 * Initialize a new `JsCoverage` reporter.
2178 * @param {Runner} runner
2179 * @api public
2182 function HTMLCov(runner) {
2183 var jade = require('jade'),
2184 file = __dirname + '/templates/coverage.jade',
2185 str = fs.readFileSync(file, 'utf8'),
2186 fn = jade.compile(str, { filename: file }),
2187 self = this;
2189 JSONCov.call(this, runner, false);
2191 runner.on('end', function() {
2192 process.stdout.write(
2193 fn({
2194 cov: self.cov,
2195 coverageClass: coverageClass
2202 * Return coverage class for `n`.
2204 * @return {String}
2205 * @api private
2208 function coverageClass(n) {
2209 if (n >= 75) return 'high';
2210 if (n >= 50) return 'medium';
2211 if (n >= 25) return 'low';
2212 return 'terrible';
2214 }); // module: reporters/html-cov.js
2216 require.register('reporters/html.js', function(module, exports, require) {
2218 * Module dependencies.
2221 var Base = require('./base'),
2222 utils = require('../utils'),
2223 Progress = require('../browser/progress'),
2224 escape = utils.escape;
2227 * Save timer references to avoid Sinon interfering (see GH-237).
2230 var Date = global.Date,
2231 setTimeout = global.setTimeout,
2232 setInterval = global.setInterval,
2233 clearTimeout = global.clearTimeout,
2234 clearInterval = global.clearInterval;
2237 * Expose `Doc`.
2240 exports = module.exports = HTML;
2243 * Stats template.
2246 var statsTemplate =
2247 '<ul id="mocha-stats">' +
2248 '<li class="progress"><canvas width="40" height="40"></canvas></li>' +
2249 '<li class="passes"><a href="#">passes:</a> <em>0</em></li>' +
2250 '<li class="failures"><a href="#">failures:</a> <em>0</em></li>' +
2251 '<li class="duration">duration: <em>0</em>s</li>' +
2252 '</ul>';
2255 * Initialize a new `Doc` reporter.
2257 * @param {Runner} runner
2258 * @api public
2261 function HTML(runner, root) {
2262 Base.call(this, runner);
2264 var self = this,
2265 stats = this.stats,
2266 total = runner.total,
2267 stat = fragment(statsTemplate),
2268 items = stat.getElementsByTagName('li'),
2269 passes = items[1].getElementsByTagName('em')[0],
2270 passesLink = items[1].getElementsByTagName('a')[0],
2271 failures = items[2].getElementsByTagName('em')[0],
2272 failuresLink = items[2].getElementsByTagName('a')[0],
2273 duration = items[3].getElementsByTagName('em')[0],
2274 canvas = stat.getElementsByTagName('canvas')[0],
2275 report = fragment('<ul id="mocha-report"></ul>'),
2276 stack = [report],
2277 progress,
2278 ctx;
2280 root = root || document.getElementById('mocha');
2282 if (canvas.getContext) {
2283 var ratio = window.devicePixelRatio || 1;
2284 canvas.style.width = canvas.width;
2285 canvas.style.height = canvas.height;
2286 canvas.width *= ratio;
2287 canvas.height *= ratio;
2288 ctx = canvas.getContext('2d');
2289 ctx.scale(ratio, ratio);
2290 progress = new Progress();
2293 if (!root) return error('#mocha div missing, add it to your document');
2295 // pass toggle
2296 on(passesLink, 'click', function() {
2297 unhide();
2298 var name = /pass/.test(report.className) ? '' : ' pass';
2299 report.className = report.className.replace(/fail|pass/g, '') + name;
2300 if (report.className.trim()) hideSuitesWithout('test pass');
2303 // failure toggle
2304 on(failuresLink, 'click', function() {
2305 unhide();
2306 var name = /fail/.test(report.className) ? '' : ' fail';
2307 report.className = report.className.replace(/fail|pass/g, '') + name;
2308 if (report.className.trim()) hideSuitesWithout('test fail');
2311 root.appendChild(stat);
2312 root.appendChild(report);
2314 if (progress) progress.size(40);
2316 runner.on('suite', function(suite) {
2317 if (suite.root) return;
2319 // suite
2320 var url = '?grep=' + encodeURIComponent(suite.fullTitle());
2321 var el = fragment(
2322 '<li class="suite"><h1><a href="%s">%s</a></h1></li>',
2323 url,
2324 escape(suite.title)
2327 // container
2328 stack[0].appendChild(el);
2329 stack.unshift(document.createElement('ul'));
2330 el.appendChild(stack[0]);
2333 runner.on('suite end', function(suite) {
2334 if (suite.root) return;
2335 stack.shift();
2338 runner.on('fail', function(test, err) {
2339 if ('hook' == test.type) runner.emit('test end', test);
2342 runner.on('test end', function(test) {
2343 // TODO: add to stats
2344 var percent = ((stats.tests / this.total) * 100) | 0;
2345 if (progress) progress.update(percent).draw(ctx);
2347 // update stats
2348 var ms = new Date() - stats.start;
2349 text(passes, stats.passes);
2350 text(failures, stats.failures);
2351 text(duration, (ms / 1000).toFixed(2));
2353 // test
2354 if ('passed' == test.state) {
2355 var el = fragment(
2356 '<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="?grep=%e" class="replay">‣</a></h2></li>',
2357 test.speed,
2358 test.title,
2359 test.duration,
2360 encodeURIComponent(test.fullTitle())
2362 } else if (test.pending) {
2363 var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title);
2364 } else {
2365 var el = fragment(
2366 '<li class="test fail"><h2>%e <a href="?grep=%e" class="replay">‣</a></h2></li>',
2367 test.title,
2368 encodeURIComponent(test.fullTitle())
2370 var str = test.err.stack || test.err.toString();
2372 // FF / Opera do not add the message
2373 if (!~str.indexOf(test.err.message)) {
2374 str = test.err.message + '\n' + str;
2377 // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
2378 // check for the result of the stringifying.
2379 if ('[object Error]' == str) str = test.err.message;
2381 // Safari doesn't give you a stack. Let's at least provide a source line.
2382 if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
2383 str += '\n(' + test.err.sourceURL + ':' + test.err.line + ')';
2386 el.appendChild(fragment('<pre class="error">%e</pre>', str));
2389 // toggle code
2390 // TODO: defer
2391 if (!test.pending) {
2392 var h2 = el.getElementsByTagName('h2')[0];
2394 on(h2, 'click', function() {
2395 pre.style.display = 'none' == pre.style.display ? 'block' : 'none';
2398 var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString()));
2399 el.appendChild(pre);
2400 pre.style.display = 'none';
2403 // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.
2404 if (stack[0]) stack[0].appendChild(el);
2409 * Display error `msg`.
2412 function error(msg) {
2413 document.body.appendChild(fragment('<div id="mocha-error">%s</div>', msg));
2417 * Return a DOM fragment from `html`.
2420 function fragment(html) {
2421 var args = arguments,
2422 div = document.createElement('div'),
2423 i = 1;
2425 div.innerHTML = html.replace(/%([se])/g, function(_, type) {
2426 switch (type) {
2427 case 's':
2428 return String(args[i++]);
2429 case 'e':
2430 return escape(args[i++]);
2434 return div.firstChild;
2438 * Check for suites that do not have elements
2439 * with `classname`, and hide them.
2442 function hideSuitesWithout(classname) {
2443 var suites = document.getElementsByClassName('suite');
2444 for (var i = 0; i < suites.length; i++) {
2445 var els = suites[i].getElementsByClassName(classname);
2446 if (0 == els.length) suites[i].className += ' hidden';
2451 * Unhide .hidden suites.
2454 function unhide() {
2455 var els = document.getElementsByClassName('suite hidden');
2456 for (var i = 0; i < els.length; ++i) {
2457 els[i].className = els[i].className.replace('suite hidden', 'suite');
2462 * Set `el` text to `str`.
2465 function text(el, str) {
2466 if (el.textContent) {
2467 el.textContent = str;
2468 } else {
2469 el.innerText = str;
2474 * Listen on `event` with callback `fn`.
2477 function on(el, event, fn) {
2478 if (el.addEventListener) {
2479 el.addEventListener(event, fn, false);
2480 } else {
2481 el.attachEvent('on' + event, fn);
2484 }); // module: reporters/html.js
2486 require.register('reporters/index.js', function(module, exports, require) {
2487 exports.Base = require('./base');
2488 exports.Dot = require('./dot');
2489 exports.Doc = require('./doc');
2490 exports.TAP = require('./tap');
2491 exports.JSON = require('./json');
2492 exports.HTML = require('./html');
2493 exports.List = require('./list');
2494 exports.Min = require('./min');
2495 exports.Spec = require('./spec');
2496 exports.Nyan = require('./nyan');
2497 exports.XUnit = require('./xunit');
2498 exports.Markdown = require('./markdown');
2499 exports.Progress = require('./progress');
2500 exports.Landing = require('./landing');
2501 exports.JSONCov = require('./json-cov');
2502 exports.HTMLCov = require('./html-cov');
2503 exports.JSONStream = require('./json-stream');
2504 exports.Teamcity = require('./teamcity');
2505 }); // module: reporters/index.js
2507 require.register('reporters/json-cov.js', function(module, exports, require) {
2509 * Module dependencies.
2512 var Base = require('./base');
2515 * Expose `JSONCov`.
2518 exports = module.exports = JSONCov;
2521 * Initialize a new `JsCoverage` reporter.
2523 * @param {Runner} runner
2524 * @param {Boolean} output
2525 * @api public
2528 function JSONCov(runner, output) {
2529 var self = this,
2530 output = 1 == arguments.length ? true : output;
2532 Base.call(this, runner);
2534 var tests = [],
2535 failures = [],
2536 passes = [];
2538 runner.on('test end', function(test) {
2539 tests.push(test);
2542 runner.on('pass', function(test) {
2543 passes.push(test);
2546 runner.on('fail', function(test) {
2547 failures.push(test);
2550 runner.on('end', function() {
2551 var cov = global._$jscoverage || {};
2552 var result = (self.cov = map(cov));
2553 result.stats = self.stats;
2554 result.tests = tests.map(clean);
2555 result.failures = failures.map(clean);
2556 result.passes = passes.map(clean);
2557 if (!output) return;
2558 process.stdout.write(JSON.stringify(result, null, 2));
2563 * Map jscoverage data to a JSON structure
2564 * suitable for reporting.
2566 * @param {Object} cov
2567 * @return {Object}
2568 * @api private
2571 function map(cov) {
2572 var ret = {
2573 instrumentation: 'node-jscoverage',
2574 sloc: 0,
2575 hits: 0,
2576 misses: 0,
2577 coverage: 0,
2578 files: []
2581 for (var filename in cov) {
2582 var data = coverage(filename, cov[filename]);
2583 ret.files.push(data);
2584 ret.hits += data.hits;
2585 ret.misses += data.misses;
2586 ret.sloc += data.sloc;
2589 ret.files.sort(function(a, b) {
2590 return a.filename.localeCompare(b.filename);
2593 if (ret.sloc > 0) {
2594 ret.coverage = (ret.hits / ret.sloc) * 100;
2597 return ret;
2601 * Map jscoverage data for a single source file
2602 * to a JSON structure suitable for reporting.
2604 * @param {String} filename name of the source file
2605 * @param {Object} data jscoverage coverage data
2606 * @return {Object}
2607 * @api private
2610 function coverage(filename, data) {
2611 var ret = {
2612 filename: filename,
2613 coverage: 0,
2614 hits: 0,
2615 misses: 0,
2616 sloc: 0,
2617 source: {}
2620 data.source.forEach(function(line, num) {
2621 num++;
2623 if (data[num] === 0) {
2624 ret.misses++;
2625 ret.sloc++;
2626 } else if (data[num] !== undefined) {
2627 ret.hits++;
2628 ret.sloc++;
2631 ret.source[num] = {
2632 source: line,
2633 coverage: data[num] === undefined ? '' : data[num]
2637 ret.coverage = (ret.hits / ret.sloc) * 100;
2639 return ret;
2643 * Return a plain-object representation of `test`
2644 * free of cyclic properties etc.
2646 * @param {Object} test
2647 * @return {Object}
2648 * @api private
2651 function clean(test) {
2652 return {
2653 title: test.title,
2654 fullTitle: test.fullTitle(),
2655 duration: test.duration
2658 }); // module: reporters/json-cov.js
2660 require.register('reporters/json-stream.js', function(module, exports, require) {
2662 * Module dependencies.
2665 var Base = require('./base'),
2666 color = Base.color;
2669 * Expose `List`.
2672 exports = module.exports = List;
2675 * Initialize a new `List` test reporter.
2677 * @param {Runner} runner
2678 * @api public
2681 function List(runner) {
2682 Base.call(this, runner);
2684 var self = this,
2685 stats = this.stats,
2686 total = runner.total;
2688 runner.on('start', function() {
2689 console.log(JSON.stringify(['start', { total: total }]));
2692 runner.on('pass', function(test) {
2693 console.log(JSON.stringify(['pass', clean(test)]));
2696 runner.on('fail', function(test, err) {
2697 console.log(JSON.stringify(['fail', clean(test)]));
2700 runner.on('end', function() {
2701 process.stdout.write(JSON.stringify(['end', self.stats]));
2706 * Return a plain-object representation of `test`
2707 * free of cyclic properties etc.
2709 * @param {Object} test
2710 * @return {Object}
2711 * @api private
2714 function clean(test) {
2715 return {
2716 title: test.title,
2717 fullTitle: test.fullTitle(),
2718 duration: test.duration
2721 }); // module: reporters/json-stream.js
2723 require.register('reporters/json.js', function(module, exports, require) {
2725 * Module dependencies.
2728 var Base = require('./base'),
2729 cursor = Base.cursor,
2730 color = Base.color;
2733 * Expose `JSON`.
2736 exports = module.exports = JSONReporter;
2739 * Initialize a new `JSON` reporter.
2741 * @param {Runner} runner
2742 * @api public
2745 function JSONReporter(runner) {
2746 var self = this;
2747 Base.call(this, runner);
2749 var tests = [],
2750 failures = [],
2751 passes = [];
2753 runner.on('test end', function(test) {
2754 tests.push(test);
2757 runner.on('pass', function(test) {
2758 passes.push(test);
2761 runner.on('fail', function(test) {
2762 failures.push(test);
2765 runner.on('end', function() {
2766 var obj = {
2767 stats: self.stats,
2768 tests: tests.map(clean),
2769 failures: failures.map(clean),
2770 passes: passes.map(clean)
2773 process.stdout.write(JSON.stringify(obj, null, 2));
2778 * Return a plain-object representation of `test`
2779 * free of cyclic properties etc.
2781 * @param {Object} test
2782 * @return {Object}
2783 * @api private
2786 function clean(test) {
2787 return {
2788 title: test.title,
2789 fullTitle: test.fullTitle(),
2790 duration: test.duration
2793 }); // module: reporters/json.js
2795 require.register('reporters/landing.js', function(module, exports, require) {
2797 * Module dependencies.
2800 var Base = require('./base'),
2801 cursor = Base.cursor,
2802 color = Base.color;
2805 * Expose `Landing`.
2808 exports = module.exports = Landing;
2811 * Airplane color.
2814 Base.colors.plane = 0;
2817 * Airplane crash color.
2820 Base.colors['plane crash'] = 31;
2823 * Runway color.
2826 Base.colors.runway = 90;
2829 * Initialize a new `Landing` reporter.
2831 * @param {Runner} runner
2832 * @api public
2835 function Landing(runner) {
2836 Base.call(this, runner);
2838 var self = this,
2839 stats = this.stats,
2840 width = (Base.window.width * 0.75) | 0,
2841 total = runner.total,
2842 stream = process.stdout,
2843 plane = color('plane', '✈'),
2844 crashed = -1,
2845 n = 0;
2847 function runway() {
2848 var buf = Array(width).join('-');
2849 return ' ' + color('runway', buf);
2852 runner.on('start', function() {
2853 stream.write('\n ');
2854 cursor.hide();
2857 runner.on('test end', function(test) {
2858 // check if the plane crashed
2859 var col = -1 == crashed ? ((width * ++n) / total) | 0 : crashed;
2861 // show the crash
2862 if ('failed' == test.state) {
2863 plane = color('plane crash', '✈');
2864 crashed = col;
2867 // render landing strip
2868 stream.write('\u001b[4F\n\n');
2869 stream.write(runway());
2870 stream.write('\n ');
2871 stream.write(color('runway', Array(col).join('â‹…')));
2872 stream.write(plane);
2873 stream.write(color('runway', Array(width - col).join('â‹…') + '\n'));
2874 stream.write(runway());
2875 stream.write('\u001b[0m');
2878 runner.on('end', function() {
2879 cursor.show();
2880 console.log();
2881 self.epilogue();
2886 * Inherit from `Base.prototype`.
2889 function F() {}
2890 F.prototype = Base.prototype;
2891 Landing.prototype = new F();
2892 Landing.prototype.constructor = Landing;
2893 }); // module: reporters/landing.js
2895 require.register('reporters/list.js', function(module, exports, require) {
2897 * Module dependencies.
2900 var Base = require('./base'),
2901 cursor = Base.cursor,
2902 color = Base.color;
2905 * Expose `List`.
2908 exports = module.exports = List;
2911 * Initialize a new `List` test reporter.
2913 * @param {Runner} runner
2914 * @api public
2917 function List(runner) {
2918 Base.call(this, runner);
2920 var self = this,
2921 stats = this.stats,
2922 n = 0;
2924 runner.on('start', function() {
2925 console.log();
2928 runner.on('test', function(test) {
2929 process.stdout.write(color('pass', ' ' + test.fullTitle() + ': '));
2932 runner.on('pending', function(test) {
2933 var fmt = color('checkmark', ' -') + color('pending', ' %s');
2934 console.log(fmt, test.fullTitle());
2937 runner.on('pass', function(test) {
2938 var fmt =
2939 color('checkmark', ' ' + Base.symbols.dot) +
2940 color('pass', ' %s: ') +
2941 color(test.speed, '%dms');
2942 cursor.CR();
2943 console.log(fmt, test.fullTitle(), test.duration);
2946 runner.on('fail', function(test, err) {
2947 cursor.CR();
2948 console.log(color('fail', ' %d) %s'), ++n, test.fullTitle());
2951 runner.on('end', self.epilogue.bind(self));
2955 * Inherit from `Base.prototype`.
2958 function F() {}
2959 F.prototype = Base.prototype;
2960 List.prototype = new F();
2961 List.prototype.constructor = List;
2962 }); // module: reporters/list.js
2964 require.register('reporters/markdown.js', function(module, exports, require) {
2966 * Module dependencies.
2969 var Base = require('./base'),
2970 utils = require('../utils');
2973 * Expose `Markdown`.
2976 exports = module.exports = Markdown;
2979 * Initialize a new `Markdown` reporter.
2981 * @param {Runner} runner
2982 * @api public
2985 function Markdown(runner) {
2986 Base.call(this, runner);
2988 var self = this,
2989 stats = this.stats,
2990 level = 0,
2991 buf = '';
2993 function title(str) {
2994 return Array(level).join('#') + ' ' + str;
2997 function indent() {
2998 return Array(level).join(' ');
3001 function mapTOC(suite, obj) {
3002 var ret = obj;
3003 obj = obj[suite.title] = obj[suite.title] || { suite: suite };
3004 suite.suites.forEach(function(suite) {
3005 mapTOC(suite, obj);
3007 return ret;
3010 function stringifyTOC(obj, level) {
3011 ++level;
3012 var buf = '';
3013 var link;
3014 for (var key in obj) {
3015 if ('suite' == key) continue;
3016 if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
3017 if (key) buf += Array(level).join(' ') + link;
3018 buf += stringifyTOC(obj[key], level);
3020 --level;
3021 return buf;
3024 function generateTOC(suite) {
3025 var obj = mapTOC(suite, {});
3026 return stringifyTOC(obj, 0);
3029 generateTOC(runner.suite);
3031 runner.on('suite', function(suite) {
3032 ++level;
3033 var slug = utils.slug(suite.fullTitle());
3034 buf += '<a name="' + slug + '"></a>' + '\n';
3035 buf += title(suite.title) + '\n';
3038 runner.on('suite end', function(suite) {
3039 --level;
3042 runner.on('pass', function(test) {
3043 var code = utils.clean(test.fn.toString());
3044 buf += test.title + '.\n';
3045 buf += '\n```js\n';
3046 buf += code + '\n';
3047 buf += '```\n\n';
3050 runner.on('end', function() {
3051 process.stdout.write('# TOC\n');
3052 process.stdout.write(generateTOC(runner.suite));
3053 process.stdout.write(buf);
3056 }); // module: reporters/markdown.js
3058 require.register('reporters/min.js', function(module, exports, require) {
3060 * Module dependencies.
3063 var Base = require('./base');
3066 * Expose `Min`.
3069 exports = module.exports = Min;
3072 * Initialize a new `Min` minimal test reporter (best used with --watch).
3074 * @param {Runner} runner
3075 * @api public
3078 function Min(runner) {
3079 Base.call(this, runner);
3081 runner.on('start', function() {
3082 // clear screen
3083 process.stdout.write('\u001b[2J');
3084 // set cursor position
3085 process.stdout.write('\u001b[1;3H');
3088 runner.on('end', this.epilogue.bind(this));
3092 * Inherit from `Base.prototype`.
3095 function F() {}
3096 F.prototype = Base.prototype;
3097 Min.prototype = new F();
3098 Min.prototype.constructor = Min;
3099 }); // module: reporters/min.js
3101 require.register('reporters/nyan.js', function(module, exports, require) {
3103 * Module dependencies.
3106 var Base = require('./base'),
3107 color = Base.color;
3110 * Expose `Dot`.
3113 exports = module.exports = NyanCat;
3116 * Initialize a new `Dot` matrix test reporter.
3118 * @param {Runner} runner
3119 * @api public
3122 function NyanCat(runner) {
3123 Base.call(this, runner);
3125 var self = this,
3126 stats = this.stats,
3127 width = (Base.window.width * 0.75) | 0,
3128 rainbowColors = (this.rainbowColors = self.generateColors()),
3129 colorIndex = (this.colorIndex = 0),
3130 numerOfLines = (this.numberOfLines = 4),
3131 trajectories = (this.trajectories = [[], [], [], []]),
3132 nyanCatWidth = (this.nyanCatWidth = 11),
3133 trajectoryWidthMax = (this.trajectoryWidthMax = width - nyanCatWidth),
3134 scoreboardWidth = (this.scoreboardWidth = 5),
3135 tick = (this.tick = 0),
3136 n = 0;
3138 runner.on('start', function() {
3139 Base.cursor.hide();
3140 self.draw('start');
3143 runner.on('pending', function(test) {
3144 self.draw('pending');
3147 runner.on('pass', function(test) {
3148 self.draw('pass');
3151 runner.on('fail', function(test, err) {
3152 self.draw('fail');
3155 runner.on('end', function() {
3156 Base.cursor.show();
3157 for (var i = 0; i < self.numberOfLines; i++) write('\n');
3158 self.epilogue();
3163 * Draw the nyan cat with runner `status`.
3165 * @param {String} status
3166 * @api private
3169 NyanCat.prototype.draw = function(status) {
3170 this.appendRainbow();
3171 this.drawScoreboard();
3172 this.drawRainbow();
3173 this.drawNyanCat(status);
3174 this.tick = !this.tick;
3178 * Draw the "scoreboard" showing the number
3179 * of passes, failures and pending tests.
3181 * @api private
3184 NyanCat.prototype.drawScoreboard = function() {
3185 var stats = this.stats;
3186 var colors = Base.colors;
3188 function draw(color, n) {
3189 write(' ');
3190 write('\u001b[' + color + 'm' + n + '\u001b[0m');
3191 write('\n');
3194 draw(colors.green, stats.passes);
3195 draw(colors.fail, stats.failures);
3196 draw(colors.pending, stats.pending);
3197 write('\n');
3199 this.cursorUp(this.numberOfLines);
3203 * Append the rainbow.
3205 * @api private
3208 NyanCat.prototype.appendRainbow = function() {
3209 var segment = this.tick ? '_' : '-';
3210 var rainbowified = this.rainbowify(segment);
3212 for (var index = 0; index < this.numberOfLines; index++) {
3213 var trajectory = this.trajectories[index];
3214 if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();
3215 trajectory.push(rainbowified);
3220 * Draw the rainbow.
3222 * @api private
3225 NyanCat.prototype.drawRainbow = function() {
3226 var self = this;
3228 this.trajectories.forEach(function(line, index) {
3229 write('\u001b[' + self.scoreboardWidth + 'C');
3230 write(line.join(''));
3231 write('\n');
3234 this.cursorUp(this.numberOfLines);
3238 * Draw the nyan cat with `status`.
3240 * @param {String} status
3241 * @api private
3244 NyanCat.prototype.drawNyanCat = function(status) {
3245 var self = this;
3246 var startWidth = this.scoreboardWidth + this.trajectories[0].length;
3247 var color = '\u001b[' + startWidth + 'C';
3248 var padding = '';
3250 write(color);
3251 write('_,------,');
3252 write('\n');
3254 write(color);
3255 padding = self.tick ? ' ' : ' ';
3256 write('_|' + padding + '/\\_/\\ ');
3257 write('\n');
3259 write(color);
3260 padding = self.tick ? '_' : '__';
3261 var tail = self.tick ? '~' : '^';
3262 var face;
3263 switch (status) {
3264 case 'pass':
3265 face = '( ^ .^)';
3266 break;
3267 case 'fail':
3268 face = '( o .o)';
3269 break;
3270 default:
3271 face = '( - .-)';
3273 write(tail + '|' + padding + face + ' ');
3274 write('\n');
3276 write(color);
3277 padding = self.tick ? ' ' : ' ';
3278 write(padding + '"" "" ');
3279 write('\n');
3281 this.cursorUp(this.numberOfLines);
3285 * Move cursor up `n`.
3287 * @param {Number} n
3288 * @api private
3291 NyanCat.prototype.cursorUp = function(n) {
3292 write('\u001b[' + n + 'A');
3296 * Move cursor down `n`.
3298 * @param {Number} n
3299 * @api private
3302 NyanCat.prototype.cursorDown = function(n) {
3303 write('\u001b[' + n + 'B');
3307 * Generate rainbow colors.
3309 * @return {Array}
3310 * @api private
3313 NyanCat.prototype.generateColors = function() {
3314 var colors = [];
3316 for (var i = 0; i < 6 * 7; i++) {
3317 var pi3 = Math.floor(Math.PI / 3);
3318 var n = i * (1.0 / 6);
3319 var r = Math.floor(3 * Math.sin(n) + 3);
3320 var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);
3321 var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);
3322 colors.push(36 * r + 6 * g + b + 16);
3325 return colors;
3329 * Apply rainbow to the given `str`.
3331 * @param {String} str
3332 * @return {String}
3333 * @api private
3336 NyanCat.prototype.rainbowify = function(str) {
3337 var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
3338 this.colorIndex += 1;
3339 return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m';
3343 * Stdout helper.
3346 function write(string) {
3347 process.stdout.write(string);
3351 * Inherit from `Base.prototype`.
3354 function F() {}
3355 F.prototype = Base.prototype;
3356 NyanCat.prototype = new F();
3357 NyanCat.prototype.constructor = NyanCat;
3358 }); // module: reporters/nyan.js
3360 require.register('reporters/progress.js', function(module, exports, require) {
3362 * Module dependencies.
3365 var Base = require('./base'),
3366 cursor = Base.cursor,
3367 color = Base.color;
3370 * Expose `Progress`.
3373 exports = module.exports = Progress;
3376 * General progress bar color.
3379 Base.colors.progress = 90;
3382 * Initialize a new `Progress` bar test reporter.
3384 * @param {Runner} runner
3385 * @param {Object} options
3386 * @api public
3389 function Progress(runner, options) {
3390 Base.call(this, runner);
3392 var self = this,
3393 options = options || {},
3394 stats = this.stats,
3395 width = (Base.window.width * 0.5) | 0,
3396 total = runner.total,
3397 complete = 0,
3398 max = Math.max;
3400 // default chars
3401 options.open = options.open || '[';
3402 options.complete = options.complete || 'â–¬';
3403 options.incomplete = options.incomplete || Base.symbols.dot;
3404 options.close = options.close || ']';
3405 options.verbose = false;
3407 // tests started
3408 runner.on('start', function() {
3409 console.log();
3410 cursor.hide();
3413 // tests complete
3414 runner.on('test end', function() {
3415 complete++;
3416 var incomplete = total - complete,
3417 percent = complete / total,
3418 n = (width * percent) | 0,
3419 i = width - n;
3421 cursor.CR();
3422 process.stdout.write('\u001b[J');
3423 process.stdout.write(color('progress', ' ' + options.open));
3424 process.stdout.write(Array(n).join(options.complete));
3425 process.stdout.write(Array(i).join(options.incomplete));
3426 process.stdout.write(color('progress', options.close));
3427 if (options.verbose) {
3428 process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
3432 // tests are complete, output some stats
3433 // and the failures if any
3434 runner.on('end', function() {
3435 cursor.show();
3436 console.log();
3437 self.epilogue();
3442 * Inherit from `Base.prototype`.
3445 function F() {}
3446 F.prototype = Base.prototype;
3447 Progress.prototype = new F();
3448 Progress.prototype.constructor = Progress;
3449 }); // module: reporters/progress.js
3451 require.register('reporters/spec.js', function(module, exports, require) {
3453 * Module dependencies.
3456 var Base = require('./base'),
3457 cursor = Base.cursor,
3458 color = Base.color;
3461 * Expose `Spec`.
3464 exports = module.exports = Spec;
3467 * Initialize a new `Spec` test reporter.
3469 * @param {Runner} runner
3470 * @api public
3473 function Spec(runner) {
3474 Base.call(this, runner);
3476 var self = this,
3477 stats = this.stats,
3478 indents = 0,
3479 n = 0;
3481 function indent() {
3482 return Array(indents).join(' ');
3485 runner.on('start', function() {
3486 console.log();
3489 runner.on('suite', function(suite) {
3490 ++indents;
3491 console.log(color('suite', '%s%s'), indent(), suite.title);
3494 runner.on('suite end', function(suite) {
3495 --indents;
3496 if (1 == indents) console.log();
3499 runner.on('test', function(test) {
3500 process.stdout.write(indent() + color('pass', ' â—¦ ' + test.title + ': '));
3503 runner.on('pending', function(test) {
3504 var fmt = indent() + color('pending', ' - %s');
3505 console.log(fmt, test.title);
3508 runner.on('pass', function(test) {
3509 if ('fast' == test.speed) {
3510 var fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s ');
3511 cursor.CR();
3512 console.log(fmt, test.title);
3513 } else {
3514 var fmt =
3515 indent() +
3516 color('checkmark', ' ' + Base.symbols.ok) +
3517 color('pass', ' %s ') +
3518 color(test.speed, '(%dms)');
3519 cursor.CR();
3520 console.log(fmt, test.title, test.duration);
3524 runner.on('fail', function(test, err) {
3525 cursor.CR();
3526 console.log(indent() + color('fail', ' %d) %s'), ++n, test.title);
3529 runner.on('end', self.epilogue.bind(self));
3533 * Inherit from `Base.prototype`.
3536 function F() {}
3537 F.prototype = Base.prototype;
3538 Spec.prototype = new F();
3539 Spec.prototype.constructor = Spec;
3540 }); // module: reporters/spec.js
3542 require.register('reporters/tap.js', function(module, exports, require) {
3544 * Module dependencies.
3547 var Base = require('./base'),
3548 cursor = Base.cursor,
3549 color = Base.color;
3552 * Expose `TAP`.
3555 exports = module.exports = TAP;
3558 * Initialize a new `TAP` reporter.
3560 * @param {Runner} runner
3561 * @api public
3564 function TAP(runner) {
3565 Base.call(this, runner);
3567 var self = this,
3568 stats = this.stats,
3569 n = 1,
3570 passes = 0,
3571 failures = 0;
3573 runner.on('start', function() {
3574 var total = runner.grepTotal(runner.suite);
3575 console.log('%d..%d', 1, total);
3578 runner.on('test end', function() {
3579 ++n;
3582 runner.on('pending', function(test) {
3583 console.log('ok %d %s # SKIP -', n, title(test));
3586 runner.on('pass', function(test) {
3587 passes++;
3588 console.log('ok %d %s', n, title(test));
3591 runner.on('fail', function(test, err) {
3592 failures++;
3593 console.log('not ok %d %s', n, title(test));
3594 if (err.stack) console.log(err.stack.replace(/^/gm, ' '));
3597 runner.on('end', function() {
3598 console.log('# tests ' + (passes + failures));
3599 console.log('# pass ' + passes);
3600 console.log('# fail ' + failures);
3605 * Return a TAP-safe title of `test`
3607 * @param {Object} test
3608 * @return {String}
3609 * @api private
3612 function title(test) {
3613 return test.fullTitle().replace(/#/g, '');
3615 }); // module: reporters/tap.js
3617 require.register('reporters/teamcity.js', function(module, exports, require) {
3619 * Module dependencies.
3622 var Base = require('./base');
3625 * Expose `Teamcity`.
3628 exports = module.exports = Teamcity;
3631 * Initialize a new `Teamcity` reporter.
3633 * @param {Runner} runner
3634 * @api public
3637 function Teamcity(runner) {
3638 Base.call(this, runner);
3639 var stats = this.stats;
3641 runner.on('start', function() {
3642 console.log("##teamcity[testSuiteStarted name='mocha.suite']");
3645 runner.on('test', function(test) {
3646 console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']");
3649 runner.on('fail', function(test, err) {
3650 console.log(
3651 "##teamcity[testFailed name='" +
3652 escape(test.fullTitle()) +
3653 "' message='" +
3654 escape(err.message) +
3655 "']"
3659 runner.on('pending', function(test) {
3660 console.log(
3661 "##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"
3665 runner.on('test end', function(test) {
3666 console.log(
3667 "##teamcity[testFinished name='" +
3668 escape(test.fullTitle()) +
3669 "' duration='" +
3670 test.duration +
3671 "']"
3675 runner.on('end', function() {
3676 console.log(
3677 "##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"
3683 * Escape the given `str`.
3686 function escape(str) {
3687 return str
3688 .replace(/\|/g, '||')
3689 .replace(/\n/g, '|n')
3690 .replace(/\r/g, '|r')
3691 .replace(/\[/g, '|[')
3692 .replace(/\]/g, '|]')
3693 .replace(/\u0085/g, '|x')
3694 .replace(/\u2028/g, '|l')
3695 .replace(/\u2029/g, '|p')
3696 .replace(/'/g, "|'");
3698 }); // module: reporters/teamcity.js
3700 require.register('reporters/xunit.js', function(module, exports, require) {
3702 * Module dependencies.
3705 var Base = require('./base'),
3706 utils = require('../utils'),
3707 escape = utils.escape;
3710 * Save timer references to avoid Sinon interfering (see GH-237).
3713 var Date = global.Date,
3714 setTimeout = global.setTimeout,
3715 setInterval = global.setInterval,
3716 clearTimeout = global.clearTimeout,
3717 clearInterval = global.clearInterval;
3720 * Expose `XUnit`.
3723 exports = module.exports = XUnit;
3726 * Initialize a new `XUnit` reporter.
3728 * @param {Runner} runner
3729 * @api public
3732 function XUnit(runner) {
3733 Base.call(this, runner);
3734 var stats = this.stats,
3735 tests = [],
3736 self = this;
3738 runner.on('pass', function(test) {
3739 tests.push(test);
3742 runner.on('fail', function(test) {
3743 tests.push(test);
3746 runner.on('end', function() {
3747 console.log(
3748 tag(
3749 'testsuite',
3751 name: 'Mocha Tests',
3752 tests: stats.tests,
3753 failures: stats.failures,
3754 errors: stats.failures,
3755 skip: stats.tests - stats.failures - stats.passes,
3756 timestamp: new Date().toUTCString(),
3757 time: stats.duration / 1000
3759 false
3763 tests.forEach(test);
3764 console.log('</testsuite>');
3769 * Inherit from `Base.prototype`.
3772 function F() {}
3773 F.prototype = Base.prototype;
3774 XUnit.prototype = new F();
3775 XUnit.prototype.constructor = XUnit;
3778 * Output tag for the given `test.`
3781 function test(test) {
3782 var attrs = {
3783 classname: test.parent.fullTitle(),
3784 name: test.title,
3785 time: test.duration / 1000
3788 if ('failed' == test.state) {
3789 var err = test.err;
3790 attrs.message = escape(err.message);
3791 console.log(
3792 tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))
3794 } else if (test.pending) {
3795 console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
3796 } else {
3797 console.log(tag('testcase', attrs, true));
3802 * HTML tag helper.
3805 function tag(name, attrs, close, content) {
3806 var end = close ? '/>' : '>',
3807 pairs = [],
3808 tag;
3810 for (var key in attrs) {
3811 pairs.push(key + '="' + escape(attrs[key]) + '"');
3814 tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
3815 if (content) tag += content + '</' + name + end;
3816 return tag;
3820 * Return cdata escaped CDATA `str`.
3823 function cdata(str) {
3824 return '<![CDATA[' + escape(str) + ']]>';
3826 }); // module: reporters/xunit.js
3828 require.register('runnable.js', function(module, exports, require) {
3830 * Module dependencies.
3833 var EventEmitter = require('browser/events').EventEmitter,
3834 debug = require('browser/debug')('mocha:runnable'),
3835 milliseconds = require('./ms');
3838 * Save timer references to avoid Sinon interfering (see GH-237).
3841 var Date = global.Date,
3842 setTimeout = global.setTimeout,
3843 setInterval = global.setInterval,
3844 clearTimeout = global.clearTimeout,
3845 clearInterval = global.clearInterval;
3848 * Object#toString().
3851 var toString = Object.prototype.toString;
3854 * Expose `Runnable`.
3857 module.exports = Runnable;
3860 * Initialize a new `Runnable` with the given `title` and callback `fn`.
3862 * @param {String} title
3863 * @param {Function} fn
3864 * @api private
3867 function Runnable(title, fn) {
3868 this.title = title;
3869 this.fn = fn;
3870 this.async = fn && fn.length;
3871 this.sync = !this.async;
3872 this._timeout = 2000;
3873 this._slow = 75;
3874 this.timedOut = false;
3878 * Inherit from `EventEmitter.prototype`.
3881 function F() {}
3882 F.prototype = EventEmitter.prototype;
3883 Runnable.prototype = new F();
3884 Runnable.prototype.constructor = Runnable;
3887 * Set & get timeout `ms`.
3889 * @param {Number|String} ms
3890 * @return {Runnable|Number} ms or self
3891 * @api private
3894 Runnable.prototype.timeout = function(ms) {
3895 if (0 == arguments.length) return this._timeout;
3896 if ('string' == typeof ms) ms = milliseconds(ms);
3897 debug('timeout %d', ms);
3898 this._timeout = ms;
3899 if (this.timer) this.resetTimeout();
3900 return this;
3904 * Set & get slow `ms`.
3906 * @param {Number|String} ms
3907 * @return {Runnable|Number} ms or self
3908 * @api private
3911 Runnable.prototype.slow = function(ms) {
3912 if (0 === arguments.length) return this._slow;
3913 if ('string' == typeof ms) ms = milliseconds(ms);
3914 debug('timeout %d', ms);
3915 this._slow = ms;
3916 return this;
3920 * Return the full title generated by recursively
3921 * concatenating the parent's full title.
3923 * @return {String}
3924 * @api public
3927 Runnable.prototype.fullTitle = function() {
3928 return this.parent.fullTitle() + ' ' + this.title;
3932 * Clear the timeout.
3934 * @api private
3937 Runnable.prototype.clearTimeout = function() {
3938 clearTimeout(this.timer);
3942 * Inspect the runnable void of private properties.
3944 * @return {String}
3945 * @api private
3948 Runnable.prototype.inspect = function() {
3949 return JSON.stringify(
3950 this,
3951 function(key, val) {
3952 if ('_' == key[0]) return;
3953 if ('parent' == key) return '#<Suite>';
3954 if ('ctx' == key) return '#<Context>';
3955 return val;
3962 * Reset the timeout.
3964 * @api private
3967 Runnable.prototype.resetTimeout = function() {
3968 var self = this,
3969 ms = this.timeout();
3971 this.clearTimeout();
3972 if (ms) {
3973 this.timer = setTimeout(function() {
3974 self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
3975 self.timedOut = true;
3976 }, ms);
3981 * Run the test and invoke `fn(err)`.
3983 * @param {Function} fn
3984 * @api private
3987 Runnable.prototype.run = function(fn) {
3988 var self = this,
3989 ms = this.timeout(),
3990 start = new Date(),
3991 ctx = this.ctx,
3992 finished,
3993 emitted;
3995 if (ctx) ctx.runnable(this);
3997 // timeout
3998 if (this.async) {
3999 if (ms) {
4000 this.timer = setTimeout(function() {
4001 done(new Error('timeout of ' + ms + 'ms exceeded'));
4002 self.timedOut = true;
4003 }, ms);
4007 // called multiple times
4008 function multiple(err) {
4009 if (emitted) return;
4010 emitted = true;
4011 self.emit('error', err || new Error('done() called multiple times'));
4014 // finished
4015 function done(err) {
4016 if (self.timedOut) return;
4017 if (finished) return multiple(err);
4018 self.clearTimeout();
4019 self.duration = new Date() - start;
4020 finished = true;
4021 fn(err);
4024 // for .resetTimeout()
4025 this.callback = done;
4027 // async
4028 if (this.async) {
4029 try {
4030 this.fn.call(ctx, function(err) {
4031 if (err instanceof Error || toString.call(err) === '[object Error]') return done(err);
4032 if (null != err) return done(new Error('done() invoked with non-Error: ' + err));
4033 done();
4035 } catch (err) {
4036 done(err);
4038 return;
4041 if (this.asyncOnly) {
4042 return done(new Error('--async-only option in use without declaring `done()`'));
4045 // sync
4046 try {
4047 if (!this.pending) this.fn.call(ctx);
4048 this.duration = new Date() - start;
4049 fn();
4050 } catch (err) {
4051 fn(err);
4054 }); // module: runnable.js
4056 require.register('runner.js', function(module, exports, require) {
4058 * Module dependencies.
4061 var EventEmitter = require('browser/events').EventEmitter,
4062 debug = require('browser/debug')('mocha:runner'),
4063 Test = require('./test'),
4064 utils = require('./utils'),
4065 filter = utils.filter,
4066 keys = utils.keys;
4069 * Non-enumerable globals.
4072 var globals = [
4073 'setTimeout',
4074 'clearTimeout',
4075 'setInterval',
4076 'clearInterval',
4077 'XMLHttpRequest',
4078 'Date'
4082 * Expose `Runner`.
4085 module.exports = Runner;
4088 * Initialize a `Runner` for the given `suite`.
4090 * Events:
4092 * - `start` execution started
4093 * - `end` execution complete
4094 * - `suite` (suite) test suite execution started
4095 * - `suite end` (suite) all tests (and sub-suites) have finished
4096 * - `test` (test) test execution started
4097 * - `test end` (test) test completed
4098 * - `hook` (hook) hook execution started
4099 * - `hook end` (hook) hook complete
4100 * - `pass` (test) test passed
4101 * - `fail` (test, err) test failed
4103 * @api public
4106 function Runner(suite) {
4107 var self = this;
4108 this._globals = [];
4109 this.suite = suite;
4110 this.total = suite.total();
4111 this.failures = 0;
4112 this.on('test end', function(test) {
4113 self.checkGlobals(test);
4115 this.on('hook end', function(hook) {
4116 self.checkGlobals(hook);
4118 this.grep(/.*/);
4119 this.globals(this.globalProps().concat(['errno']));
4123 * Wrapper for setImmediate, process.nextTick, or browser polyfill.
4125 * @param {Function} fn
4126 * @api private
4129 Runner.immediately = global.setImmediate || process.nextTick;
4132 * Inherit from `EventEmitter.prototype`.
4135 function F() {}
4136 F.prototype = EventEmitter.prototype;
4137 Runner.prototype = new F();
4138 Runner.prototype.constructor = Runner;
4141 * Run tests with full titles matching `re`. Updates runner.total
4142 * with number of tests matched.
4144 * @param {RegExp} re
4145 * @param {Boolean} invert
4146 * @return {Runner} for chaining
4147 * @api public
4150 Runner.prototype.grep = function(re, invert) {
4151 debug('grep %s', re);
4152 this._grep = re;
4153 this._invert = invert;
4154 this.total = this.grepTotal(this.suite);
4155 return this;
4159 * Returns the number of tests matching the grep search for the
4160 * given suite.
4162 * @param {Suite} suite
4163 * @return {Number}
4164 * @api public
4167 Runner.prototype.grepTotal = function(suite) {
4168 var self = this;
4169 var total = 0;
4171 suite.eachTest(function(test) {
4172 var match = self._grep.test(test.fullTitle());
4173 if (self._invert) match = !match;
4174 if (match) total++;
4177 return total;
4181 * Return a list of global properties.
4183 * @return {Array}
4184 * @api private
4187 Runner.prototype.globalProps = function() {
4188 var props = utils.keys(global);
4190 // non-enumerables
4191 for (var i = 0; i < globals.length; ++i) {
4192 if (~utils.indexOf(props, globals[i])) continue;
4193 props.push(globals[i]);
4196 return props;
4200 * Allow the given `arr` of globals.
4202 * @param {Array} arr
4203 * @return {Runner} for chaining
4204 * @api public
4207 Runner.prototype.globals = function(arr) {
4208 if (0 == arguments.length) return this._globals;
4209 debug('globals %j', arr);
4210 utils.forEach(
4211 arr,
4212 function(arr) {
4213 this._globals.push(arr);
4215 this
4217 return this;
4221 * Check for global variable leaks.
4223 * @api private
4226 Runner.prototype.checkGlobals = function(test) {
4227 if (this.ignoreLeaks) return;
4228 var ok = this._globals;
4229 var globals = this.globalProps();
4230 var isNode = process.kill;
4231 var leaks;
4233 // check length - 2 ('errno' and 'location' globals)
4234 if (isNode && 1 == ok.length - globals.length) return;
4235 else if (2 == ok.length - globals.length) return;
4237 leaks = filterLeaks(ok, globals);
4238 this._globals = this._globals.concat(leaks);
4240 if (leaks.length > 1) {
4241 this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
4242 } else if (leaks.length) {
4243 this.fail(test, new Error('global leak detected: ' + leaks[0]));
4248 * Fail the given `test`.
4250 * @param {Test} test
4251 * @param {Error} err
4252 * @api private
4255 Runner.prototype.fail = function(test, err) {
4256 ++this.failures;
4257 test.state = 'failed';
4259 if ('string' == typeof err) {
4260 err = new Error('the string "' + err + '" was thrown, throw an Error :)');
4263 this.emit('fail', test, err);
4267 * Fail the given `hook` with `err`.
4269 * Hook failures (currently) hard-end due
4270 * to that fact that a failing hook will
4271 * surely cause subsequent tests to fail,
4272 * causing jumbled reporting.
4274 * @param {Hook} hook
4275 * @param {Error} err
4276 * @api private
4279 Runner.prototype.failHook = function(hook, err) {
4280 this.fail(hook, err);
4281 this.emit('end');
4285 * Run hook `name` callbacks and then invoke `fn()`.
4287 * @param {String} name
4288 * @param {Function} function
4289 * @api private
4292 Runner.prototype.hook = function(name, fn) {
4293 var suite = this.suite,
4294 hooks = suite['_' + name],
4295 self = this,
4296 timer;
4298 function next(i) {
4299 var hook = hooks[i];
4300 if (!hook) return fn();
4301 self.currentRunnable = hook;
4303 self.emit('hook', hook);
4305 hook.on('error', function(err) {
4306 self.failHook(hook, err);
4309 hook.run(function(err) {
4310 hook.removeAllListeners('error');
4311 var testError = hook.error();
4312 if (testError) self.fail(self.test, testError);
4313 if (err) return self.failHook(hook, err);
4314 self.emit('hook end', hook);
4315 next(++i);
4319 Runner.immediately(function() {
4320 next(0);
4325 * Run hook `name` for the given array of `suites`
4326 * in order, and callback `fn(err)`.
4328 * @param {String} name
4329 * @param {Array} suites
4330 * @param {Function} fn
4331 * @api private
4334 Runner.prototype.hooks = function(name, suites, fn) {
4335 var self = this,
4336 orig = this.suite;
4338 function next(suite) {
4339 self.suite = suite;
4341 if (!suite) {
4342 self.suite = orig;
4343 return fn();
4346 self.hook(name, function(err) {
4347 if (err) {
4348 self.suite = orig;
4349 return fn(err);
4352 next(suites.pop());
4356 next(suites.pop());
4360 * Run hooks from the top level down.
4362 * @param {String} name
4363 * @param {Function} fn
4364 * @api private
4367 Runner.prototype.hookUp = function(name, fn) {
4368 var suites = [this.suite].concat(this.parents()).reverse();
4369 this.hooks(name, suites, fn);
4373 * Run hooks from the bottom up.
4375 * @param {String} name
4376 * @param {Function} fn
4377 * @api private
4380 Runner.prototype.hookDown = function(name, fn) {
4381 var suites = [this.suite].concat(this.parents());
4382 this.hooks(name, suites, fn);
4386 * Return an array of parent Suites from
4387 * closest to furthest.
4389 * @return {Array}
4390 * @api private
4393 Runner.prototype.parents = function() {
4394 var suite = this.suite,
4395 suites = [];
4396 while ((suite = suite.parent)) suites.push(suite);
4397 return suites;
4401 * Run the current test and callback `fn(err)`.
4403 * @param {Function} fn
4404 * @api private
4407 Runner.prototype.runTest = function(fn) {
4408 var test = this.test,
4409 self = this;
4411 if (this.asyncOnly) test.asyncOnly = true;
4413 try {
4414 test.on('error', function(err) {
4415 self.fail(test, err);
4417 test.run(fn);
4418 } catch (err) {
4419 fn(err);
4424 * Run tests in the given `suite` and invoke
4425 * the callback `fn()` when complete.
4427 * @param {Suite} suite
4428 * @param {Function} fn
4429 * @api private
4432 Runner.prototype.runTests = function(suite, fn) {
4433 var self = this,
4434 tests = suite.tests.slice(),
4435 test;
4437 function next(err) {
4438 // if we bail after first err
4439 if (self.failures && suite._bail) return fn();
4441 // next test
4442 test = tests.shift();
4444 // all done
4445 if (!test) return fn();
4447 // grep
4448 var match = self._grep.test(test.fullTitle());
4449 if (self._invert) match = !match;
4450 if (!match) return next();
4452 // pending
4453 if (test.pending) {
4454 self.emit('pending', test);
4455 self.emit('test end', test);
4456 return next();
4459 // execute test and hook(s)
4460 self.emit('test', (self.test = test));
4461 self.hookDown('beforeEach', function() {
4462 self.currentRunnable = self.test;
4463 self.runTest(function(err) {
4464 test = self.test;
4466 if (err) {
4467 self.fail(test, err);
4468 self.emit('test end', test);
4469 return self.hookUp('afterEach', next);
4472 test.state = 'passed';
4473 self.emit('pass', test);
4474 self.emit('test end', test);
4475 self.hookUp('afterEach', next);
4480 this.next = next;
4481 next();
4485 * Run the given `suite` and invoke the
4486 * callback `fn()` when complete.
4488 * @param {Suite} suite
4489 * @param {Function} fn
4490 * @api private
4493 Runner.prototype.runSuite = function(suite, fn) {
4494 var total = this.grepTotal(suite),
4495 self = this,
4496 i = 0;
4498 debug('run suite %s', suite.fullTitle());
4500 if (!total) return fn();
4502 this.emit('suite', (this.suite = suite));
4504 function next() {
4505 var curr = suite.suites[i++];
4506 if (!curr) return done();
4507 self.runSuite(curr, next);
4510 function done() {
4511 self.suite = suite;
4512 self.hook('afterAll', function() {
4513 self.emit('suite end', suite);
4514 fn();
4518 this.hook('beforeAll', function() {
4519 self.runTests(suite, next);
4524 * Handle uncaught exceptions.
4526 * @param {Error} err
4527 * @api private
4530 Runner.prototype.uncaught = function(err) {
4531 debug('uncaught exception %s', err.message);
4532 var runnable = this.currentRunnable;
4533 if (!runnable || 'failed' == runnable.state) return;
4534 runnable.clearTimeout();
4535 err.uncaught = true;
4536 this.fail(runnable, err);
4538 // recover from test
4539 if ('test' == runnable.type) {
4540 this.emit('test end', runnable);
4541 this.hookUp('afterEach', this.next);
4542 return;
4545 // bail on hooks
4546 this.emit('end');
4550 * Run the root suite and invoke `fn(failures)`
4551 * on completion.
4553 * @param {Function} fn
4554 * @return {Runner} for chaining
4555 * @api public
4558 Runner.prototype.run = function(fn) {
4559 var self = this,
4560 fn = fn || function() {};
4562 function uncaught(err) {
4563 self.uncaught(err);
4566 debug('start');
4568 // callback
4569 this.on('end', function() {
4570 debug('end');
4571 process.removeListener('uncaughtException', uncaught);
4572 fn(self.failures);
4575 // run suites
4576 this.emit('start');
4577 this.runSuite(this.suite, function() {
4578 debug('finished running');
4579 self.emit('end');
4582 // uncaught exception
4583 process.on('uncaughtException', uncaught);
4585 return this;
4589 * Filter leaks with the given globals flagged as `ok`.
4591 * @param {Array} ok
4592 * @param {Array} globals
4593 * @return {Array}
4594 * @api private
4597 function filterLeaks(ok, globals) {
4598 return filter(globals, function(key) {
4599 var matched = filter(ok, function(ok) {
4600 if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
4601 // Opera and IE expose global variables for HTML element IDs (issue #243)
4602 if (/^mocha-/.test(key)) return true;
4603 return key == ok;
4605 return matched.length == 0 && (!global.navigator || 'onerror' !== key);
4608 }); // module: runner.js
4610 require.register('suite.js', function(module, exports, require) {
4612 * Module dependencies.
4615 var EventEmitter = require('browser/events').EventEmitter,
4616 debug = require('browser/debug')('mocha:suite'),
4617 milliseconds = require('./ms'),
4618 utils = require('./utils'),
4619 Hook = require('./hook');
4622 * Expose `Suite`.
4625 exports = module.exports = Suite;
4628 * Create a new `Suite` with the given `title`
4629 * and parent `Suite`. When a suite with the
4630 * same title is already present, that suite
4631 * is returned to provide nicer reporter
4632 * and more flexible meta-testing.
4634 * @param {Suite} parent
4635 * @param {String} title
4636 * @return {Suite}
4637 * @api public
4640 exports.create = function(parent, title) {
4641 var suite = new Suite(title, parent.ctx);
4642 suite.parent = parent;
4643 if (parent.pending) suite.pending = true;
4644 title = suite.fullTitle();
4645 parent.addSuite(suite);
4646 return suite;
4650 * Initialize a new `Suite` with the given
4651 * `title` and `ctx`.
4653 * @param {String} title
4654 * @param {Context} ctx
4655 * @api private
4658 function Suite(title, ctx) {
4659 this.title = title;
4660 this.ctx = ctx;
4661 this.suites = [];
4662 this.tests = [];
4663 this.pending = false;
4664 this._beforeEach = [];
4665 this._beforeAll = [];
4666 this._afterEach = [];
4667 this._afterAll = [];
4668 this.root = !title;
4669 this._timeout = 2000;
4670 this._slow = 75;
4671 this._bail = false;
4675 * Inherit from `EventEmitter.prototype`.
4678 function F() {}
4679 F.prototype = EventEmitter.prototype;
4680 Suite.prototype = new F();
4681 Suite.prototype.constructor = Suite;
4684 * Return a clone of this `Suite`.
4686 * @return {Suite}
4687 * @api private
4690 Suite.prototype.clone = function() {
4691 var suite = new Suite(this.title);
4692 debug('clone');
4693 suite.ctx = this.ctx;
4694 suite.timeout(this.timeout());
4695 suite.slow(this.slow());
4696 suite.bail(this.bail());
4697 return suite;
4701 * Set timeout `ms` or short-hand such as "2s".
4703 * @param {Number|String} ms
4704 * @return {Suite|Number} for chaining
4705 * @api private
4708 Suite.prototype.timeout = function(ms) {
4709 if (0 == arguments.length) return this._timeout;
4710 if ('string' == typeof ms) ms = milliseconds(ms);
4711 debug('timeout %d', ms);
4712 this._timeout = parseInt(ms, 10);
4713 return this;
4717 * Set slow `ms` or short-hand such as "2s".
4719 * @param {Number|String} ms
4720 * @return {Suite|Number} for chaining
4721 * @api private
4724 Suite.prototype.slow = function(ms) {
4725 if (0 === arguments.length) return this._slow;
4726 if ('string' == typeof ms) ms = milliseconds(ms);
4727 debug('slow %d', ms);
4728 this._slow = ms;
4729 return this;
4733 * Sets whether to bail after first error.
4735 * @parma {Boolean} bail
4736 * @return {Suite|Number} for chaining
4737 * @api private
4740 Suite.prototype.bail = function(bail) {
4741 if (0 == arguments.length) return this._bail;
4742 debug('bail %s', bail);
4743 this._bail = bail;
4744 return this;
4748 * Run `fn(test[, done])` before running tests.
4750 * @param {Function} fn
4751 * @return {Suite} for chaining
4752 * @api private
4755 Suite.prototype.beforeAll = function(fn) {
4756 if (this.pending) return this;
4757 var hook = new Hook('"before all" hook', fn);
4758 hook.parent = this;
4759 hook.timeout(this.timeout());
4760 hook.slow(this.slow());
4761 hook.ctx = this.ctx;
4762 this._beforeAll.push(hook);
4763 this.emit('beforeAll', hook);
4764 return this;
4768 * Run `fn(test[, done])` after running tests.
4770 * @param {Function} fn
4771 * @return {Suite} for chaining
4772 * @api private
4775 Suite.prototype.afterAll = function(fn) {
4776 if (this.pending) return this;
4777 var hook = new Hook('"after all" hook', fn);
4778 hook.parent = this;
4779 hook.timeout(this.timeout());
4780 hook.slow(this.slow());
4781 hook.ctx = this.ctx;
4782 this._afterAll.push(hook);
4783 this.emit('afterAll', hook);
4784 return this;
4788 * Run `fn(test[, done])` before each test case.
4790 * @param {Function} fn
4791 * @return {Suite} for chaining
4792 * @api private
4795 Suite.prototype.beforeEach = function(fn) {
4796 if (this.pending) return this;
4797 var hook = new Hook('"before each" hook', fn);
4798 hook.parent = this;
4799 hook.timeout(this.timeout());
4800 hook.slow(this.slow());
4801 hook.ctx = this.ctx;
4802 this._beforeEach.push(hook);
4803 this.emit('beforeEach', hook);
4804 return this;
4808 * Run `fn(test[, done])` after each test case.
4810 * @param {Function} fn
4811 * @return {Suite} for chaining
4812 * @api private
4815 Suite.prototype.afterEach = function(fn) {
4816 if (this.pending) return this;
4817 var hook = new Hook('"after each" hook', fn);
4818 hook.parent = this;
4819 hook.timeout(this.timeout());
4820 hook.slow(this.slow());
4821 hook.ctx = this.ctx;
4822 this._afterEach.push(hook);
4823 this.emit('afterEach', hook);
4824 return this;
4828 * Add a test `suite`.
4830 * @param {Suite} suite
4831 * @return {Suite} for chaining
4832 * @api private
4835 Suite.prototype.addSuite = function(suite) {
4836 suite.parent = this;
4837 suite.timeout(this.timeout());
4838 suite.slow(this.slow());
4839 suite.bail(this.bail());
4840 this.suites.push(suite);
4841 this.emit('suite', suite);
4842 return this;
4846 * Add a `test` to this suite.
4848 * @param {Test} test
4849 * @return {Suite} for chaining
4850 * @api private
4853 Suite.prototype.addTest = function(test) {
4854 test.parent = this;
4855 test.timeout(this.timeout());
4856 test.slow(this.slow());
4857 test.ctx = this.ctx;
4858 this.tests.push(test);
4859 this.emit('test', test);
4860 return this;
4864 * Return the full title generated by recursively
4865 * concatenating the parent's full title.
4867 * @return {String}
4868 * @api public
4871 Suite.prototype.fullTitle = function() {
4872 if (this.parent) {
4873 var full = this.parent.fullTitle();
4874 if (full) return full + ' ' + this.title;
4876 return this.title;
4880 * Return the total number of tests.
4882 * @return {Number}
4883 * @api public
4886 Suite.prototype.total = function() {
4887 return (
4888 utils.reduce(
4889 this.suites,
4890 function(sum, suite) {
4891 return sum + suite.total();
4894 ) + this.tests.length
4899 * Iterates through each suite recursively to find
4900 * all tests. Applies a function in the format
4901 * `fn(test)`.
4903 * @param {Function} fn
4904 * @return {Suite}
4905 * @api private
4908 Suite.prototype.eachTest = function(fn) {
4909 utils.forEach(this.tests, fn);
4910 utils.forEach(this.suites, function(suite) {
4911 suite.eachTest(fn);
4913 return this;
4915 }); // module: suite.js
4917 require.register('test.js', function(module, exports, require) {
4919 * Module dependencies.
4922 var Runnable = require('./runnable');
4925 * Expose `Test`.
4928 module.exports = Test;
4931 * Initialize a new `Test` with the given `title` and callback `fn`.
4933 * @param {String} title
4934 * @param {Function} fn
4935 * @api private
4938 function Test(title, fn) {
4939 Runnable.call(this, title, fn);
4940 this.pending = !fn;
4941 this.type = 'test';
4945 * Inherit from `Runnable.prototype`.
4948 function F() {}
4949 F.prototype = Runnable.prototype;
4950 Test.prototype = new F();
4951 Test.prototype.constructor = Test;
4952 }); // module: test.js
4954 require.register('utils.js', function(module, exports, require) {
4956 * Module dependencies.
4959 var fs = require('browser/fs'),
4960 path = require('browser/path'),
4961 join = path.join,
4962 debug = require('browser/debug')('mocha:watch');
4965 * Ignored directories.
4968 var ignore = ['node_modules', '.git'];
4971 * Escape special characters in the given string of html.
4973 * @param {String} html
4974 * @return {String}
4975 * @api private
4978 exports.escape = function(html) {
4979 return String(html)
4980 .replace(/&/g, '&amp;')
4981 .replace(/"/g, '&quot;')
4982 .replace(/</g, '&lt;')
4983 .replace(/>/g, '&gt;');
4987 * Array#forEach (<=IE8)
4989 * @param {Array} array
4990 * @param {Function} fn
4991 * @param {Object} scope
4992 * @api private
4995 exports.forEach = function(arr, fn, scope) {
4996 for (var i = 0, l = arr.length; i < l; i++) fn.call(scope, arr[i], i);
5000 * Array#indexOf (<=IE8)
5002 * @parma {Array} arr
5003 * @param {Object} obj to find index of
5004 * @param {Number} start
5005 * @api private
5008 exports.indexOf = function(arr, obj, start) {
5009 for (var i = start || 0, l = arr.length; i < l; i++) {
5010 if (arr[i] === obj) return i;
5012 return -1;
5016 * Array#reduce (<=IE8)
5018 * @param {Array} array
5019 * @param {Function} fn
5020 * @param {Object} initial value
5021 * @api private
5024 exports.reduce = function(arr, fn, val) {
5025 var rval = val;
5027 for (var i = 0, l = arr.length; i < l; i++) {
5028 rval = fn(rval, arr[i], i, arr);
5031 return rval;
5035 * Array#filter (<=IE8)
5037 * @param {Array} array
5038 * @param {Function} fn
5039 * @api private
5042 exports.filter = function(arr, fn) {
5043 var ret = [];
5045 for (var i = 0, l = arr.length; i < l; i++) {
5046 var val = arr[i];
5047 if (fn(val, i, arr)) ret.push(val);
5050 return ret;
5054 * Object.keys (<=IE8)
5056 * @param {Object} obj
5057 * @return {Array} keys
5058 * @api private
5061 exports.keys =
5062 Object.keys ||
5063 function(obj) {
5064 var keys = [],
5065 has = Object.prototype.hasOwnProperty; // for `window` on <=IE8
5067 for (var key in obj) {
5068 if (has.call(obj, key)) {
5069 keys.push(key);
5073 return keys;
5077 * Watch the given `files` for changes
5078 * and invoke `fn(file)` on modification.
5080 * @param {Array} files
5081 * @param {Function} fn
5082 * @api private
5085 exports.watch = function(files, fn) {
5086 var options = { interval: 100 };
5087 files.forEach(function(file) {
5088 debug('file %s', file);
5089 fs.watchFile(file, options, function(curr, prev) {
5090 if (prev.mtime < curr.mtime) fn(file);
5096 * Ignored files.
5099 function ignored(path) {
5100 return !~ignore.indexOf(path);
5104 * Lookup files in the given `dir`.
5106 * @return {Array}
5107 * @api private
5110 exports.files = function(dir, ret) {
5111 ret = ret || [];
5113 fs.readdirSync(dir)
5114 .filter(ignored)
5115 .forEach(function(path) {
5116 path = join(dir, path);
5117 if (fs.statSync(path).isDirectory()) {
5118 exports.files(path, ret);
5119 } else if (path.match(/\.(js|coffee)$/)) {
5120 ret.push(path);
5124 return ret;
5128 * Compute a slug from the given `str`.
5130 * @param {String} str
5131 * @return {String}
5132 * @api private
5135 exports.slug = function(str) {
5136 return str
5137 .toLowerCase()
5138 .replace(/ +/g, '-')
5139 .replace(/[^-\w]/g, '');
5143 * Strip the function definition from `str`,
5144 * and re-indent for pre whitespace.
5147 exports.clean = function(str) {
5148 str = str.replace(/^function *\(.*\) *{/, '').replace(/\s+\}$/, '');
5150 var spaces = str.match(/^\n?( *)/)[1].length,
5151 re = new RegExp('^ {' + spaces + '}', 'gm');
5153 str = str.replace(re, '');
5155 return exports.trim(str);
5159 * Escape regular expression characters in `str`.
5161 * @param {String} str
5162 * @return {String}
5163 * @api private
5166 exports.escapeRegexp = function(str) {
5167 return str.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&');
5171 * Trim the given `str`.
5173 * @param {String} str
5174 * @return {String}
5175 * @api private
5178 exports.trim = function(str) {
5179 return str.replace(/^\s+|\s+$/g, '');
5183 * Parse the given `qs`.
5185 * @param {String} qs
5186 * @return {Object}
5187 * @api private
5190 exports.parseQuery = function(qs) {
5191 return exports.reduce(
5192 qs.replace('?', '').split('&'),
5193 function(obj, pair) {
5194 var i = pair.indexOf('='),
5195 key = pair.slice(0, i),
5196 val = pair.slice(++i);
5198 obj[key] = decodeURIComponent(val);
5199 return obj;
5206 * Highlight the given string of `js`.
5208 * @param {String} js
5209 * @return {String}
5210 * @api private
5213 function highlight(js) {
5214 return js
5215 .replace(/</g, '&lt;')
5216 .replace(/>/g, '&gt;')
5217 .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
5218 .replace(/('.*?')/gm, '<span class="string">$1</span>')
5219 .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
5220 .replace(/(\d+)/gm, '<span class="number">$1</span>')
5221 .replace(
5222 /\bnew *(\w+)/gm,
5223 '<span class="keyword">new</span> <span class="init">$1</span>'
5225 .replace(
5226 /\b(function|new|throw|return|var|if|else)\b/gm,
5227 '<span class="keyword">$1</span>'
5232 * Highlight the contents of tag `name`.
5234 * @param {String} name
5235 * @api private
5238 exports.highlightTags = function(name) {
5239 var code = document.getElementsByTagName(name);
5240 for (var i = 0, len = code.length; i < len; ++i) {
5241 code[i].innerHTML = highlight(code[i].innerHTML);
5244 }); // module: utils.js
5246 * Node shims.
5248 * These are meant only to allow
5249 * mocha.js to run untouched, not
5250 * to allow running node code in
5251 * the browser.
5254 process = {};
5255 process.exit = function(status) {};
5256 process.stdout = {};
5257 global = window;
5260 * Remove uncaughtException listener.
5263 process.removeListener = function(e) {
5264 if ('uncaughtException' == e) {
5265 window.onerror = null;
5270 * Implements uncaughtException listener.
5273 process.on = function(e, fn) {
5274 if ('uncaughtException' == e) {
5275 window.onerror = function(err, url, line) {
5276 fn(new Error(err + ' (' + url + ':' + line + ')'));
5281 // boot
5282 (function() {
5284 * Expose mocha.
5287 var Mocha = (window.Mocha = require('mocha')),
5288 mocha = (window.mocha = new Mocha({ reporter: 'html' }));
5290 var immediateQueue = [],
5291 immediateTimeout;
5293 function timeslice() {
5294 var immediateStart = new Date().getTime();
5295 while (immediateQueue.length && new Date().getTime() - immediateStart < 100) {
5296 immediateQueue.shift()();
5298 if (immediateQueue.length) {
5299 immediateTimeout = setTimeout(timeslice, 0);
5300 } else {
5301 immediateTimeout = null;
5306 * High-performance override of Runner.immediately.
5309 Mocha.Runner.immediately = function(callback) {
5310 immediateQueue.push(callback);
5311 if (!immediateTimeout) {
5312 immediateTimeout = setTimeout(timeslice, 0);
5317 * Override ui to ensure that the ui functions are initialized.
5318 * Normally this would happen in Mocha.prototype.loadFiles.
5321 mocha.ui = function(ui) {
5322 Mocha.prototype.ui.call(this, ui);
5323 this.suite.emit('pre-require', window, null, this);
5324 return this;
5328 * Setup mocha with the given setting options.
5331 mocha.setup = function(opts) {
5332 if ('string' == typeof opts) opts = { ui: opts };
5333 for (var opt in opts) this[opt](opts[opt]);
5334 return this;
5338 * Run mocha, returning the Runner.
5341 mocha.run = function(fn) {
5342 var options = mocha.options;
5343 mocha.globals('location');
5345 var query = Mocha.utils.parseQuery(window.location.search || '');
5346 if (query.grep) mocha.grep(query.grep);
5347 if (query.invert) mocha.invert();
5349 return Mocha.prototype.run.call(mocha, function() {
5350 Mocha.utils.highlightTags('code');
5351 if (fn) fn();
5354 })();
5355 })();
5356 return mocha;