1;(function(){ 2 3// CommonJS require() 4 5function 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)); 12 } 13 return mod.exports; 14 } 15 16require.modules = {}; 17 18require.resolve = function (path){ 19 var orig = path 20 , reg = path + '.js' 21 , index = path + '/index.js'; 22 return require.modules[reg] && reg 23 || require.modules[index] && index 24 || orig; 25 }; 26 27require.register = function (path, fn){ 28 require.modules[path] = fn; 29 }; 30 31require.relative = function (parent) { 32 return function(p){ 33 if ('.' != p.charAt(0)) return require(p); 34 35 var path = parent.split('/') 36 , segs = p.split('/'); 37 path.pop(); 38 39 for (var i = 0; i < segs.length; i++) { 40 var seg = segs[i]; 41 if ('..' == seg) path.pop(); 42 else if ('.' != seg) path.push(seg); 43 } 44 45 return require(path.join('/')); 46 }; 47 }; 48 49 50require.register("browser/debug.js", function(module, exports, require){ 51module.exports = function(type){ 52 return function(){ 53 } 54}; 55 56}); // module: browser/debug.js 57 58require.register("browser/diff.js", function(module, exports, require){ 59/* See LICENSE file for terms of use */ 60 61/* 62 * Text diff implementation. 63 * 64 * This library supports the following APIS: 65 * JsDiff.diffChars: Character by character diff 66 * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace 67 * JsDiff.diffLines: Line based diff 68 * 69 * JsDiff.diffCss: Diff targeted at CSS content 70 * 71 * These methods are based on the implementation proposed in 72 * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). 73 * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927 74 */ 75var JsDiff = (function() { 76 /*jshint maxparams: 5*/ 77 function clonePath(path) { 78 return { newPos: path.newPos, components: path.components.slice(0) }; 79 } 80 function removeEmpty(array) { 81 var ret = []; 82 for (var i = 0; i < array.length; i++) { 83 if (array[i]) { 84 ret.push(array[i]); 85 } 86 } 87 return ret; 88 } 89 function escapeHTML(s) { 90 var n = s; 91 n = n.replace(/&/g, '&'); 92 n = n.replace(/</g, '<'); 93 n = n.replace(/>/g, '>'); 94 n = n.replace(/"/g, '"'); 95 96 return n; 97 } 98 99 var Diff = function(ignoreWhitespace) { 100 this.ignoreWhitespace = ignoreWhitespace; 101 }; 102 Diff.prototype = { 103 diff: function(oldString, newString) { 104 // Handle the identity case (this is due to unrolling editLength == 0 105 if (newString === oldString) { 106 return [{ value: newString }]; 107 } 108 if (!newString) { 109 return [{ value: oldString, removed: true }]; 110 } 111 if (!oldString) { 112 return [{ value: newString, added: true }]; 113 } 114 115 newString = this.tokenize(newString); 116 oldString = this.tokenize(oldString); 117 118 var newLen = newString.length, oldLen = oldString.length; 119 var maxEditLength = newLen + oldLen; 120 var bestPath = [{ newPos: -1, components: [] }]; 121 122 // Seed editLength = 0 123 var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); 124 if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) { 125 return bestPath[0].components; 126 } 127 128 for (var editLength = 1; editLength <= maxEditLength; editLength++) { 129 for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) { 130 var basePath; 131 var addPath = bestPath[diagonalPath-1], 132 removePath = bestPath[diagonalPath+1]; 133 oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; 134 if (addPath) { 135 // No one else is going to attempt to use this value, clear it 136 bestPath[diagonalPath-1] = undefined; 137 } 138 139 var canAdd = addPath && addPath.newPos+1 < newLen; 140 var canRemove = removePath && 0 <= oldPos && oldPos < oldLen; 141 if (!canAdd && !canRemove) { 142 bestPath[diagonalPath] = undefined; 143 continue; 144 } 145 146 // Select the diagonal that we want to branch from. We select the prior 147 // path whose position in the new string is the farthest from the origin 148 // and does not pass the bounds of the diff graph 149 if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { 150 basePath = clonePath(removePath); 151 this.pushComponent(basePath.components, oldString[oldPos], undefined, true); 152 } else { 153 basePath = clonePath(addPath); 154 basePath.newPos++; 155 this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined); 156 } 157 158 var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath); 159 160 if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) { 161 return basePath.components; 162 } else { 163 bestPath[diagonalPath] = basePath; 164 } 165 } 166 } 167 }, 168 169 pushComponent: function(components, value, added, removed) { 170 var last = components[components.length-1]; 171 if (last && last.added === added && last.removed === removed) { 172 // We need to clone here as the component clone operation is just 173 // as shallow array clone 174 components[components.length-1] = 175 {value: this.join(last.value, value), added: added, removed: removed }; 176 } else { 177 components.push({value: value, added: added, removed: removed }); 178 } 179 }, 180 extractCommon: function(basePath, newString, oldString, diagonalPath) { 181 var newLen = newString.length, 182 oldLen = oldString.length, 183 newPos = basePath.newPos, 184 oldPos = newPos - diagonalPath; 185 while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) { 186 newPos++; 187 oldPos++; 188 189 this.pushComponent(basePath.components, newString[newPos], undefined, undefined); 190 } 191 basePath.newPos = newPos; 192 return oldPos; 193 }, 194 195 equals: function(left, right) { 196 var reWhitespace = /\S/; 197 if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) { 198 return true; 199 } else { 200 return left === right; 201 } 202 }, 203 join: function(left, right) { 204 return left + right; 205 }, 206 tokenize: function(value) { 207 return value; 208 } 209 }; 210 211 var CharDiff = new Diff(); 212 213 var WordDiff = new Diff(true); 214 var WordWithSpaceDiff = new Diff(); 215 WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) { 216 return removeEmpty(value.split(/(\s+|\b)/)); 217 }; 218 219 var CssDiff = new Diff(true); 220 CssDiff.tokenize = function(value) { 221 return removeEmpty(value.split(/([{}:;,]|\s+)/)); 222 }; 223 224 var LineDiff = new Diff(); 225 LineDiff.tokenize = function(value) { 226 var retLines = [], 227 lines = value.split(/^/m); 228 229 for(var i = 0; i < lines.length; i++) { 230 var line = lines[i], 231 lastLine = lines[i - 1]; 232 233 // Merge lines that may contain windows new lines 234 if (line == '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') { 235 retLines[retLines.length - 1] += '\n'; 236 } else if (line) { 237 retLines.push(line); 238 } 239 } 240 241 return retLines; 242 }; 243 244 return { 245 Diff: Diff, 246 247 diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); }, 248 diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); }, 249 diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); }, 250 diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); }, 251 252 diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); }, 253 254 createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { 255 var ret = []; 256 257 ret.push('Index: ' + fileName); 258 ret.push('==================================================================='); 259 ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader)); 260 ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader)); 261 262 var diff = LineDiff.diff(oldStr, newStr); 263 if (!diff[diff.length-1].value) { 264 diff.pop(); // Remove trailing newline add 265 } 266 diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier 267 268 function contextLines(lines) { 269 return lines.map(function(entry) { return ' ' + entry; }); 270 } 271 function eofNL(curRange, i, current) { 272 var last = diff[diff.length-2], 273 isLast = i === diff.length-2, 274 isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed); 275 276 // Figure out if this is the last line for the given file and missing NL 277 if (!/\n$/.test(current.value) && (isLast || isLastOfType)) { 278 curRange.push('\\ No newline at end of file'); 279 } 280 } 281 282 var oldRangeStart = 0, newRangeStart = 0, curRange = [], 283 oldLine = 1, newLine = 1; 284 for (var i = 0; i < diff.length; i++) { 285 var current = diff[i], 286 lines = current.lines || current.value.replace(/\n$/, '').split('\n'); 287 current.lines = lines; 288 289 if (current.added || current.removed) { 290 if (!oldRangeStart) { 291 var prev = diff[i-1]; 292 oldRangeStart = oldLine; 293 newRangeStart = newLine; 294 295 if (prev) { 296 curRange = contextLines(prev.lines.slice(-4)); 297 oldRangeStart -= curRange.length; 298 newRangeStart -= curRange.length; 299 } 300 } 301 curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; })); 302 eofNL(curRange, i, current); 303 304 if (current.added) { 305 newLine += lines.length; 306 } else { 307 oldLine += lines.length; 308 } 309 } else { 310 if (oldRangeStart) { 311 // Close out any changes that have been output (or join overlapping) 312 if (lines.length <= 8 && i < diff.length-2) { 313 // Overlapping 314 curRange.push.apply(curRange, contextLines(lines)); 315 } else { 316 // end the range and output 317 var contextSize = Math.min(lines.length, 4); 318 ret.push( 319 '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize) 320 + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize) 321 + ' @@'); 322 ret.push.apply(ret, curRange); 323 ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); 324 if (lines.length <= 4) { 325 eofNL(ret, i, current); 326 } 327 328 oldRangeStart = 0; newRangeStart = 0; curRange = []; 329 } 330 } 331 oldLine += lines.length; 332 newLine += lines.length; 333 } 334 } 335 336 return ret.join('\n') + '\n'; 337 }, 338 339 applyPatch: function(oldStr, uniDiff) { 340 var diffstr = uniDiff.split('\n'); 341 var diff = []; 342 var remEOFNL = false, 343 addEOFNL = false; 344 345 for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) { 346 if(diffstr[i][0] === '@') { 347 var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/); 348 diff.unshift({ 349 start:meh[3], 350 oldlength:meh[2], 351 oldlines:[], 352 newlength:meh[4], 353 newlines:[] 354 }); 355 } else if(diffstr[i][0] === '+') { 356 diff[0].newlines.push(diffstr[i].substr(1)); 357 } else if(diffstr[i][0] === '-') { 358 diff[0].oldlines.push(diffstr[i].substr(1)); 359 } else if(diffstr[i][0] === ' ') { 360 diff[0].newlines.push(diffstr[i].substr(1)); 361 diff[0].oldlines.push(diffstr[i].substr(1)); 362 } else if(diffstr[i][0] === '\\') { 363 if (diffstr[i-1][0] === '+') { 364 remEOFNL = true; 365 } else if(diffstr[i-1][0] === '-') { 366 addEOFNL = true; 367 } 368 } 369 } 370 371 var str = oldStr.split('\n'); 372 for (var i = diff.length - 1; i >= 0; i--) { 373 var d = diff[i]; 374 for (var j = 0; j < d.oldlength; j++) { 375 if(str[d.start-1+j] !== d.oldlines[j]) { 376 return false; 377 } 378 } 379 Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines)); 380 } 381 382 if (remEOFNL) { 383 while (!str[str.length-1]) { 384 str.pop(); 385 } 386 } else if (addEOFNL) { 387 str.push(''); 388 } 389 return str.join('\n'); 390 }, 391 392 convertChangesToXML: function(changes){ 393 var ret = []; 394 for ( var i = 0; i < changes.length; i++) { 395 var change = changes[i]; 396 if (change.added) { 397 ret.push('<ins>'); 398 } else if (change.removed) { 399 ret.push('<del>'); 400 } 401 402 ret.push(escapeHTML(change.value)); 403 404 if (change.added) { 405 ret.push('</ins>'); 406 } else if (change.removed) { 407 ret.push('</del>'); 408 } 409 } 410 return ret.join(''); 411 }, 412 413 // See: http://code.google.com/p/google-diff-match-patch/wiki/API 414 convertChangesToDMP: function(changes){ 415 var ret = [], change; 416 for ( var i = 0; i < changes.length; i++) { 417 change = changes[i]; 418 ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]); 419 } 420 return ret; 421 } 422 }; 423})(); 424 425if (typeof module !== 'undefined') { 426 module.exports = JsDiff; 427} 428 429}); // module: browser/diff.js 430 431require.register("browser/escape-string-regexp.js", function(module, exports, require){ 432'use strict'; 433 434var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; 435 436module.exports = function (str) { 437 if (typeof str !== 'string') { 438 throw new TypeError('Expected a string'); 439 } 440 441 return str.replace(matchOperatorsRe, '\\$&'); 442}; 443 444}); // module: browser/escape-string-regexp.js 445 446require.register("browser/events.js", function(module, exports, require){ 447/** 448 * Module exports. 449 */ 450 451exports.EventEmitter = EventEmitter; 452 453/** 454 * Check if `obj` is an array. 455 */ 456 457function isArray(obj) { 458 return '[object Array]' == {}.toString.call(obj); 459} 460 461/** 462 * Event emitter constructor. 463 * 464 * @api public 465 */ 466 467function EventEmitter(){}; 468 469/** 470 * Adds a listener. 471 * 472 * @api public 473 */ 474 475EventEmitter.prototype.on = function (name, fn) { 476 if (!this.$events) { 477 this.$events = {}; 478 } 479 480 if (!this.$events[name]) { 481 this.$events[name] = fn; 482 } else if (isArray(this.$events[name])) { 483 this.$events[name].push(fn); 484 } else { 485 this.$events[name] = [this.$events[name], fn]; 486 } 487 488 return this; 489}; 490 491EventEmitter.prototype.addListener = EventEmitter.prototype.on; 492 493/** 494 * Adds a volatile listener. 495 * 496 * @api public 497 */ 498 499EventEmitter.prototype.once = function (name, fn) { 500 var self = this; 501 502 function on () { 503 self.removeListener(name, on); 504 fn.apply(this, arguments); 505 }; 506 507 on.listener = fn; 508 this.on(name, on); 509 510 return this; 511}; 512 513/** 514 * Removes a listener. 515 * 516 * @api public 517 */ 518 519EventEmitter.prototype.removeListener = function (name, fn) { 520 if (this.$events && this.$events[name]) { 521 var list = this.$events[name]; 522 523 if (isArray(list)) { 524 var pos = -1; 525 526 for (var i = 0, l = list.length; i < l; i++) { 527 if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { 528 pos = i; 529 break; 530 } 531 } 532 533 if (pos < 0) { 534 return this; 535 } 536 537 list.splice(pos, 1); 538 539 if (!list.length) { 540 delete this.$events[name]; 541 } 542 } else if (list === fn || (list.listener && list.listener === fn)) { 543 delete this.$events[name]; 544 } 545 } 546 547 return this; 548}; 549 550/** 551 * Removes all listeners for an event. 552 * 553 * @api public 554 */ 555 556EventEmitter.prototype.removeAllListeners = function (name) { 557 if (name === undefined) { 558 this.$events = {}; 559 return this; 560 } 561 562 if (this.$events && this.$events[name]) { 563 this.$events[name] = null; 564 } 565 566 return this; 567}; 568 569/** 570 * Gets all listeners for a certain event. 571 * 572 * @api public 573 */ 574 575EventEmitter.prototype.listeners = function (name) { 576 if (!this.$events) { 577 this.$events = {}; 578 } 579 580 if (!this.$events[name]) { 581 this.$events[name] = []; 582 } 583 584 if (!isArray(this.$events[name])) { 585 this.$events[name] = [this.$events[name]]; 586 } 587 588 return this.$events[name]; 589}; 590 591/** 592 * Emits an event. 593 * 594 * @api public 595 */ 596 597EventEmitter.prototype.emit = function (name) { 598 if (!this.$events) { 599 return false; 600 } 601 602 var handler = this.$events[name]; 603 604 if (!handler) { 605 return false; 606 } 607 608 var args = [].slice.call(arguments, 1); 609 610 if ('function' == typeof handler) { 611 handler.apply(this, args); 612 } else if (isArray(handler)) { 613 var listeners = handler.slice(); 614 615 for (var i = 0, l = listeners.length; i < l; i++) { 616 listeners[i].apply(this, args); 617 } 618 } else { 619 return false; 620 } 621 622 return true; 623}; 624 625}); // module: browser/events.js 626 627require.register("browser/fs.js", function(module, exports, require){ 628 629}); // module: browser/fs.js 630 631require.register("browser/glob.js", function(module, exports, require){ 632 633}); // module: browser/glob.js 634 635require.register("browser/path.js", function(module, exports, require){ 636 637}); // module: browser/path.js 638 639require.register("browser/progress.js", function(module, exports, require){ 640/** 641 * Expose `Progress`. 642 */ 643 644module.exports = Progress; 645 646/** 647 * Initialize a new `Progress` indicator. 648 */ 649 650function Progress() { 651 this.percent = 0; 652 this.size(0); 653 this.fontSize(11); 654 this.font('helvetica, arial, sans-serif'); 655} 656 657/** 658 * Set progress size to `n`. 659 * 660 * @param {Number} n 661 * @return {Progress} for chaining 662 * @api public 663 */ 664 665Progress.prototype.size = function(n){ 666 this._size = n; 667 return this; 668}; 669 670/** 671 * Set text to `str`. 672 * 673 * @param {String} str 674 * @return {Progress} for chaining 675 * @api public 676 */ 677 678Progress.prototype.text = function(str){ 679 this._text = str; 680 return this; 681}; 682 683/** 684 * Set font size to `n`. 685 * 686 * @param {Number} n 687 * @return {Progress} for chaining 688 * @api public 689 */ 690 691Progress.prototype.fontSize = function(n){ 692 this._fontSize = n; 693 return this; 694}; 695 696/** 697 * Set font `family`. 698 * 699 * @param {String} family 700 * @return {Progress} for chaining 701 */ 702 703Progress.prototype.font = function(family){ 704 this._font = family; 705 return this; 706}; 707 708/** 709 * Update percentage to `n`. 710 * 711 * @param {Number} n 712 * @return {Progress} for chaining 713 */ 714 715Progress.prototype.update = function(n){ 716 this.percent = n; 717 return this; 718}; 719 720/** 721 * Draw on `ctx`. 722 * 723 * @param {CanvasRenderingContext2d} ctx 724 * @return {Progress} for chaining 725 */ 726 727Progress.prototype.draw = function(ctx){ 728 try { 729 var percent = Math.min(this.percent, 100) 730 , size = this._size 731 , half = size / 2 732 , x = half 733 , y = half 734 , rad = half - 1 735 , fontSize = this._fontSize; 736 737 ctx.font = fontSize + 'px ' + this._font; 738 739 var angle = Math.PI * 2 * (percent / 100); 740 ctx.clearRect(0, 0, size, size); 741 742 // outer circle 743 ctx.strokeStyle = '#9f9f9f'; 744 ctx.beginPath(); 745 ctx.arc(x, y, rad, 0, angle, false); 746 ctx.stroke(); 747 748 // inner circle 749 ctx.strokeStyle = '#eee'; 750 ctx.beginPath(); 751 ctx.arc(x, y, rad - 1, 0, angle, true); 752 ctx.stroke(); 753 754 // text 755 var text = this._text || (percent | 0) + '%' 756 , w = ctx.measureText(text).width; 757 758 ctx.fillText( 759 text 760 , x - w / 2 + 1 761 , y + fontSize / 2 - 1); 762 } catch (ex) {} //don't fail if we can't render progress 763 return this; 764}; 765 766}); // module: browser/progress.js 767 768require.register("browser/tty.js", function(module, exports, require){ 769exports.isatty = function(){ 770 return true; 771}; 772 773exports.getWindowSize = function(){ 774 if ('innerHeight' in global) { 775 return [global.innerHeight, global.innerWidth]; 776 } else { 777 // In a Web Worker, the DOM Window is not available. 778 return [640, 480]; 779 } 780}; 781 782}); // module: browser/tty.js 783 784require.register("context.js", function(module, exports, require){ 785/** 786 * Expose `Context`. 787 */ 788 789module.exports = Context; 790 791/** 792 * Initialize a new `Context`. 793 * 794 * @api private 795 */ 796 797function Context(){} 798 799/** 800 * Set or get the context `Runnable` to `runnable`. 801 * 802 * @param {Runnable} runnable 803 * @return {Context} 804 * @api private 805 */ 806 807Context.prototype.runnable = function(runnable){ 808 if (0 == arguments.length) return this._runnable; 809 this.test = this._runnable = runnable; 810 return this; 811}; 812 813/** 814 * Set test timeout `ms`. 815 * 816 * @param {Number} ms 817 * @return {Context} self 818 * @api private 819 */ 820 821Context.prototype.timeout = function(ms){ 822 if (arguments.length === 0) return this.runnable().timeout(); 823 this.runnable().timeout(ms); 824 return this; 825}; 826 827/** 828 * Set test timeout `enabled`. 829 * 830 * @param {Boolean} enabled 831 * @return {Context} self 832 * @api private 833 */ 834 835Context.prototype.enableTimeouts = function (enabled) { 836 this.runnable().enableTimeouts(enabled); 837 return this; 838}; 839 840 841/** 842 * Set test slowness threshold `ms`. 843 * 844 * @param {Number} ms 845 * @return {Context} self 846 * @api private 847 */ 848 849Context.prototype.slow = function(ms){ 850 this.runnable().slow(ms); 851 return this; 852}; 853 854/** 855 * Mark a test as skipped. 856 * 857 * @return {Context} self 858 * @api private 859 */ 860 861Context.prototype.skip = function(){ 862 this.runnable().skip(); 863 return this; 864}; 865 866/** 867 * Inspect the context void of `._runnable`. 868 * 869 * @return {String} 870 * @api private 871 */ 872 873Context.prototype.inspect = function(){ 874 return JSON.stringify(this, function(key, val){ 875 if ('_runnable' == key) return; 876 if ('test' == key) return; 877 return val; 878 }, 2); 879}; 880 881}); // module: context.js 882 883require.register("hook.js", function(module, exports, require){ 884/** 885 * Module dependencies. 886 */ 887 888var Runnable = require('./runnable'); 889 890/** 891 * Expose `Hook`. 892 */ 893 894module.exports = Hook; 895 896/** 897 * Initialize a new `Hook` with the given `title` and callback `fn`. 898 * 899 * @param {String} title 900 * @param {Function} fn 901 * @api private 902 */ 903 904function Hook(title, fn) { 905 Runnable.call(this, title, fn); 906 this.type = 'hook'; 907} 908 909/** 910 * Inherit from `Runnable.prototype`. 911 */ 912 913function F(){}; 914F.prototype = Runnable.prototype; 915Hook.prototype = new F; 916Hook.prototype.constructor = Hook; 917 918 919/** 920 * Get or set the test `err`. 921 * 922 * @param {Error} err 923 * @return {Error} 924 * @api public 925 */ 926 927Hook.prototype.error = function(err){ 928 if (0 == arguments.length) { 929 var err = this._error; 930 this._error = null; 931 return err; 932 } 933 934 this._error = err; 935}; 936 937}); // module: hook.js 938 939require.register("interfaces/bdd.js", function(module, exports, require){ 940/** 941 * Module dependencies. 942 */ 943 944var Suite = require('../suite') 945 , Test = require('../test') 946 , utils = require('../utils') 947 , escapeRe = require('browser/escape-string-regexp'); 948 949/** 950 * BDD-style interface: 951 * 952 * describe('Array', function(){ 953 * describe('#indexOf()', function(){ 954 * it('should return -1 when not present', function(){ 955 * 956 * }); 957 * 958 * it('should return the index when present', function(){ 959 * 960 * }); 961 * }); 962 * }); 963 * 964 */ 965 966module.exports = function(suite){ 967 var suites = [suite]; 968 969 suite.on('pre-require', function(context, file, mocha){ 970 971 var common = require('./common')(suites, context); 972 973 context.before = common.before; 974 context.after = common.after; 975 context.beforeEach = common.beforeEach; 976 context.afterEach = common.afterEach; 977 context.run = mocha.options.delay && common.runWithSuite(suite); 978 /** 979 * Describe a "suite" with the given `title` 980 * and callback `fn` containing nested suites 981 * and/or tests. 982 */ 983 984 context.describe = context.context = function(title, fn){ 985 var suite = Suite.create(suites[0], title); 986 suite.file = file; 987 suites.unshift(suite); 988 fn.call(suite); 989 suites.shift(); 990 return suite; 991 }; 992 993 /** 994 * Pending describe. 995 */ 996 997 context.xdescribe = 998 context.xcontext = 999 context.describe.skip = function(title, fn){ 1000 var suite = Suite.create(suites[0], title); 1001 suite.pending = true; 1002 suites.unshift(suite); 1003 fn.call(suite); 1004 suites.shift(); 1005 }; 1006 1007 /** 1008 * Exclusive suite. 1009 */ 1010 1011 context.describe.only = function(title, fn){ 1012 var suite = context.describe(title, fn); 1013 mocha.grep(suite.fullTitle()); 1014 return suite; 1015 }; 1016 1017 /** 1018 * Describe a specification or test-case 1019 * with the given `title` and callback `fn` 1020 * acting as a thunk. 1021 */ 1022 1023 context.it = context.specify = function(title, fn){ 1024 var suite = suites[0]; 1025 if (suite.pending) fn = null; 1026 var test = new Test(title, fn); 1027 test.file = file; 1028 suite.addTest(test); 1029 return test; 1030 }; 1031 1032 /** 1033 * Exclusive test-case. 1034 */ 1035 1036 context.it.only = function(title, fn){ 1037 var test = context.it(title, fn); 1038 var reString = '^' + escapeRe(test.fullTitle()) + '$'; 1039 mocha.grep(new RegExp(reString)); 1040 return test; 1041 }; 1042 1043 /** 1044 * Pending test case. 1045 */ 1046 1047 context.xit = 1048 context.xspecify = 1049 context.it.skip = function(title){ 1050 context.it(title); 1051 }; 1052 1053 }); 1054}; 1055 1056}); // module: interfaces/bdd.js 1057 1058require.register("interfaces/common.js", function(module, exports, require){ 1059/** 1060 * Functions common to more than one interface 1061 * @module lib/interfaces/common 1062 */ 1063 1064'use strict'; 1065 1066module.exports = function (suites, context) { 1067 1068 return { 1069 /** 1070 * This is only present if flag --delay is passed into Mocha. It triggers 1071 * root suite execution. Returns a function which runs the root suite. 1072 */ 1073 runWithSuite: function runWithSuite(suite) { 1074 return function run() { 1075 suite.run(); 1076 }; 1077 }, 1078 1079 /** 1080 * Execute before running tests. 1081 */ 1082 before: function (name, fn) { 1083 suites[0].beforeAll(name, fn); 1084 }, 1085 1086 /** 1087 * Execute after running tests. 1088 */ 1089 after: function (name, fn) { 1090 suites[0].afterAll(name, fn); 1091 }, 1092 1093 /** 1094 * Execute before each test case. 1095 */ 1096 beforeEach: function (name, fn) { 1097 suites[0].beforeEach(name, fn); 1098 }, 1099 1100 /** 1101 * Execute after each test case. 1102 */ 1103 afterEach: function (name, fn) { 1104 suites[0].afterEach(name, fn); 1105 }, 1106 1107 test: { 1108 /** 1109 * Pending test case. 1110 */ 1111 skip: function (title) { 1112 context.test(title); 1113 } 1114 } 1115 } 1116}; 1117 1118}); // module: interfaces/common.js 1119 1120require.register("interfaces/exports.js", function(module, exports, require){ 1121/** 1122 * Module dependencies. 1123 */ 1124 1125var Suite = require('../suite') 1126 , Test = require('../test'); 1127 1128/** 1129 * TDD-style interface: 1130 * 1131 * exports.Array = { 1132 * '#indexOf()': { 1133 * 'should return -1 when the value is not present': function(){ 1134 * 1135 * }, 1136 * 1137 * 'should return the correct index when the value is present': function(){ 1138 * 1139 * } 1140 * } 1141 * }; 1142 * 1143 */ 1144 1145module.exports = function(suite){ 1146 var suites = [suite]; 1147 1148 suite.on('require', visit); 1149 1150 function visit(obj, file) { 1151 var suite; 1152 for (var key in obj) { 1153 if ('function' == typeof obj[key]) { 1154 var fn = obj[key]; 1155 switch (key) { 1156 case 'before': 1157 suites[0].beforeAll(fn); 1158 break; 1159 case 'after': 1160 suites[0].afterAll(fn); 1161 break; 1162 case 'beforeEach': 1163 suites[0].beforeEach(fn); 1164 break; 1165 case 'afterEach': 1166 suites[0].afterEach(fn); 1167 break; 1168 default: 1169 var test = new Test(key, fn); 1170 test.file = file; 1171 suites[0].addTest(test); 1172 } 1173 } else { 1174 suite = Suite.create(suites[0], key); 1175 suites.unshift(suite); 1176 visit(obj[key]); 1177 suites.shift(); 1178 } 1179 } 1180 } 1181}; 1182 1183}); // module: interfaces/exports.js 1184 1185require.register("interfaces/index.js", function(module, exports, require){ 1186exports.bdd = require('./bdd'); 1187exports.tdd = require('./tdd'); 1188exports.qunit = require('./qunit'); 1189exports.exports = require('./exports'); 1190 1191}); // module: interfaces/index.js 1192 1193require.register("interfaces/qunit.js", function(module, exports, require){ 1194/** 1195 * Module dependencies. 1196 */ 1197 1198var Suite = require('../suite') 1199 , Test = require('../test') 1200 , escapeRe = require('browser/escape-string-regexp') 1201 , utils = require('../utils'); 1202 1203/** 1204 * QUnit-style interface: 1205 * 1206 * suite('Array'); 1207 * 1208 * test('#length', function(){ 1209 * var arr = [1,2,3]; 1210 * ok(arr.length == 3); 1211 * }); 1212 * 1213 * test('#indexOf()', function(){ 1214 * var arr = [1,2,3]; 1215 * ok(arr.indexOf(1) == 0); 1216 * ok(arr.indexOf(2) == 1); 1217 * ok(arr.indexOf(3) == 2); 1218 * }); 1219 * 1220 * suite('String'); 1221 * 1222 * test('#length', function(){ 1223 * ok('foo'.length == 3); 1224 * }); 1225 * 1226 */ 1227 1228module.exports = function(suite){ 1229 var suites = [suite]; 1230 1231 suite.on('pre-require', function(context, file, mocha){ 1232 1233 var common = require('./common')(suites, context); 1234 1235 context.before = common.before; 1236 context.after = common.after; 1237 context.beforeEach = common.beforeEach; 1238 context.afterEach = common.afterEach; 1239 context.run = mocha.options.delay && common.runWithSuite(suite); 1240 /** 1241 * Describe a "suite" with the given `title`. 1242 */ 1243 1244 context.suite = function(title){ 1245 if (suites.length > 1) suites.shift(); 1246 var suite = Suite.create(suites[0], title); 1247 suite.file = file; 1248 suites.unshift(suite); 1249 return suite; 1250 }; 1251 1252 /** 1253 * Exclusive test-case. 1254 */ 1255 1256 context.suite.only = function(title, fn){ 1257 var suite = context.suite(title, fn); 1258 mocha.grep(suite.fullTitle()); 1259 }; 1260 1261 /** 1262 * Describe a specification or test-case 1263 * with the given `title` and callback `fn` 1264 * acting as a thunk. 1265 */ 1266 1267 context.test = function(title, fn){ 1268 var test = new Test(title, fn); 1269 test.file = file; 1270 suites[0].addTest(test); 1271 return test; 1272 }; 1273 1274 /** 1275 * Exclusive test-case. 1276 */ 1277 1278 context.test.only = function(title, fn){ 1279 var test = context.test(title, fn); 1280 var reString = '^' + escapeRe(test.fullTitle()) + '$'; 1281 mocha.grep(new RegExp(reString)); 1282 }; 1283 1284 context.test.skip = common.test.skip; 1285 1286 }); 1287}; 1288 1289}); // module: interfaces/qunit.js 1290 1291require.register("interfaces/tdd.js", function(module, exports, require){ 1292/** 1293 * Module dependencies. 1294 */ 1295 1296var Suite = require('../suite') 1297 , Test = require('../test') 1298 , escapeRe = require('browser/escape-string-regexp') 1299 , utils = require('../utils'); 1300 1301/** 1302 * TDD-style interface: 1303 * 1304 * suite('Array', function(){ 1305 * suite('#indexOf()', function(){ 1306 * suiteSetup(function(){ 1307 * 1308 * }); 1309 * 1310 * test('should return -1 when not present', function(){ 1311 * 1312 * }); 1313 * 1314 * test('should return the index when present', function(){ 1315 * 1316 * }); 1317 * 1318 * suiteTeardown(function(){ 1319 * 1320 * }); 1321 * }); 1322 * }); 1323 * 1324 */ 1325 1326module.exports = function(suite){ 1327 var suites = [suite]; 1328 1329 suite.on('pre-require', function(context, file, mocha){ 1330 1331 var common = require('./common')(suites, context); 1332 1333 context.setup = common.beforeEach; 1334 context.teardown = common.afterEach; 1335 context.suiteSetup = common.before; 1336 context.suiteTeardown = common.after; 1337 context.run = mocha.options.delay && common.runWithSuite(suite); 1338 /** 1339 * Describe a "suite" with the given `title` 1340 * and callback `fn` containing nested suites 1341 * and/or tests. 1342 */ 1343 1344 context.suite = function(title, fn){ 1345 var suite = Suite.create(suites[0], title); 1346 suite.file = file; 1347 suites.unshift(suite); 1348 fn.call(suite); 1349 suites.shift(); 1350 return suite; 1351 }; 1352 1353 /** 1354 * Pending suite. 1355 */ 1356 context.suite.skip = function(title, fn) { 1357 var suite = Suite.create(suites[0], title); 1358 suite.pending = true; 1359 suites.unshift(suite); 1360 fn.call(suite); 1361 suites.shift(); 1362 }; 1363 1364 /** 1365 * Exclusive test-case. 1366 */ 1367 1368 context.suite.only = function(title, fn){ 1369 var suite = context.suite(title, fn); 1370 mocha.grep(suite.fullTitle()); 1371 }; 1372 1373 /** 1374 * Describe a specification or test-case 1375 * with the given `title` and callback `fn` 1376 * acting as a thunk. 1377 */ 1378 1379 context.test = function(title, fn){ 1380 var suite = suites[0]; 1381 if (suite.pending) fn = null; 1382 var test = new Test(title, fn); 1383 test.file = file; 1384 suite.addTest(test); 1385 return test; 1386 }; 1387 1388 /** 1389 * Exclusive test-case. 1390 */ 1391 1392 context.test.only = function(title, fn){ 1393 var test = context.test(title, fn); 1394 var reString = '^' + escapeRe(test.fullTitle()) + '$'; 1395 mocha.grep(new RegExp(reString)); 1396 }; 1397 1398 context.test.skip = common.test.skip; 1399 }); 1400}; 1401 1402}); // module: interfaces/tdd.js 1403 1404require.register("mocha.js", function(module, exports, require){ 1405/*! 1406 * mocha 1407 * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca> 1408 * MIT Licensed 1409 */ 1410 1411/** 1412 * Module dependencies. 1413 */ 1414 1415var path = require('browser/path') 1416 , escapeRe = require('browser/escape-string-regexp') 1417 , utils = require('./utils'); 1418 1419/** 1420 * Expose `Mocha`. 1421 */ 1422 1423exports = module.exports = Mocha; 1424 1425/** 1426 * To require local UIs and reporters when running in node. 1427 */ 1428 1429if (typeof process !== 'undefined' && typeof process.cwd === 'function') { 1430 var join = path.join 1431 , cwd = process.cwd(); 1432 module.paths.push(cwd, join(cwd, 'node_modules')); 1433} 1434 1435/** 1436 * Expose internals. 1437 */ 1438 1439exports.utils = utils; 1440exports.interfaces = require('./interfaces'); 1441exports.reporters = require('./reporters'); 1442exports.Runnable = require('./runnable'); 1443exports.Context = require('./context'); 1444exports.Runner = require('./runner'); 1445exports.Suite = require('./suite'); 1446exports.Hook = require('./hook'); 1447exports.Test = require('./test'); 1448 1449/** 1450 * Return image `name` path. 1451 * 1452 * @param {String} name 1453 * @return {String} 1454 * @api private 1455 */ 1456 1457function image(name) { 1458 return __dirname + '/../images/' + name + '.png'; 1459} 1460 1461/** 1462 * Setup mocha with `options`. 1463 * 1464 * Options: 1465 * 1466 * - `ui` name "bdd", "tdd", "exports" etc 1467 * - `reporter` reporter instance, defaults to `mocha.reporters.spec` 1468 * - `globals` array of accepted globals 1469 * - `timeout` timeout in milliseconds 1470 * - `bail` bail on the first test failure 1471 * - `slow` milliseconds to wait before considering a test slow 1472 * - `ignoreLeaks` ignore global leaks 1473 * - `fullTrace` display the full stack-trace on failing 1474 * - `grep` string or regexp to filter tests with 1475 * 1476 * @param {Object} options 1477 * @api public 1478 */ 1479 1480function Mocha(options) { 1481 options = options || {}; 1482 this.files = []; 1483 this.options = options; 1484 if (options.grep) this.grep(new RegExp(options.grep)); 1485 if (options.fgrep) this.grep(options.fgrep); 1486 this.suite = new exports.Suite('', new exports.Context); 1487 this.ui(options.ui); 1488 this.bail(options.bail); 1489 this.reporter(options.reporter, options.reporterOptions); 1490 if (null != options.timeout) this.timeout(options.timeout); 1491 this.useColors(options.useColors); 1492 if (options.enableTimeouts !== null) this.enableTimeouts(options.enableTimeouts); 1493 if (options.slow) this.slow(options.slow); 1494 1495 this.suite.on('pre-require', function (context) { 1496 exports.afterEach = context.afterEach || context.teardown; 1497 exports.after = context.after || context.suiteTeardown; 1498 exports.beforeEach = context.beforeEach || context.setup; 1499 exports.before = context.before || context.suiteSetup; 1500 exports.describe = context.describe || context.suite; 1501 exports.it = context.it || context.test; 1502 exports.setup = context.setup || context.beforeEach; 1503 exports.suiteSetup = context.suiteSetup || context.before; 1504 exports.suiteTeardown = context.suiteTeardown || context.after; 1505 exports.suite = context.suite || context.describe; 1506 exports.teardown = context.teardown || context.afterEach; 1507 exports.test = context.test || context.it; 1508 exports.run = context.run; 1509 }); 1510} 1511 1512/** 1513 * Enable or disable bailing on the first failure. 1514 * 1515 * @param {Boolean} [bail] 1516 * @api public 1517 */ 1518 1519Mocha.prototype.bail = function(bail){ 1520 if (0 == arguments.length) bail = true; 1521 this.suite.bail(bail); 1522 return this; 1523}; 1524 1525/** 1526 * Add test `file`. 1527 * 1528 * @param {String} file 1529 * @api public 1530 */ 1531 1532Mocha.prototype.addFile = function(file){ 1533 this.files.push(file); 1534 return this; 1535}; 1536 1537/** 1538 * Set reporter to `reporter`, defaults to "spec". 1539 * 1540 * @param {String|Function} reporter name or constructor 1541 * @param {Object} reporterOptions optional options 1542 * @api public 1543 */ 1544Mocha.prototype.reporter = function(reporter, reporterOptions){ 1545 if ('function' == typeof reporter) { 1546 this._reporter = reporter; 1547 } else { 1548 reporter = reporter || 'spec'; 1549 var _reporter; 1550 try { _reporter = require('./reporters/' + reporter); } catch (err) {} 1551 if (!_reporter) try { _reporter = require(reporter); } catch (err) {} 1552 if (!_reporter && reporter === 'teamcity') 1553 console.warn('The Teamcity reporter was moved to a package named ' + 1554 'mocha-teamcity-reporter ' + 1555 '(https://npmjs.org/package/mocha-teamcity-reporter).'); 1556 if (!_reporter) throw new Error('invalid reporter "' + reporter + '"'); 1557 this._reporter = _reporter; 1558 } 1559 this.options.reporterOptions = reporterOptions; 1560 return this; 1561}; 1562 1563/** 1564 * Set test UI `name`, defaults to "bdd". 1565 * 1566 * @param {String} bdd 1567 * @api public 1568 */ 1569 1570Mocha.prototype.ui = function(name){ 1571 name = name || 'bdd'; 1572 this._ui = exports.interfaces[name]; 1573 if (!this._ui) try { this._ui = require(name); } catch (err) {} 1574 if (!this._ui) throw new Error('invalid interface "' + name + '"'); 1575 this._ui = this._ui(this.suite); 1576 return this; 1577}; 1578 1579/** 1580 * Load registered files. 1581 * 1582 * @api private 1583 */ 1584 1585Mocha.prototype.loadFiles = function(fn){ 1586 var self = this; 1587 var suite = this.suite; 1588 var pending = this.files.length; 1589 this.files.forEach(function(file){ 1590 file = path.resolve(file); 1591 suite.emit('pre-require', global, file, self); 1592 suite.emit('require', require(file), file, self); 1593 suite.emit('post-require', global, file, self); 1594 --pending || (fn && fn()); 1595 }); 1596}; 1597 1598/** 1599 * Enable growl support. 1600 * 1601 * @api private 1602 */ 1603 1604Mocha.prototype._growl = function(runner, reporter) { 1605 var notify = require('growl'); 1606 1607 runner.on('end', function(){ 1608 var stats = reporter.stats; 1609 if (stats.failures) { 1610 var msg = stats.failures + ' of ' + runner.total + ' tests failed'; 1611 notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); 1612 } else { 1613 notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { 1614 name: 'mocha' 1615 , title: 'Passed' 1616 , image: image('ok') 1617 }); 1618 } 1619 }); 1620}; 1621 1622/** 1623 * Add regexp to grep, if `re` is a string it is escaped. 1624 * 1625 * @param {RegExp|String} re 1626 * @return {Mocha} 1627 * @api public 1628 */ 1629 1630Mocha.prototype.grep = function(re){ 1631 this.options.grep = 'string' == typeof re 1632 ? new RegExp(escapeRe(re)) 1633 : re; 1634 return this; 1635}; 1636 1637/** 1638 * Invert `.grep()` matches. 1639 * 1640 * @return {Mocha} 1641 * @api public 1642 */ 1643 1644Mocha.prototype.invert = function(){ 1645 this.options.invert = true; 1646 return this; 1647}; 1648 1649/** 1650 * Ignore global leaks. 1651 * 1652 * @param {Boolean} ignore 1653 * @return {Mocha} 1654 * @api public 1655 */ 1656 1657Mocha.prototype.ignoreLeaks = function(ignore){ 1658 this.options.ignoreLeaks = !!ignore; 1659 return this; 1660}; 1661 1662/** 1663 * Enable global leak checking. 1664 * 1665 * @return {Mocha} 1666 * @api public 1667 */ 1668 1669Mocha.prototype.checkLeaks = function(){ 1670 this.options.ignoreLeaks = false; 1671 return this; 1672}; 1673 1674/** 1675 * Display long stack-trace on failing 1676 * 1677 * @return {Mocha} 1678 * @api public 1679 */ 1680 1681Mocha.prototype.fullTrace = function() { 1682 this.options.fullStackTrace = true; 1683 return this; 1684}; 1685 1686/** 1687 * Enable growl support. 1688 * 1689 * @return {Mocha} 1690 * @api public 1691 */ 1692 1693Mocha.prototype.growl = function(){ 1694 this.options.growl = true; 1695 return this; 1696}; 1697 1698/** 1699 * Ignore `globals` array or string. 1700 * 1701 * @param {Array|String} globals 1702 * @return {Mocha} 1703 * @api public 1704 */ 1705 1706Mocha.prototype.globals = function(globals){ 1707 this.options.globals = (this.options.globals || []).concat(globals); 1708 return this; 1709}; 1710 1711/** 1712 * Emit color output. 1713 * 1714 * @param {Boolean} colors 1715 * @return {Mocha} 1716 * @api public 1717 */ 1718 1719Mocha.prototype.useColors = function(colors){ 1720 if (colors !== undefined) { 1721 this.options.useColors = colors; 1722 } 1723 return this; 1724}; 1725 1726/** 1727 * Use inline diffs rather than +/-. 1728 * 1729 * @param {Boolean} inlineDiffs 1730 * @return {Mocha} 1731 * @api public 1732 */ 1733 1734Mocha.prototype.useInlineDiffs = function(inlineDiffs) { 1735 this.options.useInlineDiffs = arguments.length && inlineDiffs != undefined 1736 ? inlineDiffs 1737 : false; 1738 return this; 1739}; 1740 1741/** 1742 * Set the timeout in milliseconds. 1743 * 1744 * @param {Number} timeout 1745 * @return {Mocha} 1746 * @api public 1747 */ 1748 1749Mocha.prototype.timeout = function(timeout){ 1750 this.suite.timeout(timeout); 1751 return this; 1752}; 1753 1754/** 1755 * Set slowness threshold in milliseconds. 1756 * 1757 * @param {Number} slow 1758 * @return {Mocha} 1759 * @api public 1760 */ 1761 1762Mocha.prototype.slow = function(slow){ 1763 this.suite.slow(slow); 1764 return this; 1765}; 1766 1767/** 1768 * Enable timeouts. 1769 * 1770 * @param {Boolean} enabled 1771 * @return {Mocha} 1772 * @api public 1773 */ 1774 1775Mocha.prototype.enableTimeouts = function(enabled) { 1776 this.suite.enableTimeouts(arguments.length && enabled !== undefined 1777 ? enabled 1778 : true); 1779 return this 1780}; 1781 1782/** 1783 * Makes all tests async (accepting a callback) 1784 * 1785 * @return {Mocha} 1786 * @api public 1787 */ 1788 1789Mocha.prototype.asyncOnly = function(){ 1790 this.options.asyncOnly = true; 1791 return this; 1792}; 1793 1794/** 1795 * Disable syntax highlighting (in browser). 1796 * @returns {Mocha} 1797 * @api public 1798 */ 1799Mocha.prototype.noHighlighting = function() { 1800 this.options.noHighlighting = true; 1801 return this; 1802}; 1803 1804/** 1805 * Delay root suite execution. 1806 * @returns {Mocha} 1807 * @api public 1808 */ 1809Mocha.prototype.delay = function delay() { 1810 this.options.delay = true; 1811 return this; 1812}; 1813 1814/** 1815 * Run tests and invoke `fn()` when complete. 1816 * 1817 * @param {Function} fn 1818 * @return {Runner} 1819 * @api public 1820 */ 1821Mocha.prototype.run = function(fn){ 1822 if (this.files.length) this.loadFiles(); 1823 var suite = this.suite; 1824 var options = this.options; 1825 options.files = this.files; 1826 var runner = new exports.Runner(suite, options.delay); 1827 var reporter = new this._reporter(runner, options); 1828 runner.ignoreLeaks = false !== options.ignoreLeaks; 1829 runner.fullStackTrace = options.fullStackTrace; 1830 runner.asyncOnly = options.asyncOnly; 1831 if (options.grep) runner.grep(options.grep, options.invert); 1832 if (options.globals) runner.globals(options.globals); 1833 if (options.growl) this._growl(runner, reporter); 1834 if (options.useColors !== undefined) { 1835 exports.reporters.Base.useColors = options.useColors; 1836 } 1837 exports.reporters.Base.inlineDiffs = options.useInlineDiffs; 1838 1839 function done(failures) { 1840 if (reporter.done) { 1841 reporter.done(failures, fn); 1842 } else fn && fn(failures); 1843 } 1844 1845 return runner.run(done); 1846}; 1847 1848}); // module: mocha.js 1849 1850require.register("ms.js", function(module, exports, require){ 1851/** 1852 * Helpers. 1853 */ 1854 1855var s = 1000; 1856var m = s * 60; 1857var h = m * 60; 1858var d = h * 24; 1859var y = d * 365.25; 1860 1861/** 1862 * Parse or format the given `val`. 1863 * 1864 * Options: 1865 * 1866 * - `long` verbose formatting [false] 1867 * 1868 * @param {String|Number} val 1869 * @param {Object} options 1870 * @return {String|Number} 1871 * @api public 1872 */ 1873 1874module.exports = function(val, options){ 1875 options = options || {}; 1876 if ('string' == typeof val) return parse(val); 1877 return options['long'] ? longFormat(val) : shortFormat(val); 1878}; 1879 1880/** 1881 * Parse the given `str` and return milliseconds. 1882 * 1883 * @param {String} str 1884 * @return {Number} 1885 * @api private 1886 */ 1887 1888function parse(str) { 1889 var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); 1890 if (!match) return; 1891 var n = parseFloat(match[1]); 1892 var type = (match[2] || 'ms').toLowerCase(); 1893 switch (type) { 1894 case 'years': 1895 case 'year': 1896 case 'y': 1897 return n * y; 1898 case 'days': 1899 case 'day': 1900 case 'd': 1901 return n * d; 1902 case 'hours': 1903 case 'hour': 1904 case 'h': 1905 return n * h; 1906 case 'minutes': 1907 case 'minute': 1908 case 'm': 1909 return n * m; 1910 case 'seconds': 1911 case 'second': 1912 case 's': 1913 return n * s; 1914 case 'ms': 1915 return n; 1916 } 1917} 1918 1919/** 1920 * Short format for `ms`. 1921 * 1922 * @param {Number} ms 1923 * @return {String} 1924 * @api private 1925 */ 1926 1927function shortFormat(ms) { 1928 if (ms >= d) return Math.round(ms / d) + 'd'; 1929 if (ms >= h) return Math.round(ms / h) + 'h'; 1930 if (ms >= m) return Math.round(ms / m) + 'm'; 1931 if (ms >= s) return Math.round(ms / s) + 's'; 1932 return ms + 'ms'; 1933} 1934 1935/** 1936 * Long format for `ms`. 1937 * 1938 * @param {Number} ms 1939 * @return {String} 1940 * @api private 1941 */ 1942 1943function longFormat(ms) { 1944 return plural(ms, d, 'day') 1945 || plural(ms, h, 'hour') 1946 || plural(ms, m, 'minute') 1947 || plural(ms, s, 'second') 1948 || ms + ' ms'; 1949} 1950 1951/** 1952 * Pluralization helper. 1953 */ 1954 1955function plural(ms, n, name) { 1956 if (ms < n) return; 1957 if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; 1958 return Math.ceil(ms / n) + ' ' + name + 's'; 1959} 1960 1961}); // module: ms.js 1962 1963require.register("pending.js", function(module, exports, require){ 1964 1965/** 1966 * Expose `Pending`. 1967 */ 1968 1969module.exports = Pending; 1970 1971/** 1972 * Initialize a new `Pending` error with the given message. 1973 * 1974 * @param {String} message 1975 */ 1976 1977function Pending(message) { 1978 this.message = message; 1979} 1980 1981}); // module: pending.js 1982 1983require.register("reporters/base.js", function(module, exports, require){ 1984/** 1985 * Module dependencies. 1986 */ 1987 1988var tty = require('browser/tty') 1989 , diff = require('browser/diff') 1990 , ms = require('../ms') 1991 , utils = require('../utils') 1992 , supportsColor = process.env ? require('supports-color') : null; 1993 1994/** 1995 * Save timer references to avoid Sinon interfering (see GH-237). 1996 */ 1997 1998var Date = global.Date 1999 , setTimeout = global.setTimeout 2000 , setInterval = global.setInterval 2001 , clearTimeout = global.clearTimeout 2002 , clearInterval = global.clearInterval; 2003 2004/** 2005 * Check if both stdio streams are associated with a tty. 2006 */ 2007 2008var isatty = tty.isatty(1) && tty.isatty(2); 2009 2010/** 2011 * Expose `Base`. 2012 */ 2013 2014exports = module.exports = Base; 2015 2016/** 2017 * Enable coloring by default, except in the browser interface. 2018 */ 2019 2020exports.useColors = process.env 2021 ? (supportsColor || (process.env.MOCHA_COLORS !== undefined)) 2022 : false; 2023 2024/** 2025 * Inline diffs instead of +/- 2026 */ 2027 2028exports.inlineDiffs = false; 2029 2030/** 2031 * Default color map. 2032 */ 2033 2034exports.colors = { 2035 'pass': 90 2036 , 'fail': 31 2037 , 'bright pass': 92 2038 , 'bright fail': 91 2039 , 'bright yellow': 93 2040 , 'pending': 36 2041 , 'suite': 0 2042 , 'error title': 0 2043 , 'error message': 31 2044 , 'error stack': 90 2045 , 'checkmark': 32 2046 , 'fast': 90 2047 , 'medium': 33 2048 , 'slow': 31 2049 , 'green': 32 2050 , 'light': 90 2051 , 'diff gutter': 90 2052 , 'diff added': 42 2053 , 'diff removed': 41 2054}; 2055 2056/** 2057 * Default symbol map. 2058 */ 2059 2060exports.symbols = { 2061 ok: '✓', 2062 err: '✖', 2063 dot: '․' 2064}; 2065 2066// With node.js on Windows: use symbols available in terminal default fonts 2067if ('win32' == process.platform) { 2068 exports.symbols.ok = '\u221A'; 2069 exports.symbols.err = '\u00D7'; 2070 exports.symbols.dot = '.'; 2071} 2072 2073/** 2074 * Color `str` with the given `type`, 2075 * allowing colors to be disabled, 2076 * as well as user-defined color 2077 * schemes. 2078 * 2079 * @param {String} type 2080 * @param {String} str 2081 * @return {String} 2082 * @api private 2083 */ 2084 2085var color = exports.color = function(type, str) { 2086 if (!exports.useColors) return String(str); 2087 return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; 2088}; 2089 2090/** 2091 * Expose term window size, with some 2092 * defaults for when stderr is not a tty. 2093 */ 2094 2095exports.window = { 2096 width: isatty 2097 ? process.stdout.getWindowSize 2098 ? process.stdout.getWindowSize(1)[0] 2099 : tty.getWindowSize()[1] 2100 : 75 2101}; 2102 2103/** 2104 * Expose some basic cursor interactions 2105 * that are common among reporters. 2106 */ 2107 2108exports.cursor = { 2109 hide: function(){ 2110 isatty && process.stdout.write('\u001b[?25l'); 2111 }, 2112 2113 show: function(){ 2114 isatty && process.stdout.write('\u001b[?25h'); 2115 }, 2116 2117 deleteLine: function(){ 2118 isatty && process.stdout.write('\u001b[2K'); 2119 }, 2120 2121 beginningOfLine: function(){ 2122 isatty && process.stdout.write('\u001b[0G'); 2123 }, 2124 2125 CR: function(){ 2126 if (isatty) { 2127 exports.cursor.deleteLine(); 2128 exports.cursor.beginningOfLine(); 2129 } else { 2130 process.stdout.write('\r'); 2131 } 2132 } 2133}; 2134 2135/** 2136 * Outut the given `failures` as a list. 2137 * 2138 * @param {Array} failures 2139 * @api public 2140 */ 2141 2142exports.list = function(failures){ 2143 console.log(); 2144 failures.forEach(function(test, i){ 2145 // format 2146 var fmt = color('error title', ' %s) %s:\n') 2147 + color('error message', ' %s') 2148 + color('error stack', '\n%s\n'); 2149 2150 // msg 2151 var err = test.err 2152 , message = err.message || '' 2153 , stack = err.stack || message 2154 , index = stack.indexOf(message) + message.length 2155 , msg = stack.slice(0, index) 2156 , actual = err.actual 2157 , expected = err.expected 2158 , escape = true; 2159 2160 // uncaught 2161 if (err.uncaught) { 2162 msg = 'Uncaught ' + msg; 2163 } 2164 // explicitly show diff 2165 if (err.showDiff && sameType(actual, expected)) { 2166 2167 if ('string' !== typeof actual) { 2168 escape = false; 2169 err.actual = actual = utils.stringify(actual); 2170 err.expected = expected = utils.stringify(expected); 2171 } 2172 2173 fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n'); 2174 var match = message.match(/^([^:]+): expected/); 2175 msg = '\n ' + color('error message', match ? match[1] : msg); 2176 2177 if (exports.inlineDiffs) { 2178 msg += inlineDiff(err, escape); 2179 } else { 2180 msg += unifiedDiff(err, escape); 2181 } 2182 } 2183 2184 // indent stack trace without msg 2185 stack = stack.slice(index ? index + 1 : index) 2186 .replace(/^/gm, ' '); 2187 2188 console.log(fmt, (i + 1), test.fullTitle(), msg, stack); 2189 }); 2190}; 2191 2192/** 2193 * Initialize a new `Base` reporter. 2194 * 2195 * All other reporters generally 2196 * inherit from this reporter, providing 2197 * stats such as test duration, number 2198 * of tests passed / failed etc. 2199 * 2200 * @param {Runner} runner 2201 * @api public 2202 */ 2203 2204function Base(runner) { 2205 var self = this 2206 , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } 2207 , failures = this.failures = []; 2208 2209 if (!runner) return; 2210 this.runner = runner; 2211 2212 runner.stats = stats; 2213 2214 runner.on('start', function(){ 2215 stats.start = new Date; 2216 }); 2217 2218 runner.on('suite', function(suite){ 2219 stats.suites = stats.suites || 0; 2220 suite.root || stats.suites++; 2221 }); 2222 2223 runner.on('test end', function(test){ 2224 stats.tests = stats.tests || 0; 2225 stats.tests++; 2226 }); 2227 2228 runner.on('pass', function(test){ 2229 stats.passes = stats.passes || 0; 2230 2231 var medium = test.slow() / 2; 2232 test.speed = test.duration > test.slow() 2233 ? 'slow' 2234 : test.duration > medium 2235 ? 'medium' 2236 : 'fast'; 2237 2238 stats.passes++; 2239 }); 2240 2241 runner.on('fail', function(test, err){ 2242 stats.failures = stats.failures || 0; 2243 stats.failures++; 2244 test.err = err; 2245 failures.push(test); 2246 }); 2247 2248 runner.on('end', function(){ 2249 stats.end = new Date; 2250 stats.duration = new Date - stats.start; 2251 }); 2252 2253 runner.on('pending', function(){ 2254 stats.pending++; 2255 }); 2256} 2257 2258/** 2259 * Output common epilogue used by many of 2260 * the bundled reporters. 2261 * 2262 * @api public 2263 */ 2264 2265Base.prototype.epilogue = function(){ 2266 var stats = this.stats; 2267 var tests; 2268 var fmt; 2269 2270 console.log(); 2271 2272 // passes 2273 fmt = color('bright pass', ' ') 2274 + color('green', ' %d passing') 2275 + color('light', ' (%s)'); 2276 2277 console.log(fmt, 2278 stats.passes || 0, 2279 ms(stats.duration)); 2280 2281 // pending 2282 if (stats.pending) { 2283 fmt = color('pending', ' ') 2284 + color('pending', ' %d pending'); 2285 2286 console.log(fmt, stats.pending); 2287 } 2288 2289 // failures 2290 if (stats.failures) { 2291 fmt = color('fail', ' %d failing'); 2292 2293 console.log(fmt, stats.failures); 2294 2295 Base.list(this.failures); 2296 console.log(); 2297 } 2298 2299 console.log(); 2300}; 2301 2302/** 2303 * Pad the given `str` to `len`. 2304 * 2305 * @param {String} str 2306 * @param {String} len 2307 * @return {String} 2308 * @api private 2309 */ 2310 2311function pad(str, len) { 2312 str = String(str); 2313 return Array(len - str.length + 1).join(' ') + str; 2314} 2315 2316 2317/** 2318 * Returns an inline diff between 2 strings with coloured ANSI output 2319 * 2320 * @param {Error} Error with actual/expected 2321 * @return {String} Diff 2322 * @api private 2323 */ 2324 2325function inlineDiff(err, escape) { 2326 var msg = errorDiff(err, 'WordsWithSpace', escape); 2327 2328 // linenos 2329 var lines = msg.split('\n'); 2330 if (lines.length > 4) { 2331 var width = String(lines.length).length; 2332 msg = lines.map(function(str, i){ 2333 return pad(++i, width) + ' |' + ' ' + str; 2334 }).join('\n'); 2335 } 2336 2337 // legend 2338 msg = '\n' 2339 + color('diff removed', 'actual') 2340 + ' ' 2341 + color('diff added', 'expected') 2342 + '\n\n' 2343 + msg 2344 + '\n'; 2345 2346 // indent 2347 msg = msg.replace(/^/gm, ' '); 2348 return msg; 2349} 2350 2351/** 2352 * Returns a unified diff between 2 strings 2353 * 2354 * @param {Error} Error with actual/expected 2355 * @return {String} Diff 2356 * @api private 2357 */ 2358 2359function unifiedDiff(err, escape) { 2360 var indent = ' '; 2361 function cleanUp(line) { 2362 if (escape) { 2363 line = escapeInvisibles(line); 2364 } 2365 if (line[0] === '+') return indent + colorLines('diff added', line); 2366 if (line[0] === '-') return indent + colorLines('diff removed', line); 2367 if (line.match(/\@\@/)) return null; 2368 if (line.match(/\\ No newline/)) return null; 2369 else return indent + line; 2370 } 2371 function notBlank(line) { 2372 return line != null; 2373 } 2374 var msg = diff.createPatch('string', err.actual, err.expected); 2375 var lines = msg.split('\n').splice(4); 2376 return '\n ' 2377 + colorLines('diff added', '+ expected') + ' ' 2378 + colorLines('diff removed', '- actual') 2379 + '\n\n' 2380 + lines.map(cleanUp).filter(notBlank).join('\n'); 2381} 2382 2383/** 2384 * Return a character diff for `err`. 2385 * 2386 * @param {Error} err 2387 * @return {String} 2388 * @api private 2389 */ 2390 2391function errorDiff(err, type, escape) { 2392 var actual = escape ? escapeInvisibles(err.actual) : err.actual; 2393 var expected = escape ? escapeInvisibles(err.expected) : err.expected; 2394 return diff['diff' + type](actual, expected).map(function(str){ 2395 if (str.added) return colorLines('diff added', str.value); 2396 if (str.removed) return colorLines('diff removed', str.value); 2397 return str.value; 2398 }).join(''); 2399} 2400 2401/** 2402 * Returns a string with all invisible characters in plain text 2403 * 2404 * @param {String} line 2405 * @return {String} 2406 * @api private 2407 */ 2408function escapeInvisibles(line) { 2409 return line.replace(/\t/g, '<tab>') 2410 .replace(/\r/g, '<CR>') 2411 .replace(/\n/g, '<LF>\n'); 2412} 2413 2414/** 2415 * Color lines for `str`, using the color `name`. 2416 * 2417 * @param {String} name 2418 * @param {String} str 2419 * @return {String} 2420 * @api private 2421 */ 2422 2423function colorLines(name, str) { 2424 return str.split('\n').map(function(str){ 2425 return color(name, str); 2426 }).join('\n'); 2427} 2428 2429/** 2430 * Check that a / b have the same type. 2431 * 2432 * @param {Object} a 2433 * @param {Object} b 2434 * @return {Boolean} 2435 * @api private 2436 */ 2437 2438function sameType(a, b) { 2439 a = Object.prototype.toString.call(a); 2440 b = Object.prototype.toString.call(b); 2441 return a == b; 2442} 2443 2444}); // module: reporters/base.js 2445 2446require.register("reporters/doc.js", function(module, exports, require){ 2447/** 2448 * Module dependencies. 2449 */ 2450 2451var Base = require('./base') 2452 , utils = require('../utils'); 2453 2454/** 2455 * Expose `Doc`. 2456 */ 2457 2458exports = module.exports = Doc; 2459 2460/** 2461 * Initialize a new `Doc` reporter. 2462 * 2463 * @param {Runner} runner 2464 * @api public 2465 */ 2466 2467function Doc(runner) { 2468 Base.call(this, runner); 2469 2470 var self = this 2471 , stats = this.stats 2472 , total = runner.total 2473 , indents = 2; 2474 2475 function indent() { 2476 return Array(indents).join(' '); 2477 } 2478 2479 runner.on('suite', function(suite){ 2480 if (suite.root) return; 2481 ++indents; 2482 console.log('%s<section class="suite">', indent()); 2483 ++indents; 2484 console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title)); 2485 console.log('%s<dl>', indent()); 2486 }); 2487 2488 runner.on('suite end', function(suite){ 2489 if (suite.root) return; 2490 console.log('%s</dl>', indent()); 2491 --indents; 2492 console.log('%s</section>', indent()); 2493 --indents; 2494 }); 2495 2496 runner.on('pass', function(test){ 2497 console.log('%s <dt>%s</dt>', indent(), utils.escape(test.title)); 2498 var code = utils.escape(utils.clean(test.fn.toString())); 2499 console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code); 2500 }); 2501 2502 runner.on('fail', function(test, err){ 2503 console.log('%s <dt class="error">%s</dt>', indent(), utils.escape(test.title)); 2504 var code = utils.escape(utils.clean(test.fn.toString())); 2505 console.log('%s <dd class="error"><pre><code>%s</code></pre></dd>', indent(), code); 2506 console.log('%s <dd class="error">%s</dd>', indent(), utils.escape(err)); 2507 }); 2508} 2509 2510}); // module: reporters/doc.js 2511 2512require.register("reporters/dot.js", function(module, exports, require){ 2513/** 2514 * Module dependencies. 2515 */ 2516 2517var Base = require('./base') 2518 , color = Base.color; 2519 2520/** 2521 * Expose `Dot`. 2522 */ 2523 2524exports = module.exports = Dot; 2525 2526/** 2527 * Initialize a new `Dot` matrix test reporter. 2528 * 2529 * @param {Runner} runner 2530 * @api public 2531 */ 2532 2533function Dot(runner) { 2534 Base.call(this, runner); 2535 2536 var self = this 2537 , stats = this.stats 2538 , width = Base.window.width * .75 | 0 2539 , n = -1; 2540 2541 runner.on('start', function(){ 2542 process.stdout.write('\n '); 2543 }); 2544 2545 runner.on('pending', function(test){ 2546 if (++n % width == 0) process.stdout.write('\n '); 2547 process.stdout.write(color('pending', Base.symbols.dot)); 2548 }); 2549 2550 runner.on('pass', function(test){ 2551 if (++n % width == 0) process.stdout.write('\n '); 2552 if ('slow' == test.speed) { 2553 process.stdout.write(color('bright yellow', Base.symbols.dot)); 2554 } else { 2555 process.stdout.write(color(test.speed, Base.symbols.dot)); 2556 } 2557 }); 2558 2559 runner.on('fail', function(test, err){ 2560 if (++n % width == 0) process.stdout.write('\n '); 2561 process.stdout.write(color('fail', Base.symbols.dot)); 2562 }); 2563 2564 runner.on('end', function(){ 2565 console.log(); 2566 self.epilogue(); 2567 }); 2568} 2569 2570/** 2571 * Inherit from `Base.prototype`. 2572 */ 2573 2574function F(){}; 2575F.prototype = Base.prototype; 2576Dot.prototype = new F; 2577Dot.prototype.constructor = Dot; 2578 2579 2580}); // module: reporters/dot.js 2581 2582require.register("reporters/html-cov.js", function(module, exports, require){ 2583/** 2584 * Module dependencies. 2585 */ 2586 2587var JSONCov = require('./json-cov') 2588 , fs = require('browser/fs'); 2589 2590/** 2591 * Expose `HTMLCov`. 2592 */ 2593 2594exports = module.exports = HTMLCov; 2595 2596/** 2597 * Initialize a new `JsCoverage` reporter. 2598 * 2599 * @param {Runner} runner 2600 * @api public 2601 */ 2602 2603function HTMLCov(runner) { 2604 var jade = require('jade') 2605 , file = __dirname + '/templates/coverage.jade' 2606 , str = fs.readFileSync(file, 'utf8') 2607 , fn = jade.compile(str, { filename: file }) 2608 , self = this; 2609 2610 JSONCov.call(this, runner, false); 2611 2612 runner.on('end', function(){ 2613 process.stdout.write(fn({ 2614 cov: self.cov 2615 , coverageClass: coverageClass 2616 })); 2617 }); 2618} 2619 2620/** 2621 * Return coverage class for `n`. 2622 * 2623 * @return {String} 2624 * @api private 2625 */ 2626 2627function coverageClass(n) { 2628 if (n >= 75) return 'high'; 2629 if (n >= 50) return 'medium'; 2630 if (n >= 25) return 'low'; 2631 return 'terrible'; 2632} 2633 2634}); // module: reporters/html-cov.js 2635 2636require.register("reporters/html.js", function(module, exports, require){ 2637/** 2638 * Module dependencies. 2639 */ 2640 2641var Base = require('./base') 2642 , utils = require('../utils') 2643 , Progress = require('../browser/progress') 2644 , escape = utils.escape; 2645 2646/** 2647 * Save timer references to avoid Sinon interfering (see GH-237). 2648 */ 2649 2650var Date = global.Date 2651 , setTimeout = global.setTimeout 2652 , setInterval = global.setInterval 2653 , clearTimeout = global.clearTimeout 2654 , clearInterval = global.clearInterval; 2655 2656/** 2657 * Expose `HTML`. 2658 */ 2659 2660exports = module.exports = HTML; 2661 2662/** 2663 * Stats template. 2664 */ 2665 2666var statsTemplate = '<ul id="mocha-stats">' 2667 + '<li class="progress"><canvas width="40" height="40"></canvas></li>' 2668 + '<li class="passes"><a href="#">passes:</a> <em>0</em></li>' 2669 + '<li class="failures"><a href="#">failures:</a> <em>0</em></li>' 2670 + '<li class="duration">duration: <em>0</em>s</li>' 2671 + '</ul>'; 2672 2673/** 2674 * Initialize a new `HTML` reporter. 2675 * 2676 * @param {Runner} runner 2677 * @api public 2678 */ 2679 2680function HTML(runner) { 2681 Base.call(this, runner); 2682 2683 var self = this 2684 , stats = this.stats 2685 , total = runner.total 2686 , stat = fragment(statsTemplate) 2687 , items = stat.getElementsByTagName('li') 2688 , passes = items[1].getElementsByTagName('em')[0] 2689 , passesLink = items[1].getElementsByTagName('a')[0] 2690 , failures = items[2].getElementsByTagName('em')[0] 2691 , failuresLink = items[2].getElementsByTagName('a')[0] 2692 , duration = items[3].getElementsByTagName('em')[0] 2693 , canvas = stat.getElementsByTagName('canvas')[0] 2694 , report = fragment('<ul id="mocha-report"></ul>') 2695 , stack = [report] 2696 , progress 2697 , ctx 2698 , root = document.getElementById('mocha'); 2699 2700 if (canvas.getContext) { 2701 var ratio = window.devicePixelRatio || 1; 2702 canvas.style.width = canvas.width; 2703 canvas.style.height = canvas.height; 2704 canvas.width *= ratio; 2705 canvas.height *= ratio; 2706 ctx = canvas.getContext('2d'); 2707 ctx.scale(ratio, ratio); 2708 progress = new Progress; 2709 } 2710 2711 if (!root) return error('#mocha div missing, add it to your document'); 2712 2713 // pass toggle 2714 on(passesLink, 'click', function(){ 2715 unhide(); 2716 var name = /pass/.test(report.className) ? '' : ' pass'; 2717 report.className = report.className.replace(/fail|pass/g, '') + name; 2718 if (report.className.trim()) hideSuitesWithout('test pass'); 2719 }); 2720 2721 // failure toggle 2722 on(failuresLink, 'click', function(){ 2723 unhide(); 2724 var name = /fail/.test(report.className) ? '' : ' fail'; 2725 report.className = report.className.replace(/fail|pass/g, '') + name; 2726 if (report.className.trim()) hideSuitesWithout('test fail'); 2727 }); 2728 2729 root.appendChild(stat); 2730 root.appendChild(report); 2731 2732 if (progress) progress.size(40); 2733 2734 runner.on('suite', function(suite){ 2735 if (suite.root) return; 2736 2737 // suite 2738 var url = self.suiteURL(suite); 2739 var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title)); 2740 2741 // container 2742 stack[0].appendChild(el); 2743 stack.unshift(document.createElement('ul')); 2744 el.appendChild(stack[0]); 2745 }); 2746 2747 runner.on('suite end', function(suite){ 2748 if (suite.root) return; 2749 stack.shift(); 2750 }); 2751 2752 runner.on('fail', function(test, err){ 2753 if ('hook' == test.type) runner.emit('test end', test); 2754 }); 2755 2756 runner.on('test end', function(test){ 2757 // TODO: add to stats 2758 var percent = stats.tests / this.total * 100 | 0; 2759 if (progress) progress.update(percent).draw(ctx); 2760 2761 // update stats 2762 var ms = new Date - stats.start; 2763 text(passes, stats.passes); 2764 text(failures, stats.failures); 2765 text(duration, (ms / 1000).toFixed(2)); 2766 2767 // test 2768 if ('passed' == test.state) { 2769 var url = self.testURL(test); 2770 var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="%s" class="replay">‣</a></h2></li>', test.speed, test.title, test.duration, url); 2771 } else if (test.pending) { 2772 var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title); 2773 } else { 2774 var el = fragment('<li class="test fail"><h2>%e <a href="%e" class="replay">‣</a></h2></li>', test.title, self.testURL(test)); 2775 var str = test.err.stack || test.err.toString(); 2776 2777 // FF / Opera do not add the message 2778 if (!~str.indexOf(test.err.message)) { 2779 str = test.err.message + '\n' + str; 2780 } 2781 2782 // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we 2783 // check for the result of the stringifying. 2784 if ('[object Error]' == str) str = test.err.message; 2785 2786 // Safari doesn't give you a stack. Let's at least provide a source line. 2787 if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { 2788 str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; 2789 } 2790 2791 el.appendChild(fragment('<pre class="error">%e</pre>', str)); 2792 } 2793 2794 // toggle code 2795 // TODO: defer 2796 if (!test.pending) { 2797 var h2 = el.getElementsByTagName('h2')[0]; 2798 2799 on(h2, 'click', function(){ 2800 pre.style.display = 'none' == pre.style.display 2801 ? 'block' 2802 : 'none'; 2803 }); 2804 2805 var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString())); 2806 el.appendChild(pre); 2807 pre.style.display = 'none'; 2808 } 2809 2810 // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack. 2811 if (stack[0]) stack[0].appendChild(el); 2812 }); 2813} 2814 2815/** 2816 * Makes a URL, preserving querystring ("search") parameters. 2817 * @param {string} s 2818 * @returns {string} your new URL 2819 */ 2820var makeUrl = function makeUrl(s) { 2821 var search = window.location.search; 2822 2823 // Remove previous grep query parameter if present 2824 if (search) { 2825 search = search.replace(/[?&]grep=[^&\s]*/g, '').replace(/^&/, '?'); 2826 } 2827 2828 return window.location.pathname + (search ? search + '&' : '?' ) + 'grep=' + encodeURIComponent(s); 2829}; 2830 2831/** 2832 * Provide suite URL 2833 * 2834 * @param {Object} [suite] 2835 */ 2836HTML.prototype.suiteURL = function(suite){ 2837 return makeUrl(suite.fullTitle()); 2838}; 2839 2840/** 2841 * Provide test URL 2842 * 2843 * @param {Object} [test] 2844 */ 2845 2846HTML.prototype.testURL = function(test){ 2847 return makeUrl(test.fullTitle()); 2848}; 2849 2850/** 2851 * Display error `msg`. 2852 */ 2853 2854function error(msg) { 2855 document.body.appendChild(fragment('<div id="mocha-error">%s</div>', msg)); 2856} 2857 2858/** 2859 * Return a DOM fragment from `html`. 2860 */ 2861 2862function fragment(html) { 2863 var args = arguments 2864 , div = document.createElement('div') 2865 , i = 1; 2866 2867 div.innerHTML = html.replace(/%([se])/g, function(_, type){ 2868 switch (type) { 2869 case 's': return String(args[i++]); 2870 case 'e': return escape(args[i++]); 2871 } 2872 }); 2873 2874 return div.firstChild; 2875} 2876 2877/** 2878 * Check for suites that do not have elements 2879 * with `classname`, and hide them. 2880 */ 2881 2882function hideSuitesWithout(classname) { 2883 var suites = document.getElementsByClassName('suite'); 2884 for (var i = 0; i < suites.length; i++) { 2885 var els = suites[i].getElementsByClassName(classname); 2886 if (0 == els.length) suites[i].className += ' hidden'; 2887 } 2888} 2889 2890/** 2891 * Unhide .hidden suites. 2892 */ 2893 2894function unhide() { 2895 var els = document.getElementsByClassName('suite hidden'); 2896 for (var i = 0; i < els.length; ++i) { 2897 els[i].className = els[i].className.replace('suite hidden', 'suite'); 2898 } 2899} 2900 2901/** 2902 * Set `el` text to `str`. 2903 */ 2904 2905function text(el, str) { 2906 if (el.textContent) { 2907 el.textContent = str; 2908 } else { 2909 el.innerText = str; 2910 } 2911} 2912 2913/** 2914 * Listen on `event` with callback `fn`. 2915 */ 2916 2917function on(el, event, fn) { 2918 if (el.addEventListener) { 2919 el.addEventListener(event, fn, false); 2920 } else { 2921 el.attachEvent('on' + event, fn); 2922 } 2923} 2924 2925}); // module: reporters/html.js 2926 2927require.register("reporters/index.js", function(module, exports, require){ 2928exports.Base = require('./base'); 2929exports.Dot = require('./dot'); 2930exports.Doc = require('./doc'); 2931exports.TAP = require('./tap'); 2932exports.JSON = require('./json'); 2933exports.HTML = require('./html'); 2934exports.List = require('./list'); 2935exports.Min = require('./min'); 2936exports.Spec = require('./spec'); 2937exports.Nyan = require('./nyan'); 2938exports.XUnit = require('./xunit'); 2939exports.Markdown = require('./markdown'); 2940exports.Progress = require('./progress'); 2941exports.Landing = require('./landing'); 2942exports.JSONCov = require('./json-cov'); 2943exports.HTMLCov = require('./html-cov'); 2944exports.JSONStream = require('./json-stream'); 2945 2946}); // module: reporters/index.js 2947 2948require.register("reporters/json-cov.js", function(module, exports, require){ 2949/** 2950 * Module dependencies. 2951 */ 2952 2953var Base = require('./base'); 2954 2955/** 2956 * Expose `JSONCov`. 2957 */ 2958 2959exports = module.exports = JSONCov; 2960 2961/** 2962 * Initialize a new `JsCoverage` reporter. 2963 * 2964 * @param {Runner} runner 2965 * @param {Boolean} output 2966 * @api public 2967 */ 2968 2969function JSONCov(runner, output) { 2970 var self = this 2971 , output = 1 == arguments.length ? true : output; 2972 2973 Base.call(this, runner); 2974 2975 var tests = [] 2976 , failures = [] 2977 , passes = []; 2978 2979 runner.on('test end', function(test){ 2980 tests.push(test); 2981 }); 2982 2983 runner.on('pass', function(test){ 2984 passes.push(test); 2985 }); 2986 2987 runner.on('fail', function(test){ 2988 failures.push(test); 2989 }); 2990 2991 runner.on('end', function(){ 2992 var cov = global._$jscoverage || {}; 2993 var result = self.cov = map(cov); 2994 result.stats = self.stats; 2995 result.tests = tests.map(clean); 2996 result.failures = failures.map(clean); 2997 result.passes = passes.map(clean); 2998 if (!output) return; 2999 process.stdout.write(JSON.stringify(result, null, 2 )); 3000 }); 3001} 3002 3003/** 3004 * Map jscoverage data to a JSON structure 3005 * suitable for reporting. 3006 * 3007 * @param {Object} cov 3008 * @return {Object} 3009 * @api private 3010 */ 3011 3012function map(cov) { 3013 var ret = { 3014 instrumentation: 'node-jscoverage' 3015 , sloc: 0 3016 , hits: 0 3017 , misses: 0 3018 , coverage: 0 3019 , files: [] 3020 }; 3021 3022 for (var filename in cov) { 3023 var data = coverage(filename, cov[filename]); 3024 ret.files.push(data); 3025 ret.hits += data.hits; 3026 ret.misses += data.misses; 3027 ret.sloc += data.sloc; 3028 } 3029 3030 ret.files.sort(function(a, b) { 3031 return a.filename.localeCompare(b.filename); 3032 }); 3033 3034 if (ret.sloc > 0) { 3035 ret.coverage = (ret.hits / ret.sloc) * 100; 3036 } 3037 3038 return ret; 3039} 3040 3041/** 3042 * Map jscoverage data for a single source file 3043 * to a JSON structure suitable for reporting. 3044 * 3045 * @param {String} filename name of the source file 3046 * @param {Object} data jscoverage coverage data 3047 * @return {Object} 3048 * @api private 3049 */ 3050 3051function coverage(filename, data) { 3052 var ret = { 3053 filename: filename, 3054 coverage: 0, 3055 hits: 0, 3056 misses: 0, 3057 sloc: 0, 3058 source: {} 3059 }; 3060 3061 data.source.forEach(function(line, num){ 3062 num++; 3063 3064 if (data[num] === 0) { 3065 ret.misses++; 3066 ret.sloc++; 3067 } else if (data[num] !== undefined) { 3068 ret.hits++; 3069 ret.sloc++; 3070 } 3071 3072 ret.source[num] = { 3073 source: line 3074 , coverage: data[num] === undefined 3075 ? '' 3076 : data[num] 3077 }; 3078 }); 3079 3080 ret.coverage = ret.hits / ret.sloc * 100; 3081 3082 return ret; 3083} 3084 3085/** 3086 * Return a plain-object representation of `test` 3087 * free of cyclic properties etc. 3088 * 3089 * @param {Object} test 3090 * @return {Object} 3091 * @api private 3092 */ 3093 3094function clean(test) { 3095 return { 3096 title: test.title 3097 , fullTitle: test.fullTitle() 3098 , duration: test.duration 3099 } 3100} 3101 3102}); // module: reporters/json-cov.js 3103 3104require.register("reporters/json-stream.js", function(module, exports, require){ 3105/** 3106 * Module dependencies. 3107 */ 3108 3109var Base = require('./base') 3110 , color = Base.color; 3111 3112/** 3113 * Expose `List`. 3114 */ 3115 3116exports = module.exports = List; 3117 3118/** 3119 * Initialize a new `List` test reporter. 3120 * 3121 * @param {Runner} runner 3122 * @api public 3123 */ 3124 3125function List(runner) { 3126 Base.call(this, runner); 3127 3128 var self = this 3129 , stats = this.stats 3130 , total = runner.total; 3131 3132 runner.on('start', function(){ 3133 console.log(JSON.stringify(['start', { total: total }])); 3134 }); 3135 3136 runner.on('pass', function(test){ 3137 console.log(JSON.stringify(['pass', clean(test)])); 3138 }); 3139 3140 runner.on('fail', function(test, err){ 3141 test = clean(test); 3142 test.err = err.message; 3143 console.log(JSON.stringify(['fail', test])); 3144 }); 3145 3146 runner.on('end', function(){ 3147 process.stdout.write(JSON.stringify(['end', self.stats])); 3148 }); 3149} 3150 3151/** 3152 * Return a plain-object representation of `test` 3153 * free of cyclic properties etc. 3154 * 3155 * @param {Object} test 3156 * @return {Object} 3157 * @api private 3158 */ 3159 3160function clean(test) { 3161 return { 3162 title: test.title 3163 , fullTitle: test.fullTitle() 3164 , duration: test.duration 3165 } 3166} 3167 3168}); // module: reporters/json-stream.js 3169 3170require.register("reporters/json.js", function(module, exports, require){ 3171/** 3172 * Module dependencies. 3173 */ 3174 3175var Base = require('./base') 3176 , cursor = Base.cursor 3177 , color = Base.color; 3178 3179/** 3180 * Expose `JSON`. 3181 */ 3182 3183exports = module.exports = JSONReporter; 3184 3185/** 3186 * Initialize a new `JSON` reporter. 3187 * 3188 * @param {Runner} runner 3189 * @api public 3190 */ 3191 3192function JSONReporter(runner) { 3193 var self = this; 3194 Base.call(this, runner); 3195 3196 var tests = [] 3197 , pending = [] 3198 , failures = [] 3199 , passes = []; 3200 3201 runner.on('test end', function(test){ 3202 tests.push(test); 3203 }); 3204 3205 runner.on('pass', function(test){ 3206 passes.push(test); 3207 }); 3208 3209 runner.on('fail', function(test){ 3210 failures.push(test); 3211 }); 3212 3213 runner.on('pending', function(test){ 3214 pending.push(test); 3215 }); 3216 3217 runner.on('end', function(){ 3218 var obj = { 3219 stats: self.stats, 3220 tests: tests.map(clean), 3221 pending: pending.map(clean), 3222 failures: failures.map(clean), 3223 passes: passes.map(clean) 3224 }; 3225 3226 runner.testResults = obj; 3227 3228 process.stdout.write(JSON.stringify(obj, null, 2)); 3229 }); 3230} 3231 3232/** 3233 * Return a plain-object representation of `test` 3234 * free of cyclic properties etc. 3235 * 3236 * @param {Object} test 3237 * @return {Object} 3238 * @api private 3239 */ 3240 3241function clean(test) { 3242 return { 3243 title: test.title, 3244 fullTitle: test.fullTitle(), 3245 duration: test.duration, 3246 err: errorJSON(test.err || {}) 3247 } 3248} 3249 3250/** 3251 * Transform `error` into a JSON object. 3252 * @param {Error} err 3253 * @return {Object} 3254 */ 3255 3256function errorJSON(err) { 3257 var res = {}; 3258 Object.getOwnPropertyNames(err).forEach(function(key) { 3259 res[key] = err[key]; 3260 }, err); 3261 return res; 3262} 3263 3264}); // module: reporters/json.js 3265 3266require.register("reporters/landing.js", function(module, exports, require){ 3267/** 3268 * Module dependencies. 3269 */ 3270 3271var Base = require('./base') 3272 , cursor = Base.cursor 3273 , color = Base.color; 3274 3275/** 3276 * Expose `Landing`. 3277 */ 3278 3279exports = module.exports = Landing; 3280 3281/** 3282 * Airplane color. 3283 */ 3284 3285Base.colors.plane = 0; 3286 3287/** 3288 * Airplane crash color. 3289 */ 3290 3291Base.colors['plane crash'] = 31; 3292 3293/** 3294 * Runway color. 3295 */ 3296 3297Base.colors.runway = 90; 3298 3299/** 3300 * Initialize a new `Landing` reporter. 3301 * 3302 * @param {Runner} runner 3303 * @api public 3304 */ 3305 3306function Landing(runner) { 3307 Base.call(this, runner); 3308 3309 var self = this 3310 , stats = this.stats 3311 , width = Base.window.width * .75 | 0 3312 , total = runner.total 3313 , stream = process.stdout 3314 , plane = color('plane', '✈') 3315 , crashed = -1 3316 , n = 0; 3317 3318 function runway() { 3319 var buf = Array(width).join('-'); 3320 return ' ' + color('runway', buf); 3321 } 3322 3323 runner.on('start', function(){ 3324 stream.write('\n\n\n '); 3325 cursor.hide(); 3326 }); 3327 3328 runner.on('test end', function(test){ 3329 // check if the plane crashed 3330 var col = -1 == crashed 3331 ? width * ++n / total | 0 3332 : crashed; 3333 3334 // show the crash 3335 if ('failed' == test.state) { 3336 plane = color('plane crash', '✈'); 3337 crashed = col; 3338 } 3339 3340 // render landing strip 3341 stream.write('\u001b['+(width+1)+'D\u001b[2A'); 3342 stream.write(runway()); 3343 stream.write('\n '); 3344 stream.write(color('runway', Array(col).join('⋅'))); 3345 stream.write(plane) 3346 stream.write(color('runway', Array(width - col).join('⋅') + '\n')); 3347 stream.write(runway()); 3348 stream.write('\u001b[0m'); 3349 }); 3350 3351 runner.on('end', function(){ 3352 cursor.show(); 3353 console.log(); 3354 self.epilogue(); 3355 }); 3356} 3357 3358/** 3359 * Inherit from `Base.prototype`. 3360 */ 3361 3362function F(){}; 3363F.prototype = Base.prototype; 3364Landing.prototype = new F; 3365Landing.prototype.constructor = Landing; 3366 3367 3368}); // module: reporters/landing.js 3369 3370require.register("reporters/list.js", function(module, exports, require){ 3371/** 3372 * Module dependencies. 3373 */ 3374 3375var Base = require('./base') 3376 , cursor = Base.cursor 3377 , color = Base.color; 3378 3379/** 3380 * Expose `List`. 3381 */ 3382 3383exports = module.exports = List; 3384 3385/** 3386 * Initialize a new `List` test reporter. 3387 * 3388 * @param {Runner} runner 3389 * @api public 3390 */ 3391 3392function List(runner) { 3393 Base.call(this, runner); 3394 3395 var self = this 3396 , stats = this.stats 3397 , n = 0; 3398 3399 runner.on('start', function(){ 3400 console.log(); 3401 }); 3402 3403 runner.on('test', function(test){ 3404 process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); 3405 }); 3406 3407 runner.on('pending', function(test){ 3408 var fmt = color('checkmark', ' -') 3409 + color('pending', ' %s'); 3410 console.log(fmt, test.fullTitle()); 3411 }); 3412 3413 runner.on('pass', function(test){ 3414 var fmt = color('checkmark', ' '+Base.symbols.dot) 3415 + color('pass', ' %s: ') 3416 + color(test.speed, '%dms'); 3417 cursor.CR(); 3418 console.log(fmt, test.fullTitle(), test.duration); 3419 }); 3420 3421 runner.on('fail', function(test, err){ 3422 cursor.CR(); 3423 console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); 3424 }); 3425 3426 runner.on('end', self.epilogue.bind(self)); 3427} 3428 3429/** 3430 * Inherit from `Base.prototype`. 3431 */ 3432 3433function F(){}; 3434F.prototype = Base.prototype; 3435List.prototype = new F; 3436List.prototype.constructor = List; 3437 3438 3439}); // module: reporters/list.js 3440 3441require.register("reporters/markdown.js", function(module, exports, require){ 3442/** 3443 * Module dependencies. 3444 */ 3445 3446var Base = require('./base') 3447 , utils = require('../utils'); 3448 3449/** 3450 * Constants 3451 */ 3452 3453var SUITE_PREFIX = '$'; 3454 3455/** 3456 * Expose `Markdown`. 3457 */ 3458 3459exports = module.exports = Markdown; 3460 3461/** 3462 * Initialize a new `Markdown` reporter. 3463 * 3464 * @param {Runner} runner 3465 * @api public 3466 */ 3467 3468function Markdown(runner) { 3469 Base.call(this, runner); 3470 3471 var self = this 3472 , stats = this.stats 3473 , level = 0 3474 , buf = ''; 3475 3476 function title(str) { 3477 return Array(level).join('#') + ' ' + str; 3478 } 3479 3480 function indent() { 3481 return Array(level).join(' '); 3482 } 3483 3484 function mapTOC(suite, obj) { 3485 var ret = obj, 3486 key = SUITE_PREFIX + suite.title; 3487 obj = obj[key] = obj[key] || { suite: suite }; 3488 suite.suites.forEach(function(suite){ 3489 mapTOC(suite, obj); 3490 }); 3491 return ret; 3492 } 3493 3494 function stringifyTOC(obj, level) { 3495 ++level; 3496 var buf = ''; 3497 var link; 3498 for (var key in obj) { 3499 if ('suite' == key) continue; 3500 if (key !== SUITE_PREFIX) { 3501 link = ' - [' + key.substring(1) + ']'; 3502 link += '(#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; 3503 buf += Array(level).join(' ') + link; 3504 } 3505 buf += stringifyTOC(obj[key], level); 3506 } 3507 return buf; 3508 } 3509 3510 function generateTOC(suite) { 3511 var obj = mapTOC(suite, {}); 3512 return stringifyTOC(obj, 0); 3513 } 3514 3515 generateTOC(runner.suite); 3516 3517 runner.on('suite', function(suite){ 3518 ++level; 3519 var slug = utils.slug(suite.fullTitle()); 3520 buf += '<a name="' + slug + '"></a>' + '\n'; 3521 buf += title(suite.title) + '\n'; 3522 }); 3523 3524 runner.on('suite end', function(suite){ 3525 --level; 3526 }); 3527 3528 runner.on('pass', function(test){ 3529 var code = utils.clean(test.fn.toString()); 3530 buf += test.title + '.\n'; 3531 buf += '\n```js\n'; 3532 buf += code + '\n'; 3533 buf += '```\n\n'; 3534 }); 3535 3536 runner.on('end', function(){ 3537 process.stdout.write('# TOC\n'); 3538 process.stdout.write(generateTOC(runner.suite)); 3539 process.stdout.write(buf); 3540 }); 3541} 3542 3543}); // module: reporters/markdown.js 3544 3545require.register("reporters/min.js", function(module, exports, require){ 3546/** 3547 * Module dependencies. 3548 */ 3549 3550var Base = require('./base'); 3551 3552/** 3553 * Expose `Min`. 3554 */ 3555 3556exports = module.exports = Min; 3557 3558/** 3559 * Initialize a new `Min` minimal test reporter (best used with --watch). 3560 * 3561 * @param {Runner} runner 3562 * @api public 3563 */ 3564 3565function Min(runner) { 3566 Base.call(this, runner); 3567 3568 runner.on('start', function(){ 3569 // clear screen 3570 process.stdout.write('\u001b[2J'); 3571 // set cursor position 3572 process.stdout.write('\u001b[1;3H'); 3573 }); 3574 3575 runner.on('end', this.epilogue.bind(this)); 3576} 3577 3578/** 3579 * Inherit from `Base.prototype`. 3580 */ 3581 3582function F(){}; 3583F.prototype = Base.prototype; 3584Min.prototype = new F; 3585Min.prototype.constructor = Min; 3586 3587 3588}); // module: reporters/min.js 3589 3590require.register("reporters/nyan.js", function(module, exports, require){ 3591/** 3592 * Module dependencies. 3593 */ 3594 3595var Base = require('./base'); 3596 3597/** 3598 * Expose `Dot`. 3599 */ 3600 3601exports = module.exports = NyanCat; 3602 3603/** 3604 * Initialize a new `Dot` matrix test reporter. 3605 * 3606 * @param {Runner} runner 3607 * @api public 3608 */ 3609 3610function NyanCat(runner) { 3611 Base.call(this, runner); 3612 var self = this 3613 , stats = this.stats 3614 , width = Base.window.width * .75 | 0 3615 , rainbowColors = this.rainbowColors = self.generateColors() 3616 , colorIndex = this.colorIndex = 0 3617 , numerOfLines = this.numberOfLines = 4 3618 , trajectories = this.trajectories = [[], [], [], []] 3619 , nyanCatWidth = this.nyanCatWidth = 11 3620 , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) 3621 , scoreboardWidth = this.scoreboardWidth = 5 3622 , tick = this.tick = 0 3623 , n = 0; 3624 3625 runner.on('start', function(){ 3626 Base.cursor.hide(); 3627 self.draw(); 3628 }); 3629 3630 runner.on('pending', function(test){ 3631 self.draw(); 3632 }); 3633 3634 runner.on('pass', function(test){ 3635 self.draw(); 3636 }); 3637 3638 runner.on('fail', function(test, err){ 3639 self.draw(); 3640 }); 3641 3642 runner.on('end', function(){ 3643 Base.cursor.show(); 3644 for (var i = 0; i < self.numberOfLines; i++) write('\n'); 3645 self.epilogue(); 3646 }); 3647} 3648 3649/** 3650 * Draw the nyan cat 3651 * 3652 * @api private 3653 */ 3654 3655NyanCat.prototype.draw = function(){ 3656 this.appendRainbow(); 3657 this.drawScoreboard(); 3658 this.drawRainbow(); 3659 this.drawNyanCat(); 3660 this.tick = !this.tick; 3661}; 3662 3663/** 3664 * Draw the "scoreboard" showing the number 3665 * of passes, failures and pending tests. 3666 * 3667 * @api private 3668 */ 3669 3670NyanCat.prototype.drawScoreboard = function(){ 3671 var stats = this.stats; 3672 3673 function draw(type, n) { 3674 write(' '); 3675 write(Base.color(type, n)); 3676 write('\n'); 3677 } 3678 3679 draw('green', stats.passes); 3680 draw('fail', stats.failures); 3681 draw('pending', stats.pending); 3682 write('\n'); 3683 3684 this.cursorUp(this.numberOfLines); 3685}; 3686 3687/** 3688 * Append the rainbow. 3689 * 3690 * @api private 3691 */ 3692 3693NyanCat.prototype.appendRainbow = function(){ 3694 var segment = this.tick ? '_' : '-'; 3695 var rainbowified = this.rainbowify(segment); 3696 3697 for (var index = 0; index < this.numberOfLines; index++) { 3698 var trajectory = this.trajectories[index]; 3699 if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); 3700 trajectory.push(rainbowified); 3701 } 3702}; 3703 3704/** 3705 * Draw the rainbow. 3706 * 3707 * @api private 3708 */ 3709 3710NyanCat.prototype.drawRainbow = function(){ 3711 var self = this; 3712 3713 this.trajectories.forEach(function(line, index) { 3714 write('\u001b[' + self.scoreboardWidth + 'C'); 3715 write(line.join('')); 3716 write('\n'); 3717 }); 3718 3719 this.cursorUp(this.numberOfLines); 3720}; 3721 3722/** 3723 * Draw the nyan cat 3724 * 3725 * @api private 3726 */ 3727 3728NyanCat.prototype.drawNyanCat = function() { 3729 var self = this; 3730 var startWidth = this.scoreboardWidth + this.trajectories[0].length; 3731 var dist = '\u001b[' + startWidth + 'C'; 3732 var padding = ''; 3733 3734 write(dist); 3735 write('_,------,'); 3736 write('\n'); 3737 3738 write(dist); 3739 padding = self.tick ? ' ' : ' '; 3740 write('_|' + padding + '/\\_/\\ '); 3741 write('\n'); 3742 3743 write(dist); 3744 padding = self.tick ? '_' : '__'; 3745 var tail = self.tick ? '~' : '^'; 3746 var face; 3747 write(tail + '|' + padding + this.face() + ' '); 3748 write('\n'); 3749 3750 write(dist); 3751 padding = self.tick ? ' ' : ' '; 3752 write(padding + '"" "" '); 3753 write('\n'); 3754 3755 this.cursorUp(this.numberOfLines); 3756}; 3757 3758/** 3759 * Draw nyan cat face. 3760 * 3761 * @return {String} 3762 * @api private 3763 */ 3764 3765NyanCat.prototype.face = function() { 3766 var stats = this.stats; 3767 if (stats.failures) { 3768 return '( x .x)'; 3769 } else if (stats.pending) { 3770 return '( o .o)'; 3771 } else if(stats.passes) { 3772 return '( ^ .^)'; 3773 } else { 3774 return '( - .-)'; 3775 } 3776}; 3777 3778/** 3779 * Move cursor up `n`. 3780 * 3781 * @param {Number} n 3782 * @api private 3783 */ 3784 3785NyanCat.prototype.cursorUp = function(n) { 3786 write('\u001b[' + n + 'A'); 3787}; 3788 3789/** 3790 * Move cursor down `n`. 3791 * 3792 * @param {Number} n 3793 * @api private 3794 */ 3795 3796NyanCat.prototype.cursorDown = function(n) { 3797 write('\u001b[' + n + 'B'); 3798}; 3799 3800/** 3801 * Generate rainbow colors. 3802 * 3803 * @return {Array} 3804 * @api private 3805 */ 3806 3807NyanCat.prototype.generateColors = function(){ 3808 var colors = []; 3809 3810 for (var i = 0; i < (6 * 7); i++) { 3811 var pi3 = Math.floor(Math.PI / 3); 3812 var n = (i * (1.0 / 6)); 3813 var r = Math.floor(3 * Math.sin(n) + 3); 3814 var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); 3815 var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); 3816 colors.push(36 * r + 6 * g + b + 16); 3817 } 3818 3819 return colors; 3820}; 3821 3822/** 3823 * Apply rainbow to the given `str`. 3824 * 3825 * @param {String} str 3826 * @return {String} 3827 * @api private 3828 */ 3829 3830NyanCat.prototype.rainbowify = function(str){ 3831 if (!Base.useColors) 3832 return str; 3833 var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; 3834 this.colorIndex += 1; 3835 return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; 3836}; 3837 3838/** 3839 * Stdout helper. 3840 */ 3841 3842function write(string) { 3843 process.stdout.write(string); 3844} 3845 3846/** 3847 * Inherit from `Base.prototype`. 3848 */ 3849 3850function F(){}; 3851F.prototype = Base.prototype; 3852NyanCat.prototype = new F; 3853NyanCat.prototype.constructor = NyanCat; 3854 3855 3856}); // module: reporters/nyan.js 3857 3858require.register("reporters/progress.js", function(module, exports, require){ 3859/** 3860 * Module dependencies. 3861 */ 3862 3863var Base = require('./base') 3864 , cursor = Base.cursor 3865 , color = Base.color; 3866 3867/** 3868 * Expose `Progress`. 3869 */ 3870 3871exports = module.exports = Progress; 3872 3873/** 3874 * General progress bar color. 3875 */ 3876 3877Base.colors.progress = 90; 3878 3879/** 3880 * Initialize a new `Progress` bar test reporter. 3881 * 3882 * @param {Runner} runner 3883 * @param {Object} options 3884 * @api public 3885 */ 3886 3887function Progress(runner, options) { 3888 Base.call(this, runner); 3889 3890 var self = this 3891 , options = options || {} 3892 , stats = this.stats 3893 , width = Base.window.width * .50 | 0 3894 , total = runner.total 3895 , complete = 0 3896 , max = Math.max 3897 , lastN = -1; 3898 3899 // default chars 3900 options.open = options.open || '['; 3901 options.complete = options.complete || '▬'; 3902 options.incomplete = options.incomplete || Base.symbols.dot; 3903 options.close = options.close || ']'; 3904 options.verbose = false; 3905 3906 // tests started 3907 runner.on('start', function(){ 3908 console.log(); 3909 cursor.hide(); 3910 }); 3911 3912 // tests complete 3913 runner.on('test end', function(){ 3914 complete++; 3915 var incomplete = total - complete 3916 , percent = complete / total 3917 , n = width * percent | 0 3918 , i = width - n; 3919 3920 if (lastN === n && !options.verbose) { 3921 // Don't re-render the line if it hasn't changed 3922 return; 3923 } 3924 lastN = n; 3925 3926 cursor.CR(); 3927 process.stdout.write('\u001b[J'); 3928 process.stdout.write(color('progress', ' ' + options.open)); 3929 process.stdout.write(Array(n).join(options.complete)); 3930 process.stdout.write(Array(i).join(options.incomplete)); 3931 process.stdout.write(color('progress', options.close)); 3932 if (options.verbose) { 3933 process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); 3934 } 3935 }); 3936 3937 // tests are complete, output some stats 3938 // and the failures if any 3939 runner.on('end', function(){ 3940 cursor.show(); 3941 console.log(); 3942 self.epilogue(); 3943 }); 3944} 3945 3946/** 3947 * Inherit from `Base.prototype`. 3948 */ 3949 3950function F(){}; 3951F.prototype = Base.prototype; 3952Progress.prototype = new F; 3953Progress.prototype.constructor = Progress; 3954 3955 3956}); // module: reporters/progress.js 3957 3958require.register("reporters/spec.js", function(module, exports, require){ 3959/** 3960 * Module dependencies. 3961 */ 3962 3963var Base = require('./base') 3964 , cursor = Base.cursor 3965 , color = Base.color; 3966 3967/** 3968 * Expose `Spec`. 3969 */ 3970 3971exports = module.exports = Spec; 3972 3973/** 3974 * Initialize a new `Spec` test reporter. 3975 * 3976 * @param {Runner} runner 3977 * @api public 3978 */ 3979 3980function Spec(runner) { 3981 Base.call(this, runner); 3982 3983 var self = this 3984 , stats = this.stats 3985 , indents = 0 3986 , n = 0; 3987 3988 function indent() { 3989 return Array(indents).join(' ') 3990 } 3991 3992 runner.on('start', function(){ 3993 console.log(); 3994 }); 3995 3996 runner.on('suite', function(suite){ 3997 ++indents; 3998 console.log(color('suite', '%s%s'), indent(), suite.title); 3999 }); 4000 4001 runner.on('suite end', function(suite){ 4002 --indents; 4003 if (1 == indents) console.log(); 4004 }); 4005 4006 runner.on('pending', function(test){ 4007 var fmt = indent() + color('pending', ' - %s'); 4008 console.log(fmt, test.title); 4009 }); 4010 4011 runner.on('pass', function(test){ 4012 if ('fast' == test.speed) { 4013 var fmt = indent() 4014 + color('checkmark', ' ' + Base.symbols.ok) 4015 + color('pass', ' %s '); 4016 cursor.CR(); 4017 console.log(fmt, test.title); 4018 } else { 4019 var fmt = indent() 4020 + color('checkmark', ' ' + Base.symbols.ok) 4021 + color('pass', ' %s ') 4022 + color(test.speed, '(%dms)'); 4023 cursor.CR(); 4024 console.log(fmt, test.title, test.duration); 4025 } 4026 }); 4027 4028 runner.on('fail', function(test, err){ 4029 cursor.CR(); 4030 console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); 4031 }); 4032 4033 runner.on('end', self.epilogue.bind(self)); 4034} 4035 4036/** 4037 * Inherit from `Base.prototype`. 4038 */ 4039 4040function F(){}; 4041F.prototype = Base.prototype; 4042Spec.prototype = new F; 4043Spec.prototype.constructor = Spec; 4044 4045 4046}); // module: reporters/spec.js 4047 4048require.register("reporters/tap.js", function(module, exports, require){ 4049/** 4050 * Module dependencies. 4051 */ 4052 4053var Base = require('./base') 4054 , cursor = Base.cursor 4055 , color = Base.color; 4056 4057/** 4058 * Expose `TAP`. 4059 */ 4060 4061exports = module.exports = TAP; 4062 4063/** 4064 * Initialize a new `TAP` reporter. 4065 * 4066 * @param {Runner} runner 4067 * @api public 4068 */ 4069 4070function TAP(runner) { 4071 Base.call(this, runner); 4072 4073 var self = this 4074 , stats = this.stats 4075 , n = 1 4076 , passes = 0 4077 , failures = 0; 4078 4079 runner.on('start', function(){ 4080 var total = runner.grepTotal(runner.suite); 4081 console.log('%d..%d', 1, total); 4082 }); 4083 4084 runner.on('test end', function(){ 4085 ++n; 4086 }); 4087 4088 runner.on('pending', function(test){ 4089 console.log('ok %d %s # SKIP -', n, title(test)); 4090 }); 4091 4092 runner.on('pass', function(test){ 4093 passes++; 4094 console.log('ok %d %s', n, title(test)); 4095 }); 4096 4097 runner.on('fail', function(test, err){ 4098 failures++; 4099 console.log('not ok %d %s', n, title(test)); 4100 if (err.stack) console.log(err.stack.replace(/^/gm, ' ')); 4101 }); 4102 4103 runner.on('end', function(){ 4104 console.log('# tests ' + (passes + failures)); 4105 console.log('# pass ' + passes); 4106 console.log('# fail ' + failures); 4107 }); 4108} 4109 4110/** 4111 * Return a TAP-safe title of `test` 4112 * 4113 * @param {Object} test 4114 * @return {String} 4115 * @api private 4116 */ 4117 4118function title(test) { 4119 return test.fullTitle().replace(/#/g, ''); 4120} 4121 4122}); // module: reporters/tap.js 4123 4124require.register("reporters/xunit.js", function(module, exports, require){ 4125/** 4126 * Module dependencies. 4127 */ 4128 4129var Base = require('./base') 4130 , utils = require('../utils') 4131 , fs = require('browser/fs') 4132 , escape = utils.escape; 4133 4134/** 4135 * Save timer references to avoid Sinon interfering (see GH-237). 4136 */ 4137 4138var Date = global.Date 4139 , setTimeout = global.setTimeout 4140 , setInterval = global.setInterval 4141 , clearTimeout = global.clearTimeout 4142 , clearInterval = global.clearInterval; 4143 4144/** 4145 * Expose `XUnit`. 4146 */ 4147 4148exports = module.exports = XUnit; 4149 4150/** 4151 * Initialize a new `XUnit` reporter. 4152 * 4153 * @param {Runner} runner 4154 * @api public 4155 */ 4156 4157function XUnit(runner, options) { 4158 Base.call(this, runner); 4159 var stats = this.stats 4160 , tests = [] 4161 , self = this; 4162 4163 if (options.reporterOptions && options.reporterOptions.output) { 4164 if (! fs.createWriteStream) { 4165 throw new Error('file output not supported in browser'); 4166 } 4167 self.fileStream = fs.createWriteStream(options.reporterOptions.output); 4168 } 4169 4170 runner.on('pending', function(test){ 4171 tests.push(test); 4172 }); 4173 4174 runner.on('pass', function(test){ 4175 tests.push(test); 4176 }); 4177 4178 runner.on('fail', function(test){ 4179 tests.push(test); 4180 }); 4181 4182 runner.on('end', function(){ 4183 self.write(tag('testsuite', { 4184 name: 'Mocha Tests' 4185 , tests: stats.tests 4186 , failures: stats.failures 4187 , errors: stats.failures 4188 , skipped: stats.tests - stats.failures - stats.passes 4189 , timestamp: (new Date).toUTCString() 4190 , time: (stats.duration / 1000) || 0 4191 }, false)); 4192 4193 tests.forEach(function(t) { self.test(t); }); 4194 self.write('</testsuite>'); 4195 }); 4196} 4197 4198/** 4199 * Override done to close the stream (if it's a file). 4200 */ 4201XUnit.prototype.done = function(failures, fn) { 4202 if (this.fileStream) { 4203 this.fileStream.end(function() { 4204 fn(failures); 4205 }); 4206 } else { 4207 fn(failures); 4208 } 4209}; 4210 4211/** 4212 * Inherit from `Base.prototype`. 4213 */ 4214 4215function F(){}; 4216F.prototype = Base.prototype; 4217XUnit.prototype = new F; 4218XUnit.prototype.constructor = XUnit; 4219 4220 4221/** 4222 * Write out the given line 4223 */ 4224XUnit.prototype.write = function(line) { 4225 if (this.fileStream) { 4226 this.fileStream.write(line + '\n'); 4227 } else { 4228 console.log(line); 4229 } 4230}; 4231 4232/** 4233 * Output tag for the given `test.` 4234 */ 4235 4236XUnit.prototype.test = function(test, ostream) { 4237 var attrs = { 4238 classname: test.parent.fullTitle() 4239 , name: test.title 4240 , time: (test.duration / 1000) || 0 4241 }; 4242 4243 if ('failed' == test.state) { 4244 var err = test.err; 4245 this.write(tag('testcase', attrs, false, tag('failure', {}, false, cdata(escape(err.message) + "\n" + err.stack)))); 4246 } else if (test.pending) { 4247 this.write(tag('testcase', attrs, false, tag('skipped', {}, true))); 4248 } else { 4249 this.write(tag('testcase', attrs, true) ); 4250 } 4251}; 4252 4253/** 4254 * HTML tag helper. 4255 */ 4256 4257function tag(name, attrs, close, content) { 4258 var end = close ? '/>' : '>' 4259 , pairs = [] 4260 , tag; 4261 4262 for (var key in attrs) { 4263 pairs.push(key + '="' + escape(attrs[key]) + '"'); 4264 } 4265 4266 tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; 4267 if (content) tag += content + '</' + name + end; 4268 return tag; 4269} 4270 4271/** 4272 * Return cdata escaped CDATA `str`. 4273 */ 4274 4275function cdata(str) { 4276 return '<![CDATA[' + escape(str) + ']]>'; 4277} 4278 4279}); // module: reporters/xunit.js 4280 4281require.register("runnable.js", function(module, exports, require){ 4282/** 4283 * Module dependencies. 4284 */ 4285 4286var EventEmitter = require('browser/events').EventEmitter 4287 , debug = require('browser/debug')('mocha:runnable') 4288 , Pending = require('./pending') 4289 , milliseconds = require('./ms') 4290 , utils = require('./utils'); 4291 4292/** 4293 * Save timer references to avoid Sinon interfering (see GH-237). 4294 */ 4295 4296var Date = global.Date 4297 , setTimeout = global.setTimeout 4298 , setInterval = global.setInterval 4299 , clearTimeout = global.clearTimeout 4300 , clearInterval = global.clearInterval; 4301 4302/** 4303 * Object#toString(). 4304 */ 4305 4306var toString = Object.prototype.toString; 4307 4308/** 4309 * Expose `Runnable`. 4310 */ 4311 4312module.exports = Runnable; 4313 4314/** 4315 * Initialize a new `Runnable` with the given `title` and callback `fn`. 4316 * 4317 * @param {String} title 4318 * @param {Function} fn 4319 * @api private 4320 */ 4321 4322function Runnable(title, fn) { 4323 this.title = title; 4324 this.fn = fn; 4325 this.async = fn && fn.length; 4326 this.sync = ! this.async; 4327 this._timeout = 2000; 4328 this._slow = 75; 4329 this._enableTimeouts = true; 4330 this.timedOut = false; 4331 this._trace = new Error('done() called multiple times') 4332} 4333 4334/** 4335 * Inherit from `EventEmitter.prototype`. 4336 */ 4337 4338function F(){}; 4339F.prototype = EventEmitter.prototype; 4340Runnable.prototype = new F; 4341Runnable.prototype.constructor = Runnable; 4342 4343 4344/** 4345 * Set & get timeout `ms`. 4346 * 4347 * @param {Number|String} ms 4348 * @return {Runnable|Number} ms or self 4349 * @api private 4350 */ 4351 4352Runnable.prototype.timeout = function(ms){ 4353 if (0 == arguments.length) return this._timeout; 4354 if (ms === 0) this._enableTimeouts = false; 4355 if ('string' == typeof ms) ms = milliseconds(ms); 4356 debug('timeout %d', ms); 4357 this._timeout = ms; 4358 if (this.timer) this.resetTimeout(); 4359 return this; 4360}; 4361 4362/** 4363 * Set & get slow `ms`. 4364 * 4365 * @param {Number|String} ms 4366 * @return {Runnable|Number} ms or self 4367 * @api private 4368 */ 4369 4370Runnable.prototype.slow = function(ms){ 4371 if (0 === arguments.length) return this._slow; 4372 if ('string' == typeof ms) ms = milliseconds(ms); 4373 debug('timeout %d', ms); 4374 this._slow = ms; 4375 return this; 4376}; 4377 4378/** 4379 * Set and & get timeout `enabled`. 4380 * 4381 * @param {Boolean} enabled 4382 * @return {Runnable|Boolean} enabled or self 4383 * @api private 4384 */ 4385 4386Runnable.prototype.enableTimeouts = function(enabled){ 4387 if (arguments.length === 0) return this._enableTimeouts; 4388 debug('enableTimeouts %s', enabled); 4389 this._enableTimeouts = enabled; 4390 return this; 4391}; 4392 4393/** 4394 * Halt and mark as pending. 4395 * 4396 * @api private 4397 */ 4398 4399Runnable.prototype.skip = function(){ 4400 throw new Pending(); 4401}; 4402 4403/** 4404 * Return the full title generated by recursively 4405 * concatenating the parent's full title. 4406 * 4407 * @return {String} 4408 * @api public 4409 */ 4410 4411Runnable.prototype.fullTitle = function(){ 4412 return this.parent.fullTitle() + ' ' + this.title; 4413}; 4414 4415/** 4416 * Clear the timeout. 4417 * 4418 * @api private 4419 */ 4420 4421Runnable.prototype.clearTimeout = function(){ 4422 clearTimeout(this.timer); 4423}; 4424 4425/** 4426 * Inspect the runnable void of private properties. 4427 * 4428 * @return {String} 4429 * @api private 4430 */ 4431 4432Runnable.prototype.inspect = function(){ 4433 return JSON.stringify(this, function(key, val){ 4434 if ('_' == key[0]) return; 4435 if ('parent' == key) return '#<Suite>'; 4436 if ('ctx' == key) return '#<Context>'; 4437 return val; 4438 }, 2); 4439}; 4440 4441/** 4442 * Reset the timeout. 4443 * 4444 * @api private 4445 */ 4446 4447Runnable.prototype.resetTimeout = function(){ 4448 var self = this; 4449 var ms = this.timeout() || 1e9; 4450 4451 if (!this._enableTimeouts) return; 4452 this.clearTimeout(); 4453 this.timer = setTimeout(function(){ 4454 if (!self._enableTimeouts) return; 4455 self.callback(new Error('timeout of ' + ms + 'ms exceeded. Ensure the done() callback is being called in this test.')); 4456 self.timedOut = true; 4457 }, ms); 4458}; 4459 4460/** 4461 * Whitelist these globals for this test run 4462 * 4463 * @api private 4464 */ 4465Runnable.prototype.globals = function(arr){ 4466 var self = this; 4467 this._allowedGlobals = arr; 4468}; 4469 4470/** 4471 * Run the test and invoke `fn(err)`. 4472 * 4473 * @param {Function} fn 4474 * @api private 4475 */ 4476 4477Runnable.prototype.run = function(fn){ 4478 var self = this 4479 , start = new Date 4480 , ctx = this.ctx 4481 , finished 4482 , emitted; 4483 4484 // Some times the ctx exists but it is not runnable 4485 if (ctx && ctx.runnable) ctx.runnable(this); 4486 4487 // called multiple times 4488 function multiple(err) { 4489 if (emitted) return; 4490 emitted = true; 4491 self.emit('error', err || new Error('done() called multiple times; stacktrace may be inaccurate')); 4492 } 4493 4494 // finished 4495 function done(err) { 4496 var ms = self.timeout(); 4497 if (self.timedOut) return; 4498 if (finished) return multiple(err || self._trace); 4499 4500 // Discard the resolution if this test has already failed asynchronously 4501 if (self.state) return; 4502 4503 self.clearTimeout(); 4504 self.duration = new Date - start; 4505 finished = true; 4506 if (!err && self.duration > ms && self._enableTimeouts) err = new Error('timeout of ' + ms + 'ms exceeded. Ensure the done() callback is being called in this test.'); 4507 fn(err); 4508 } 4509 4510 // for .resetTimeout() 4511 this.callback = done; 4512 4513 // explicit async with `done` argument 4514 if (this.async) { 4515 this.resetTimeout(); 4516 4517 try { 4518 this.fn.call(ctx, function(err){ 4519 if (err instanceof Error || toString.call(err) === "[object Error]") return done(err); 4520 if (null != err) { 4521 if (Object.prototype.toString.call(err) === '[object Object]') { 4522 return done(new Error('done() invoked with non-Error: ' + JSON.stringify(err))); 4523 } else { 4524 return done(new Error('done() invoked with non-Error: ' + err)); 4525 } 4526 } 4527 done(); 4528 }); 4529 } catch (err) { 4530 done(utils.getError(err)); 4531 } 4532 return; 4533 } 4534 4535 if (this.asyncOnly) { 4536 return done(new Error('--async-only option in use without declaring `done()`')); 4537 } 4538 4539 // sync or promise-returning 4540 try { 4541 if (this.pending) { 4542 done(); 4543 } else { 4544 callFn(this.fn); 4545 } 4546 } catch (err) { 4547 done(utils.getError(err)); 4548 } 4549 4550 function callFn(fn) { 4551 var result = fn.call(ctx); 4552 if (result && typeof result.then === 'function') { 4553 self.resetTimeout(); 4554 result 4555 .then(function() { 4556 done() 4557 }, 4558 function(reason) { 4559 done(reason || new Error('Promise rejected with no or falsy reason')) 4560 }); 4561 } else { 4562 done(); 4563 } 4564 } 4565}; 4566 4567}); // module: runnable.js 4568 4569require.register("runner.js", function(module, exports, require){ 4570/** 4571 * Module dependencies. 4572 */ 4573 4574var EventEmitter = require('browser/events').EventEmitter 4575 , debug = require('browser/debug')('mocha:runner') 4576 , Pending = require('./pending') 4577 , Test = require('./test') 4578 , utils = require('./utils') 4579 , filter = utils.filter 4580 , keys = utils.keys 4581 , type = utils.type 4582 , stringify = utils.stringify 4583 , stackFilter = utils.stackTraceFilter(); 4584 4585/** 4586 * Non-enumerable globals. 4587 */ 4588 4589var globals = [ 4590 'setTimeout', 4591 'clearTimeout', 4592 'setInterval', 4593 'clearInterval', 4594 'XMLHttpRequest', 4595 'Date', 4596 'setImmediate', 4597 'clearImmediate' 4598]; 4599 4600/** 4601 * Expose `Runner`. 4602 */ 4603 4604module.exports = Runner; 4605 4606/** 4607 * Initialize a `Runner` for the given `suite`. 4608 * 4609 * Events: 4610 * 4611 * - `start` execution started 4612 * - `end` execution complete 4613 * - `suite` (suite) test suite execution started 4614 * - `suite end` (suite) all tests (and sub-suites) have finished 4615 * - `test` (test) test execution started 4616 * - `test end` (test) test completed 4617 * - `hook` (hook) hook execution started 4618 * - `hook end` (hook) hook complete 4619 * - `pass` (test) test passed 4620 * - `fail` (test, err) test failed 4621 * - `pending` (test) test pending 4622 * 4623 * @param {Suite} suite Root suite 4624 * @param {boolean} [delay] Whether or not to delay execution of root suite 4625 * until ready. 4626 * @api public 4627 */ 4628 4629function Runner(suite, delay) { 4630 var self = this; 4631 this._globals = []; 4632 this._abort = false; 4633 this._delay = delay; 4634 this.suite = suite; 4635 this.total = suite.total(); 4636 this.failures = 0; 4637 this.on('test end', function(test){ self.checkGlobals(test); }); 4638 this.on('hook end', function(hook){ self.checkGlobals(hook); }); 4639 this.grep(/.*/); 4640 this.globals(this.globalProps().concat(extraGlobals())); 4641} 4642 4643/** 4644 * Wrapper for setImmediate, process.nextTick, or browser polyfill. 4645 * 4646 * @param {Function} fn 4647 * @api private 4648 */ 4649 4650Runner.immediately = global.setImmediate || process.nextTick; 4651 4652/** 4653 * Inherit from `EventEmitter.prototype`. 4654 */ 4655 4656function F(){}; 4657F.prototype = EventEmitter.prototype; 4658Runner.prototype = new F; 4659Runner.prototype.constructor = Runner; 4660 4661 4662/** 4663 * Run tests with full titles matching `re`. Updates runner.total 4664 * with number of tests matched. 4665 * 4666 * @param {RegExp} re 4667 * @param {Boolean} invert 4668 * @return {Runner} for chaining 4669 * @api public 4670 */ 4671 4672Runner.prototype.grep = function(re, invert){ 4673 debug('grep %s', re); 4674 this._grep = re; 4675 this._invert = invert; 4676 this.total = this.grepTotal(this.suite); 4677 return this; 4678}; 4679 4680/** 4681 * Returns the number of tests matching the grep search for the 4682 * given suite. 4683 * 4684 * @param {Suite} suite 4685 * @return {Number} 4686 * @api public 4687 */ 4688 4689Runner.prototype.grepTotal = function(suite) { 4690 var self = this; 4691 var total = 0; 4692 4693 suite.eachTest(function(test){ 4694 var match = self._grep.test(test.fullTitle()); 4695 if (self._invert) match = !match; 4696 if (match) total++; 4697 }); 4698 4699 return total; 4700}; 4701 4702/** 4703 * Return a list of global properties. 4704 * 4705 * @return {Array} 4706 * @api private 4707 */ 4708 4709Runner.prototype.globalProps = function() { 4710 var props = utils.keys(global); 4711 4712 // non-enumerables 4713 for (var i = 0; i < globals.length; ++i) { 4714 if (~utils.indexOf(props, globals[i])) continue; 4715 props.push(globals[i]); 4716 } 4717 4718 return props; 4719}; 4720 4721/** 4722 * Allow the given `arr` of globals. 4723 * 4724 * @param {Array} arr 4725 * @return {Runner} for chaining 4726 * @api public 4727 */ 4728 4729Runner.prototype.globals = function(arr){ 4730 if (0 == arguments.length) return this._globals; 4731 debug('globals %j', arr); 4732 this._globals = this._globals.concat(arr); 4733 return this; 4734}; 4735 4736/** 4737 * Check for global variable leaks. 4738 * 4739 * @api private 4740 */ 4741 4742Runner.prototype.checkGlobals = function(test){ 4743 if (this.ignoreLeaks) return; 4744 var ok = this._globals; 4745 4746 var globals = this.globalProps(); 4747 var leaks; 4748 4749 if (test) { 4750 ok = ok.concat(test._allowedGlobals || []); 4751 } 4752 4753 if(this.prevGlobalsLength == globals.length) return; 4754 this.prevGlobalsLength = globals.length; 4755 4756 leaks = filterLeaks(ok, globals); 4757 this._globals = this._globals.concat(leaks); 4758 4759 if (leaks.length > 1) { 4760 this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); 4761 } else if (leaks.length) { 4762 this.fail(test, new Error('global leak detected: ' + leaks[0])); 4763 } 4764}; 4765 4766/** 4767 * Fail the given `test`. 4768 * 4769 * @param {Test} test 4770 * @param {Error} err 4771 * @api private 4772 */ 4773 4774Runner.prototype.fail = function(test, err) { 4775 ++this.failures; 4776 test.state = 'failed'; 4777 4778 if (!(err instanceof Error)) { 4779 err = new Error('the ' + type(err) + ' ' + stringify(err) + ' was thrown, throw an Error :)'); 4780 } 4781 4782 err.stack = this.fullStackTrace 4783 ? err.stack 4784 : stackFilter(err.stack); 4785 4786 this.emit('fail', test, err); 4787}; 4788 4789/** 4790 * Fail the given `hook` with `err`. 4791 * 4792 * Hook failures work in the following pattern: 4793 * - If bail, then exit 4794 * - Failed `before` hook skips all tests in a suite and subsuites, 4795 * but jumps to corresponding `after` hook 4796 * - Failed `before each` hook skips remaining tests in a 4797 * suite and jumps to corresponding `after each` hook, 4798 * which is run only once 4799 * - Failed `after` hook does not alter 4800 * execution order 4801 * - Failed `after each` hook skips remaining tests in a 4802 * suite and subsuites, but executes other `after each` 4803 * hooks 4804 * 4805 * @param {Hook} hook 4806 * @param {Error} err 4807 * @api private 4808 */ 4809 4810Runner.prototype.failHook = function(hook, err){ 4811 this.fail(hook, err); 4812 if (this.suite.bail()) { 4813 this.emit('end'); 4814 } 4815}; 4816 4817/** 4818 * Run hook `name` callbacks and then invoke `fn()`. 4819 * 4820 * @param {String} name 4821 * @param {Function} function 4822 * @api private 4823 */ 4824 4825Runner.prototype.hook = function(name, fn){ 4826 var suite = this.suite 4827 , hooks = suite['_' + name] 4828 , self = this 4829 , timer; 4830 4831 function next(i) { 4832 var hook = hooks[i]; 4833 if (!hook) return fn(); 4834 self.currentRunnable = hook; 4835 4836 hook.ctx.currentTest = self.test; 4837 4838 self.emit('hook', hook); 4839 4840 hook.on('error', function(err){ 4841 self.failHook(hook, err); 4842 }); 4843 4844 hook.run(function(err){ 4845 hook.removeAllListeners('error'); 4846 var testError = hook.error(); 4847 if (testError) self.fail(self.test, testError); 4848 if (err) { 4849 if (err instanceof Pending) { 4850 suite.pending = true; 4851 } else { 4852 self.failHook(hook, err); 4853 4854 // stop executing hooks, notify callee of hook err 4855 return fn(err); 4856 } 4857 } 4858 self.emit('hook end', hook); 4859 delete hook.ctx.currentTest; 4860 next(++i); 4861 }); 4862 } 4863 4864 Runner.immediately(function(){ 4865 next(0); 4866 }); 4867}; 4868 4869/** 4870 * Run hook `name` for the given array of `suites` 4871 * in order, and callback `fn(err, errSuite)`. 4872 * 4873 * @param {String} name 4874 * @param {Array} suites 4875 * @param {Function} fn 4876 * @api private 4877 */ 4878 4879Runner.prototype.hooks = function(name, suites, fn){ 4880 var self = this 4881 , orig = this.suite; 4882 4883 function next(suite) { 4884 self.suite = suite; 4885 4886 if (!suite) { 4887 self.suite = orig; 4888 return fn(); 4889 } 4890 4891 self.hook(name, function(err){ 4892 if (err) { 4893 var errSuite = self.suite; 4894 self.suite = orig; 4895 return fn(err, errSuite); 4896 } 4897 4898 next(suites.pop()); 4899 }); 4900 } 4901 4902 next(suites.pop()); 4903}; 4904 4905/** 4906 * Run hooks from the top level down. 4907 * 4908 * @param {String} name 4909 * @param {Function} fn 4910 * @api private 4911 */ 4912 4913Runner.prototype.hookUp = function(name, fn){ 4914 var suites = [this.suite].concat(this.parents()).reverse(); 4915 this.hooks(name, suites, fn); 4916}; 4917 4918/** 4919 * Run hooks from the bottom up. 4920 * 4921 * @param {String} name 4922 * @param {Function} fn 4923 * @api private 4924 */ 4925 4926Runner.prototype.hookDown = function(name, fn){ 4927 var suites = [this.suite].concat(this.parents()); 4928 this.hooks(name, suites, fn); 4929}; 4930 4931/** 4932 * Return an array of parent Suites from 4933 * closest to furthest. 4934 * 4935 * @return {Array} 4936 * @api private 4937 */ 4938 4939Runner.prototype.parents = function(){ 4940 var suite = this.suite 4941 , suites = []; 4942 while (suite = suite.parent) suites.push(suite); 4943 return suites; 4944}; 4945 4946/** 4947 * Run the current test and callback `fn(err)`. 4948 * 4949 * @param {Function} fn 4950 * @api private 4951 */ 4952 4953Runner.prototype.runTest = function(fn){ 4954 var test = this.test 4955 , self = this; 4956 4957 if (this.asyncOnly) test.asyncOnly = true; 4958 4959 try { 4960 test.on('error', function(err){ 4961 self.fail(test, err); 4962 }); 4963 test.run(fn); 4964 } catch (err) { 4965 fn(err); 4966 } 4967}; 4968 4969/** 4970 * Run tests in the given `suite` and invoke 4971 * the callback `fn()` when complete. 4972 * 4973 * @param {Suite} suite 4974 * @param {Function} fn 4975 * @api private 4976 */ 4977 4978Runner.prototype.runTests = function(suite, fn){ 4979 var self = this 4980 , tests = suite.tests.slice() 4981 , test; 4982 4983 4984 function hookErr(err, errSuite, after) { 4985 // before/after Each hook for errSuite failed: 4986 var orig = self.suite; 4987 4988 // for failed 'after each' hook start from errSuite parent, 4989 // otherwise start from errSuite itself 4990 self.suite = after ? errSuite.parent : errSuite; 4991 4992 if (self.suite) { 4993 // call hookUp afterEach 4994 self.hookUp('afterEach', function(err2, errSuite2) { 4995 self.suite = orig; 4996 // some hooks may fail even now 4997 if (err2) return hookErr(err2, errSuite2, true); 4998 // report error suite 4999 fn(errSuite); 5000 }); 5001 } else { 5002 // there is no need calling other 'after each' hooks 5003 self.suite = orig; 5004 fn(errSuite); 5005 } 5006 } 5007 5008 function next(err, errSuite) { 5009 // if we bail after first err 5010 if (self.failures && suite._bail) return fn(); 5011 5012 if (self._abort) return fn(); 5013 5014 if (err) return hookErr(err, errSuite, true); 5015 5016 // next test 5017 test = tests.shift(); 5018 5019 // all done 5020 if (!test) return fn(); 5021 5022 // grep 5023 var match = self._grep.test(test.fullTitle()); 5024 if (self._invert) match = !match; 5025 if (!match) return next(); 5026 5027 // pending 5028 if (test.pending) { 5029 self.emit('pending', test); 5030 self.emit('test end', test); 5031 return next(); 5032 } 5033 5034 // execute test and hook(s) 5035 self.emit('test', self.test = test); 5036 self.hookDown('beforeEach', function(err, errSuite){ 5037 5038 if (suite.pending) { 5039 self.emit('pending', test); 5040 self.emit('test end', test); 5041 return next(); 5042 } 5043 if (err) return hookErr(err, errSuite, false); 5044 5045 self.currentRunnable = self.test; 5046 self.runTest(function(err){ 5047 test = self.test; 5048 5049 if (err) { 5050 if (err instanceof Pending) { 5051 self.emit('pending', test); 5052 } else { 5053 self.fail(test, err); 5054 } 5055 self.emit('test end', test); 5056 5057 if (err instanceof Pending) { 5058 return next(); 5059 } 5060 5061 return self.hookUp('afterEach', next); 5062 } 5063 5064 test.state = 'passed'; 5065 self.emit('pass', test); 5066 self.emit('test end', test); 5067 self.hookUp('afterEach', next); 5068 }); 5069 }); 5070 } 5071 5072 this.next = next; 5073 next(); 5074}; 5075 5076/** 5077 * Run the given `suite` and invoke the 5078 * callback `fn()` when complete. 5079 * 5080 * @param {Suite} suite 5081 * @param {Function} fn 5082 * @api private 5083 */ 5084 5085Runner.prototype.runSuite = function(suite, fn){ 5086 var total = this.grepTotal(suite) 5087 , self = this 5088 , i = 0; 5089 5090 debug('run suite %s', suite.fullTitle()); 5091 5092 if (!total) return fn(); 5093 5094 this.emit('suite', this.suite = suite); 5095 5096 function next(errSuite) { 5097 if (errSuite) { 5098 // current suite failed on a hook from errSuite 5099 if (errSuite == suite) { 5100 // if errSuite is current suite 5101 // continue to the next sibling suite 5102 return done(); 5103 } else { 5104 // errSuite is among the parents of current suite 5105 // stop execution of errSuite and all sub-suites 5106 return done(errSuite); 5107 } 5108 } 5109 5110 if (self._abort) return done(); 5111 5112 var curr = suite.suites[i++]; 5113 if (!curr) return done(); 5114 self.runSuite(curr, next); 5115 } 5116 5117 function done(errSuite) { 5118 self.suite = suite; 5119 self.hook('afterAll', function(){ 5120 self.emit('suite end', suite); 5121 fn(errSuite); 5122 }); 5123 } 5124 5125 this.hook('beforeAll', function(err){ 5126 if (err) return done(); 5127 self.runTests(suite, next); 5128 }); 5129}; 5130 5131/** 5132 * Handle uncaught exceptions. 5133 * 5134 * @param {Error} err 5135 * @api private 5136 */ 5137 5138Runner.prototype.uncaught = function(err){ 5139 if (err) { 5140 debug('uncaught exception %s', err !== function () { 5141 return this; 5142 }.call(err) ? err : ( err.message || err )); 5143 } else { 5144 debug('uncaught undefined exception'); 5145 err = utils.undefinedError(); 5146 } 5147 err.uncaught = true; 5148 5149 var runnable = this.currentRunnable; 5150 if (!runnable) return; 5151 5152 runnable.clearTimeout(); 5153 5154 // Ignore errors if complete 5155 if (runnable.state) return; 5156 this.fail(runnable, err); 5157 5158 // recover from test 5159 if ('test' == runnable.type) { 5160 this.emit('test end', runnable); 5161 this.hookUp('afterEach', this.next); 5162 return; 5163 } 5164 5165 // bail on hooks 5166 this.emit('end'); 5167}; 5168 5169/** 5170 * Run the root suite and invoke `fn(failures)` 5171 * on completion. 5172 * 5173 * @param {Function} fn 5174 * @return {Runner} for chaining 5175 * @api public 5176 */ 5177 5178Runner.prototype.run = function(fn){ 5179 var self = this, 5180 rootSuite = this.suite; 5181 5182 fn = fn || function(){}; 5183 5184 function uncaught(err){ 5185 self.uncaught(err); 5186 } 5187 5188 function start() { 5189 self.emit('start'); 5190 self.runSuite(rootSuite, function(){ 5191 debug('finished running'); 5192 self.emit('end'); 5193 }); 5194 } 5195 5196 debug('start'); 5197 5198 // callback 5199 this.on('end', function(){ 5200 debug('end'); 5201 process.removeListener('uncaughtException', uncaught); 5202 fn(self.failures); 5203 }); 5204 5205 // uncaught exception 5206 process.on('uncaughtException', uncaught); 5207 5208 if (this._delay) { 5209 // for reporters, I guess. 5210 // might be nice to debounce some dots while we wait. 5211 this.emit('waiting', rootSuite); 5212 rootSuite.once('run', start); 5213 } 5214 else { 5215 start(); 5216 } 5217 5218 return this; 5219}; 5220 5221/** 5222 * Cleanly abort execution 5223 * 5224 * @return {Runner} for chaining 5225 * @api public 5226 */ 5227Runner.prototype.abort = function(){ 5228 debug('aborting'); 5229 this._abort = true; 5230}; 5231 5232/** 5233 * Filter leaks with the given globals flagged as `ok`. 5234 * 5235 * @param {Array} ok 5236 * @param {Array} globals 5237 * @return {Array} 5238 * @api private 5239 */ 5240 5241function filterLeaks(ok, globals) { 5242 return filter(globals, function(key){ 5243 // Firefox and Chrome exposes iframes as index inside the window object 5244 if (/^d+/.test(key)) return false; 5245 5246 // in firefox 5247 // if runner runs in an iframe, this iframe's window.getInterface method not init at first 5248 // it is assigned in some seconds 5249 if (global.navigator && /^getInterface/.test(key)) return false; 5250 5251 // an iframe could be approached by window[iframeIndex] 5252 // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak 5253 if (global.navigator && /^\d+/.test(key)) return false; 5254 5255 // Opera and IE expose global variables for HTML element IDs (issue #243) 5256 if (/^mocha-/.test(key)) return false; 5257 5258 var matched = filter(ok, function(ok){ 5259 if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); 5260 return key == ok; 5261 }); 5262 return matched.length == 0 && (!global.navigator || 'onerror' !== key); 5263 }); 5264} 5265 5266/** 5267 * Array of globals dependent on the environment. 5268 * 5269 * @return {Array} 5270 * @api private 5271 */ 5272 5273function extraGlobals() { 5274 if (typeof(process) === 'object' && 5275 typeof(process.version) === 'string') { 5276 5277 var nodeVersion = process.version.split('.').reduce(function(a, v) { 5278 return a << 8 | v; 5279 }); 5280 5281 // 'errno' was renamed to process._errno in v0.9.11. 5282 5283 if (nodeVersion < 0x00090B) { 5284 return ['errno']; 5285 } 5286 } 5287 5288 return []; 5289} 5290 5291}); // module: runner.js 5292 5293require.register("suite.js", function(module, exports, require){ 5294/** 5295 * Module dependencies. 5296 */ 5297 5298var EventEmitter = require('browser/events').EventEmitter 5299 , debug = require('browser/debug')('mocha:suite') 5300 , milliseconds = require('./ms') 5301 , utils = require('./utils') 5302 , Hook = require('./hook'); 5303 5304/** 5305 * Expose `Suite`. 5306 */ 5307 5308exports = module.exports = Suite; 5309 5310/** 5311 * Create a new `Suite` with the given `title` 5312 * and parent `Suite`. When a suite with the 5313 * same title is already present, that suite 5314 * is returned to provide nicer reporter 5315 * and more flexible meta-testing. 5316 * 5317 * @param {Suite} parent 5318 * @param {String} title 5319 * @return {Suite} 5320 * @api public 5321 */ 5322 5323exports.create = function(parent, title){ 5324 var suite = new Suite(title, parent.ctx); 5325 suite.parent = parent; 5326 if (parent.pending) suite.pending = true; 5327 title = suite.fullTitle(); 5328 parent.addSuite(suite); 5329 return suite; 5330}; 5331 5332/** 5333 * Initialize a new `Suite` with the given 5334 * `title` and `ctx`. 5335 * 5336 * @param {String} title 5337 * @param {Context} ctx 5338 * @api private 5339 */ 5340 5341function Suite(title, parentContext) { 5342 this.title = title; 5343 var context = function() {}; 5344 context.prototype = parentContext; 5345 this.ctx = new context(); 5346 this.suites = []; 5347 this.tests = []; 5348 this.pending = false; 5349 this._beforeEach = []; 5350 this._beforeAll = []; 5351 this._afterEach = []; 5352 this._afterAll = []; 5353 this.root = !title; 5354 this._timeout = 2000; 5355 this._enableTimeouts = true; 5356 this._slow = 75; 5357 this._bail = false; 5358 this.delayed = false; 5359} 5360 5361/** 5362 * Inherit from `EventEmitter.prototype`. 5363 */ 5364 5365function F(){}; 5366F.prototype = EventEmitter.prototype; 5367Suite.prototype = new F; 5368Suite.prototype.constructor = Suite; 5369 5370 5371/** 5372 * Return a clone of this `Suite`. 5373 * 5374 * @return {Suite} 5375 * @api private 5376 */ 5377 5378Suite.prototype.clone = function(){ 5379 var suite = new Suite(this.title); 5380 debug('clone'); 5381 suite.ctx = this.ctx; 5382 suite.timeout(this.timeout()); 5383 suite.enableTimeouts(this.enableTimeouts()); 5384 suite.slow(this.slow()); 5385 suite.bail(this.bail()); 5386 return suite; 5387}; 5388 5389/** 5390 * Set timeout `ms` or short-hand such as "2s". 5391 * 5392 * @param {Number|String} ms 5393 * @return {Suite|Number} for chaining 5394 * @api private 5395 */ 5396 5397Suite.prototype.timeout = function(ms){ 5398 if (0 == arguments.length) return this._timeout; 5399 if (ms.toString() === '0') this._enableTimeouts = false; 5400 if ('string' == typeof ms) ms = milliseconds(ms); 5401 debug('timeout %d', ms); 5402 this._timeout = parseInt(ms, 10); 5403 return this; 5404}; 5405 5406/** 5407 * Set timeout `enabled`. 5408 * 5409 * @param {Boolean} enabled 5410 * @return {Suite|Boolean} self or enabled 5411 * @api private 5412 */ 5413 5414Suite.prototype.enableTimeouts = function(enabled){ 5415 if (arguments.length === 0) return this._enableTimeouts; 5416 debug('enableTimeouts %s', enabled); 5417 this._enableTimeouts = enabled; 5418 return this; 5419}; 5420 5421/** 5422 * Set slow `ms` or short-hand such as "2s". 5423 * 5424 * @param {Number|String} ms 5425 * @return {Suite|Number} for chaining 5426 * @api private 5427 */ 5428 5429Suite.prototype.slow = function(ms){ 5430 if (0 === arguments.length) return this._slow; 5431 if ('string' == typeof ms) ms = milliseconds(ms); 5432 debug('slow %d', ms); 5433 this._slow = ms; 5434 return this; 5435}; 5436 5437/** 5438 * Sets whether to bail after first error. 5439 * 5440 * @param {Boolean} bail 5441 * @return {Suite|Number} for chaining 5442 * @api private 5443 */ 5444 5445Suite.prototype.bail = function(bail){ 5446 if (0 == arguments.length) return this._bail; 5447 debug('bail %s', bail); 5448 this._bail = bail; 5449 return this; 5450}; 5451 5452/** 5453 * Run `fn(test[, done])` before running tests. 5454 * 5455 * @param {Function} fn 5456 * @return {Suite} for chaining 5457 * @api private 5458 */ 5459 5460Suite.prototype.beforeAll = function(title, fn){ 5461 if (this.pending) return this; 5462 if ('function' === typeof title) { 5463 fn = title; 5464 title = fn.name; 5465 } 5466 title = '"before all" hook' + (title ? ': ' + title : ''); 5467 5468 var hook = new Hook(title, fn); 5469 hook.parent = this; 5470 hook.timeout(this.timeout()); 5471 hook.enableTimeouts(this.enableTimeouts()); 5472 hook.slow(this.slow()); 5473 hook.ctx = this.ctx; 5474 this._beforeAll.push(hook); 5475 this.emit('beforeAll', hook); 5476 return this; 5477}; 5478 5479/** 5480 * Run `fn(test[, done])` after running tests. 5481 * 5482 * @param {Function} fn 5483 * @return {Suite} for chaining 5484 * @api private 5485 */ 5486 5487Suite.prototype.afterAll = function(title, fn){ 5488 if (this.pending) return this; 5489 if ('function' === typeof title) { 5490 fn = title; 5491 title = fn.name; 5492 } 5493 title = '"after all" hook' + (title ? ': ' + title : ''); 5494 5495 var hook = new Hook(title, fn); 5496 hook.parent = this; 5497 hook.timeout(this.timeout()); 5498 hook.enableTimeouts(this.enableTimeouts()); 5499 hook.slow(this.slow()); 5500 hook.ctx = this.ctx; 5501 this._afterAll.push(hook); 5502 this.emit('afterAll', hook); 5503 return this; 5504}; 5505 5506/** 5507 * Run `fn(test[, done])` before each test case. 5508 * 5509 * @param {Function} fn 5510 * @return {Suite} for chaining 5511 * @api private 5512 */ 5513 5514Suite.prototype.beforeEach = function(title, fn){ 5515 if (this.pending) return this; 5516 if ('function' === typeof title) { 5517 fn = title; 5518 title = fn.name; 5519 } 5520 title = '"before each" hook' + (title ? ': ' + title : ''); 5521 5522 var hook = new Hook(title, fn); 5523 hook.parent = this; 5524 hook.timeout(this.timeout()); 5525 hook.enableTimeouts(this.enableTimeouts()); 5526 hook.slow(this.slow()); 5527 hook.ctx = this.ctx; 5528 this._beforeEach.push(hook); 5529 this.emit('beforeEach', hook); 5530 return this; 5531}; 5532 5533/** 5534 * Run `fn(test[, done])` after each test case. 5535 * 5536 * @param {Function} fn 5537 * @return {Suite} for chaining 5538 * @api private 5539 */ 5540 5541Suite.prototype.afterEach = function(title, fn){ 5542 if (this.pending) return this; 5543 if ('function' === typeof title) { 5544 fn = title; 5545 title = fn.name; 5546 } 5547 title = '"after each" hook' + (title ? ': ' + title : ''); 5548 5549 var hook = new Hook(title, fn); 5550 hook.parent = this; 5551 hook.timeout(this.timeout()); 5552 hook.enableTimeouts(this.enableTimeouts()); 5553 hook.slow(this.slow()); 5554 hook.ctx = this.ctx; 5555 this._afterEach.push(hook); 5556 this.emit('afterEach', hook); 5557 return this; 5558}; 5559 5560/** 5561 * Add a test `suite`. 5562 * 5563 * @param {Suite} suite 5564 * @return {Suite} for chaining 5565 * @api private 5566 */ 5567 5568Suite.prototype.addSuite = function(suite){ 5569 suite.parent = this; 5570 suite.timeout(this.timeout()); 5571 suite.enableTimeouts(this.enableTimeouts()); 5572 suite.slow(this.slow()); 5573 suite.bail(this.bail()); 5574 this.suites.push(suite); 5575 this.emit('suite', suite); 5576 return this; 5577}; 5578 5579/** 5580 * Add a `test` to this suite. 5581 * 5582 * @param {Test} test 5583 * @return {Suite} for chaining 5584 * @api private 5585 */ 5586 5587Suite.prototype.addTest = function(test){ 5588 test.parent = this; 5589 test.timeout(this.timeout()); 5590 test.enableTimeouts(this.enableTimeouts()); 5591 test.slow(this.slow()); 5592 test.ctx = this.ctx; 5593 this.tests.push(test); 5594 this.emit('test', test); 5595 return this; 5596}; 5597 5598/** 5599 * Return the full title generated by recursively 5600 * concatenating the parent's full title. 5601 * 5602 * @return {String} 5603 * @api public 5604 */ 5605 5606Suite.prototype.fullTitle = function(){ 5607 if (this.parent) { 5608 var full = this.parent.fullTitle(); 5609 if (full) return full + ' ' + this.title; 5610 } 5611 return this.title; 5612}; 5613 5614/** 5615 * Return the total number of tests. 5616 * 5617 * @return {Number} 5618 * @api public 5619 */ 5620 5621Suite.prototype.total = function(){ 5622 return utils.reduce(this.suites, function(sum, suite){ 5623 return sum + suite.total(); 5624 }, 0) + this.tests.length; 5625}; 5626 5627/** 5628 * Iterates through each suite recursively to find 5629 * all tests. Applies a function in the format 5630 * `fn(test)`. 5631 * 5632 * @param {Function} fn 5633 * @return {Suite} 5634 * @api private 5635 */ 5636 5637Suite.prototype.eachTest = function(fn){ 5638 utils.forEach(this.tests, fn); 5639 utils.forEach(this.suites, function(suite){ 5640 suite.eachTest(fn); 5641 }); 5642 return this; 5643}; 5644 5645/** 5646 * This will run the root suite if we happen to be running in delayed mode. 5647 */ 5648Suite.prototype.run = function run() { 5649 if (this.root) { 5650 this.emit('run'); 5651 } 5652}; 5653 5654}); // module: suite.js 5655 5656require.register("test.js", function(module, exports, require){ 5657/** 5658 * Module dependencies. 5659 */ 5660 5661var Runnable = require('./runnable'); 5662 5663/** 5664 * Expose `Test`. 5665 */ 5666 5667module.exports = Test; 5668 5669/** 5670 * Initialize a new `Test` with the given `title` and callback `fn`. 5671 * 5672 * @param {String} title 5673 * @param {Function} fn 5674 * @api private 5675 */ 5676 5677function Test(title, fn) { 5678 Runnable.call(this, title, fn); 5679 this.pending = !fn; 5680 this.type = 'test'; 5681} 5682 5683/** 5684 * Inherit from `Runnable.prototype`. 5685 */ 5686 5687function F(){}; 5688F.prototype = Runnable.prototype; 5689Test.prototype = new F; 5690Test.prototype.constructor = Test; 5691 5692 5693}); // module: test.js 5694 5695require.register("utils.js", function(module, exports, require){ 5696/** 5697 * Module dependencies. 5698 */ 5699 5700var fs = require('browser/fs') 5701 , path = require('browser/path') 5702 , basename = path.basename 5703 , exists = fs.existsSync || path.existsSync 5704 , glob = require('browser/glob') 5705 , join = path.join 5706 , debug = require('browser/debug')('mocha:watch'); 5707 5708/** 5709 * Ignored directories. 5710 */ 5711 5712var ignore = ['node_modules', '.git']; 5713 5714/** 5715 * Escape special characters in the given string of html. 5716 * 5717 * @param {String} html 5718 * @return {String} 5719 * @api private 5720 */ 5721 5722exports.escape = function(html){ 5723 return String(html) 5724 .replace(/&/g, '&') 5725 .replace(/"/g, '"') 5726 .replace(/</g, '<') 5727 .replace(/>/g, '>'); 5728}; 5729 5730/** 5731 * Array#forEach (<=IE8) 5732 * 5733 * @param {Array} array 5734 * @param {Function} fn 5735 * @param {Object} scope 5736 * @api private 5737 */ 5738 5739exports.forEach = function(arr, fn, scope){ 5740 for (var i = 0, l = arr.length; i < l; i++) 5741 fn.call(scope, arr[i], i); 5742}; 5743 5744/** 5745 * Array#map (<=IE8) 5746 * 5747 * @param {Array} array 5748 * @param {Function} fn 5749 * @param {Object} scope 5750 * @api private 5751 */ 5752 5753exports.map = function(arr, fn, scope){ 5754 var result = []; 5755 for (var i = 0, l = arr.length; i < l; i++) 5756 result.push(fn.call(scope, arr[i], i, arr)); 5757 return result; 5758}; 5759 5760/** 5761 * Array#indexOf (<=IE8) 5762 * 5763 * @parma {Array} arr 5764 * @param {Object} obj to find index of 5765 * @param {Number} start 5766 * @api private 5767 */ 5768 5769exports.indexOf = function(arr, obj, start){ 5770 for (var i = start || 0, l = arr.length; i < l; i++) { 5771 if (arr[i] === obj) 5772 return i; 5773 } 5774 return -1; 5775}; 5776 5777/** 5778 * Array#reduce (<=IE8) 5779 * 5780 * @param {Array} array 5781 * @param {Function} fn 5782 * @param {Object} initial value 5783 * @api private 5784 */ 5785 5786exports.reduce = function(arr, fn, val){ 5787 var rval = val; 5788 5789 for (var i = 0, l = arr.length; i < l; i++) { 5790 rval = fn(rval, arr[i], i, arr); 5791 } 5792 5793 return rval; 5794}; 5795 5796/** 5797 * Array#filter (<=IE8) 5798 * 5799 * @param {Array} array 5800 * @param {Function} fn 5801 * @api private 5802 */ 5803 5804exports.filter = function(arr, fn){ 5805 var ret = []; 5806 5807 for (var i = 0, l = arr.length; i < l; i++) { 5808 var val = arr[i]; 5809 if (fn(val, i, arr)) ret.push(val); 5810 } 5811 5812 return ret; 5813}; 5814 5815/** 5816 * Object.keys (<=IE8) 5817 * 5818 * @param {Object} obj 5819 * @return {Array} keys 5820 * @api private 5821 */ 5822 5823exports.keys = Object.keys || function(obj) { 5824 var keys = [] 5825 , has = Object.prototype.hasOwnProperty; // for `window` on <=IE8 5826 5827 for (var key in obj) { 5828 if (has.call(obj, key)) { 5829 keys.push(key); 5830 } 5831 } 5832 5833 return keys; 5834}; 5835 5836/** 5837 * Watch the given `files` for changes 5838 * and invoke `fn(file)` on modification. 5839 * 5840 * @param {Array} files 5841 * @param {Function} fn 5842 * @api private 5843 */ 5844 5845exports.watch = function(files, fn){ 5846 var options = { interval: 100 }; 5847 files.forEach(function(file){ 5848 debug('file %s', file); 5849 fs.watchFile(file, options, function(curr, prev){ 5850 if (prev.mtime < curr.mtime) fn(file); 5851 }); 5852 }); 5853}; 5854 5855/** 5856 * Array.isArray (<=IE8) 5857 * 5858 * @param {Object} obj 5859 * @return {Boolean} 5860 * @api private 5861 */ 5862var isArray = Array.isArray || function (obj) { 5863 return '[object Array]' == {}.toString.call(obj); 5864}; 5865 5866/** 5867 * @description 5868 * Buffer.prototype.toJSON polyfill 5869 * @type {Function} 5870 */ 5871if(typeof Buffer !== 'undefined' && Buffer.prototype) { 5872 Buffer.prototype.toJSON = Buffer.prototype.toJSON || function () { 5873 return Array.prototype.slice.call(this, 0); 5874 }; 5875} 5876 5877/** 5878 * Ignored files. 5879 */ 5880 5881function ignored(path){ 5882 return !~ignore.indexOf(path); 5883} 5884 5885/** 5886 * Lookup files in the given `dir`. 5887 * 5888 * @return {Array} 5889 * @api private 5890 */ 5891 5892exports.files = function(dir, ext, ret){ 5893 ret = ret || []; 5894 ext = ext || ['js']; 5895 5896 var re = new RegExp('\\.(' + ext.join('|') + ')$'); 5897 5898 fs.readdirSync(dir) 5899 .filter(ignored) 5900 .forEach(function(path){ 5901 path = join(dir, path); 5902 if (fs.statSync(path).isDirectory()) { 5903 exports.files(path, ext, ret); 5904 } else if (path.match(re)) { 5905 ret.push(path); 5906 } 5907 }); 5908 5909 return ret; 5910}; 5911 5912/** 5913 * Compute a slug from the given `str`. 5914 * 5915 * @param {String} str 5916 * @return {String} 5917 * @api private 5918 */ 5919 5920exports.slug = function(str){ 5921 return str 5922 .toLowerCase() 5923 .replace(/ +/g, '-') 5924 .replace(/[^-\w]/g, ''); 5925}; 5926 5927/** 5928 * Strip the function definition from `str`, 5929 * and re-indent for pre whitespace. 5930 */ 5931 5932exports.clean = function(str) { 5933 str = str 5934 .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '') 5935 .replace(/^function *\(.*\) *{|\(.*\) *=> *{?/, '') 5936 .replace(/\s+\}$/, ''); 5937 5938 var spaces = str.match(/^\n?( *)/)[1].length 5939 , tabs = str.match(/^\n?(\t*)/)[1].length 5940 , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm'); 5941 5942 str = str.replace(re, ''); 5943 5944 return exports.trim(str); 5945}; 5946 5947/** 5948 * Trim the given `str`. 5949 * 5950 * @param {String} str 5951 * @return {String} 5952 * @api private 5953 */ 5954 5955exports.trim = function(str){ 5956 return str.replace(/^\s+|\s+$/g, ''); 5957}; 5958 5959/** 5960 * Parse the given `qs`. 5961 * 5962 * @param {String} qs 5963 * @return {Object} 5964 * @api private 5965 */ 5966 5967exports.parseQuery = function(qs){ 5968 return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ 5969 var i = pair.indexOf('=') 5970 , key = pair.slice(0, i) 5971 , val = pair.slice(++i); 5972 5973 obj[key] = decodeURIComponent(val); 5974 return obj; 5975 }, {}); 5976}; 5977 5978/** 5979 * Highlight the given string of `js`. 5980 * 5981 * @param {String} js 5982 * @return {String} 5983 * @api private 5984 */ 5985 5986function highlight(js) { 5987 return js 5988 .replace(/</g, '<') 5989 .replace(/>/g, '>') 5990 .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>') 5991 .replace(/('.*?')/gm, '<span class="string">$1</span>') 5992 .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>') 5993 .replace(/(\d+)/gm, '<span class="number">$1</span>') 5994 .replace(/\bnew[ \t]+(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>') 5995 .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>') 5996} 5997 5998/** 5999 * Highlight the contents of tag `name`. 6000 * 6001 * @param {String} name 6002 * @api private 6003 */ 6004 6005exports.highlightTags = function(name) { 6006 var code = document.getElementById('mocha').getElementsByTagName(name); 6007 for (var i = 0, len = code.length; i < len; ++i) { 6008 code[i].innerHTML = highlight(code[i].innerHTML); 6009 } 6010}; 6011 6012/** 6013 * If a value could have properties, and has none, this function is called, which returns 6014 * a string representation of the empty value. 6015 * 6016 * Functions w/ no properties return `'[Function]'` 6017 * Arrays w/ length === 0 return `'[]'` 6018 * Objects w/ no properties return `'{}'` 6019 * All else: return result of `value.toString()` 6020 * 6021 * @param {*} value Value to inspect 6022 * @param {string} [type] The type of the value, if known. 6023 * @returns {string} 6024 */ 6025var emptyRepresentation = function emptyRepresentation(value, type) { 6026 type = type || exports.type(value); 6027 6028 switch(type) { 6029 case 'function': 6030 return '[Function]'; 6031 case 'object': 6032 return '{}'; 6033 case 'array': 6034 return '[]'; 6035 default: 6036 return value.toString(); 6037 } 6038}; 6039 6040/** 6041 * Takes some variable and asks `{}.toString()` what it thinks it is. 6042 * @param {*} value Anything 6043 * @example 6044 * type({}) // 'object' 6045 * type([]) // 'array' 6046 * type(1) // 'number' 6047 * type(false) // 'boolean' 6048 * type(Infinity) // 'number' 6049 * type(null) // 'null' 6050 * type(new Date()) // 'date' 6051 * type(/foo/) // 'regexp' 6052 * type('type') // 'string' 6053 * type(global) // 'global' 6054 * @api private 6055 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString 6056 * @returns {string} 6057 */ 6058exports.type = function type(value) { 6059 if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { 6060 return 'buffer'; 6061 } 6062 return Object.prototype.toString.call(value) 6063 .replace(/^\[.+\s(.+?)\]$/, '$1') 6064 .toLowerCase(); 6065}; 6066 6067/** 6068 * @summary Stringify `value`. 6069 * @description Different behavior depending on type of value. 6070 * - If `value` is undefined or null, return `'[undefined]'` or `'[null]'`, respectively. 6071 * - If `value` is not an object, function or array, return result of `value.toString()` wrapped in double-quotes. 6072 * - If `value` is an *empty* object, function, or array, return result of function 6073 * {@link emptyRepresentation}. 6074 * - If `value` has properties, call {@link exports.canonicalize} on it, then return result of 6075 * JSON.stringify(). 6076 * 6077 * @see exports.type 6078 * @param {*} value 6079 * @return {string} 6080 * @api private 6081 */ 6082 6083exports.stringify = function(value) { 6084 var type = exports.type(value); 6085 6086 if (!~exports.indexOf(['object', 'array', 'function'], type)) { 6087 if(type != 'buffer') { 6088 return jsonStringify(value); 6089 } 6090 var json = value.toJSON(); 6091 // Based on the toJSON result 6092 return jsonStringify(json.data && json.type ? json.data : json, 2) 6093 .replace(/,(\n|$)/g, '$1'); 6094 } 6095 6096 for (var prop in value) { 6097 if (Object.prototype.hasOwnProperty.call(value, prop)) { 6098 return jsonStringify(exports.canonicalize(value), 2).replace(/,(\n|$)/g, '$1'); 6099 } 6100 } 6101 6102 return emptyRepresentation(value, type); 6103}; 6104 6105/** 6106 * @description 6107 * like JSON.stringify but more sense. 6108 * @param {Object} object 6109 * @param {Number=} spaces 6110 * @param {number=} depth 6111 * @returns {*} 6112 * @private 6113 */ 6114function jsonStringify(object, spaces, depth) { 6115 if(typeof spaces == 'undefined') return _stringify(object); // primitive types 6116 6117 depth = depth || 1; 6118 var space = spaces * depth 6119 , str = isArray(object) ? '[' : '{' 6120 , end = isArray(object) ? ']' : '}' 6121 , length = object.length || exports.keys(object).length 6122 , repeat = function(s, n) { return new Array(n).join(s); }; // `.repeat()` polyfill 6123 6124 function _stringify(val) { 6125 switch (exports.type(val)) { 6126 case 'null': 6127 case 'undefined': 6128 val = '[' + val + ']'; 6129 break; 6130 case 'array': 6131 case 'object': 6132 val = jsonStringify(val, spaces, depth + 1); 6133 break; 6134 case 'boolean': 6135 case 'regexp': 6136 case 'number': 6137 val = val === 0 && (1/val) === -Infinity // `-0` 6138 ? '-0' 6139 : val.toString(); 6140 break; 6141 case 'date': 6142 val = '[Date: ' + val.toISOString() + ']'; 6143 break; 6144 case 'buffer': 6145 var json = val.toJSON(); 6146 // Based on the toJSON result 6147 json = json.data && json.type ? json.data : json; 6148 val = '[Buffer: ' + jsonStringify(json, 2, depth + 1) + ']'; 6149 break; 6150 default: 6151 val = (val == '[Function]' || val == '[Circular]') 6152 ? val 6153 : '"' + val + '"'; //string 6154 } 6155 return val; 6156 } 6157 6158 for(var i in object) { 6159 if(!object.hasOwnProperty(i)) continue; // not my business 6160 --length; 6161 str += '\n ' + repeat(' ', space) 6162 + (isArray(object) ? '' : '"' + i + '": ') // key 6163 + _stringify(object[i]) // value 6164 + (length ? ',' : ''); // comma 6165 } 6166 6167 return str + (str.length != 1 // [], {} 6168 ? '\n' + repeat(' ', --space) + end 6169 : end); 6170} 6171 6172/** 6173 * Return if obj is a Buffer 6174 * @param {Object} arg 6175 * @return {Boolean} 6176 * @api private 6177 */ 6178exports.isBuffer = function (arg) { 6179 return typeof Buffer !== 'undefined' && Buffer.isBuffer(arg); 6180}; 6181 6182/** 6183 * @summary Return a new Thing that has the keys in sorted order. Recursive. 6184 * @description If the Thing... 6185 * - has already been seen, return string `'[Circular]'` 6186 * - is `undefined`, return string `'[undefined]'` 6187 * - is `null`, return value `null` 6188 * - is some other primitive, return the value 6189 * - is not a primitive or an `Array`, `Object`, or `Function`, return the value of the Thing's `toString()` method 6190 * - is a non-empty `Array`, `Object`, or `Function`, return the result of calling this function again. 6191 * - is an empty `Array`, `Object`, or `Function`, return the result of calling `emptyRepresentation()` 6192 * 6193 * @param {*} value Thing to inspect. May or may not have properties. 6194 * @param {Array} [stack=[]] Stack of seen values 6195 * @return {(Object|Array|Function|string|undefined)} 6196 * @see {@link exports.stringify} 6197 * @api private 6198 */ 6199 6200exports.canonicalize = function(value, stack) { 6201 var canonicalizedObj, 6202 type = exports.type(value), 6203 prop, 6204 withStack = function withStack(value, fn) { 6205 stack.push(value); 6206 fn(); 6207 stack.pop(); 6208 }; 6209 6210 stack = stack || []; 6211 6212 if (exports.indexOf(stack, value) !== -1) { 6213 return '[Circular]'; 6214 } 6215 6216 switch(type) { 6217 case 'undefined': 6218 case 'buffer': 6219 case 'null': 6220 canonicalizedObj = value; 6221 break; 6222 case 'array': 6223 withStack(value, function () { 6224 canonicalizedObj = exports.map(value, function (item) { 6225 return exports.canonicalize(item, stack); 6226 }); 6227 }); 6228 break; 6229 case 'function': 6230 for (prop in value) { 6231 canonicalizedObj = {}; 6232 break; 6233 } 6234 if (!canonicalizedObj) { 6235 canonicalizedObj = emptyRepresentation(value, type); 6236 break; 6237 } 6238 /* falls through */ 6239 case 'object': 6240 canonicalizedObj = canonicalizedObj || {}; 6241 withStack(value, function () { 6242 exports.forEach(exports.keys(value).sort(), function (key) { 6243 canonicalizedObj[key] = exports.canonicalize(value[key], stack); 6244 }); 6245 }); 6246 break; 6247 case 'date': 6248 case 'number': 6249 case 'regexp': 6250 case 'boolean': 6251 canonicalizedObj = value; 6252 break; 6253 default: 6254 canonicalizedObj = value.toString(); 6255 } 6256 6257 return canonicalizedObj; 6258}; 6259 6260/** 6261 * Lookup file names at the given `path`. 6262 */ 6263exports.lookupFiles = function lookupFiles(path, extensions, recursive) { 6264 var files = []; 6265 var re = new RegExp('\\.(' + extensions.join('|') + ')$'); 6266 6267 if (!exists(path)) { 6268 if (exists(path + '.js')) { 6269 path += '.js'; 6270 } else { 6271 files = glob.sync(path); 6272 if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'"); 6273 return files; 6274 } 6275 } 6276 6277 try { 6278 var stat = fs.statSync(path); 6279 if (stat.isFile()) return path; 6280 } 6281 catch (ignored) { 6282 return; 6283 } 6284 6285 fs.readdirSync(path).forEach(function(file) { 6286 file = join(path, file); 6287 try { 6288 var stat = fs.statSync(file); 6289 if (stat.isDirectory()) { 6290 if (recursive) { 6291 files = files.concat(lookupFiles(file, extensions, recursive)); 6292 } 6293 return; 6294 } 6295 } 6296 catch (ignored) { 6297 return; 6298 } 6299 if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return; 6300 files.push(file); 6301 }); 6302 6303 return files; 6304}; 6305 6306/** 6307 * Generate an undefined error with a message warning the user. 6308 * 6309 * @return {Error} 6310 */ 6311 6312exports.undefinedError = function() { 6313 return new Error('Caught undefined error, did you throw without specifying what?'); 6314}; 6315 6316/** 6317 * Generate an undefined error if `err` is not defined. 6318 * 6319 * @param {Error} err 6320 * @return {Error} 6321 */ 6322 6323exports.getError = function(err) { 6324 return err || exports.undefinedError(); 6325}; 6326 6327 6328/** 6329 * @summary 6330 * This Filter based on `mocha-clean` module.(see: `github.com/rstacruz/mocha-clean`) 6331 * @description 6332 * When invoking this function you get a filter function that get the Error.stack as an input, 6333 * and return a prettify output. 6334 * (i.e: strip Mocha, node_modules, bower and componentJS from stack trace). 6335 * @returns {Function} 6336 */ 6337 6338exports.stackTraceFilter = function() { 6339 var slash = '/' 6340 , is = typeof document === 'undefined' 6341 ? { node: true } 6342 : { browser: true } 6343 , cwd = is.node 6344 ? process.cwd() + slash 6345 : location.href.replace(/\/[^\/]*$/, '/'); 6346 6347 function isNodeModule (line) { 6348 return (~line.indexOf('node_modules')); 6349 } 6350 6351 function isMochaInternal (line) { 6352 return (~line.indexOf('node_modules' + slash + 'mocha')) || 6353 (~line.indexOf('components' + slash + 'mochajs')) || 6354 (~line.indexOf('components' + slash + 'mocha')); 6355 } 6356 6357 // node_modules, bower, componentJS 6358 function isBrowserModule(line) { 6359 return (~line.indexOf('node_modules')) || 6360 (~line.indexOf('components')); 6361 } 6362 6363 function isNodeInternal (line) { 6364 return (~line.indexOf('(timers.js:')) || 6365 (~line.indexOf('(events.js:')) || 6366 (~line.indexOf('(node.js:')) || 6367 (~line.indexOf('(module.js:')) || 6368 (~line.indexOf('GeneratorFunctionPrototype.next (native)')) || 6369 false 6370 } 6371 6372 return function(stack) { 6373 stack = stack.split('\n'); 6374 6375 stack = stack.reduce(function (list, line) { 6376 if (is.node && (isNodeModule(line) || 6377 isMochaInternal(line) || 6378 isNodeInternal(line))) 6379 return list; 6380 6381 if (is.browser && (isBrowserModule(line))) 6382 return list; 6383 6384 // Clean up cwd(absolute) 6385 list.push(line.replace(cwd, '')); 6386 return list; 6387 }, []); 6388 6389 return stack.join('\n'); 6390 } 6391}; 6392}); // module: utils.js 6393// The global object is "self" in Web Workers. 6394var global = (function() { return this; })(); 6395 6396/** 6397 * Save timer references to avoid Sinon interfering (see GH-237). 6398 */ 6399 6400var Date = global.Date; 6401var setTimeout = global.setTimeout; 6402var setInterval = global.setInterval; 6403var clearTimeout = global.clearTimeout; 6404var clearInterval = global.clearInterval; 6405 6406/** 6407 * Node shims. 6408 * 6409 * These are meant only to allow 6410 * mocha.js to run untouched, not 6411 * to allow running node code in 6412 * the browser. 6413 */ 6414 6415var process = {}; 6416process.exit = function(status){}; 6417process.stdout = {}; 6418 6419var uncaughtExceptionHandlers = []; 6420 6421var originalOnerrorHandler = global.onerror; 6422 6423/** 6424 * Remove uncaughtException listener. 6425 * Revert to original onerror handler if previously defined. 6426 */ 6427 6428process.removeListener = function(e, fn){ 6429 if ('uncaughtException' == e) { 6430 if (originalOnerrorHandler) { 6431 global.onerror = originalOnerrorHandler; 6432 } else { 6433 global.onerror = function() {}; 6434 } 6435 var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn); 6436 if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); } 6437 } 6438}; 6439 6440/** 6441 * Implements uncaughtException listener. 6442 */ 6443 6444process.on = function(e, fn){ 6445 if ('uncaughtException' == e) { 6446 global.onerror = function(err, url, line){ 6447 fn(new Error(err + ' (' + url + ':' + line + ')')); 6448 return true; 6449 }; 6450 uncaughtExceptionHandlers.push(fn); 6451 } 6452}; 6453 6454/** 6455 * Expose mocha. 6456 */ 6457 6458var Mocha = global.Mocha = require('mocha'), 6459 mocha = global.mocha = new Mocha({ reporter: 'html' }); 6460 6461// The BDD UI is registered by default, but no UI will be functional in the 6462// browser without an explicit call to the overridden `mocha.ui` (see below). 6463// Ensure that this default UI does not expose its methods to the global scope. 6464mocha.suite.removeAllListeners('pre-require'); 6465 6466var immediateQueue = [] 6467 , immediateTimeout; 6468 6469function timeslice() { 6470 var immediateStart = new Date().getTime(); 6471 while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) { 6472 immediateQueue.shift()(); 6473 } 6474 if (immediateQueue.length) { 6475 immediateTimeout = setTimeout(timeslice, 0); 6476 } else { 6477 immediateTimeout = null; 6478 } 6479} 6480 6481/** 6482 * High-performance override of Runner.immediately. 6483 */ 6484 6485Mocha.Runner.immediately = function(callback) { 6486 immediateQueue.push(callback); 6487 if (!immediateTimeout) { 6488 immediateTimeout = setTimeout(timeslice, 0); 6489 } 6490}; 6491 6492/** 6493 * Function to allow assertion libraries to throw errors directly into mocha. 6494 * This is useful when running tests in a browser because window.onerror will 6495 * only receive the 'message' attribute of the Error. 6496 */ 6497mocha.throwError = function(err) { 6498 Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) { 6499 fn(err); 6500 }); 6501 throw err; 6502}; 6503 6504/** 6505 * Override ui to ensure that the ui functions are initialized. 6506 * Normally this would happen in Mocha.prototype.loadFiles. 6507 */ 6508 6509mocha.ui = function(ui){ 6510 Mocha.prototype.ui.call(this, ui); 6511 this.suite.emit('pre-require', global, null, this); 6512 return this; 6513}; 6514 6515/** 6516 * Setup mocha with the given setting options. 6517 */ 6518 6519mocha.setup = function(opts){ 6520 if ('string' == typeof opts) opts = { ui: opts }; 6521 for (var opt in opts) { 6522 if (opts.hasOwnProperty(opt)) { 6523 this[opt](opts[opt]); 6524 } 6525 } 6526 return this; 6527}; 6528 6529/** 6530 * Run mocha, returning the Runner. 6531 */ 6532 6533mocha.run = function(fn){ 6534 var options = mocha.options; 6535 mocha.globals('location'); 6536 6537 var query = Mocha.utils.parseQuery(global.location.search || ''); 6538 if (query.grep) mocha.grep(new RegExp(query.grep)); 6539 if (query.fgrep) mocha.grep(query.fgrep); 6540 if (query.invert) mocha.invert(); 6541 6542 return Mocha.prototype.run.call(mocha, function(err){ 6543 // The DOM Document is not available in Web Workers. 6544 var document = global.document; 6545 if (document && document.getElementById('mocha') && options.noHighlighting !== true) { 6546 Mocha.utils.highlightTags('code'); 6547 } 6548 if (fn) fn(err); 6549 }); 6550}; 6551 6552/** 6553 * Expose the process shim. 6554 */ 6555 6556Mocha.process = process; 6557})(); 6558