forked from sheetjs/sheetjs
		
	
		
			
	
	
		
			5555 lines
		
	
	
		
			113 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			5555 lines
		
	
	
		
			113 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | ;(function(){ | |||
|  | 
 | |||
|  | // CommonJS require()
 | |||
|  | 
 | |||
|  | function require(p){ | |||
|  |     var path = require.resolve(p) | |||
|  |       , mod = require.modules[path]; | |||
|  |     if (!mod) throw new Error('failed to require "' + p + '"'); | |||
|  |     if (!mod.exports) { | |||
|  |       mod.exports = {}; | |||
|  |       mod.call(mod.exports, mod, mod.exports, require.relative(path)); | |||
|  |     } | |||
|  |     return mod.exports; | |||
|  |   } | |||
|  | 
 | |||
|  | require.modules = {}; | |||
|  | 
 | |||
|  | require.resolve = function (path){ | |||
|  |     var orig = path | |||
|  |       , reg = path + '.js' | |||
|  |       , index = path + '/index.js'; | |||
|  |     return require.modules[reg] && reg | |||
|  |       || require.modules[index] && index | |||
|  |       || orig; | |||
|  |   }; | |||
|  | 
 | |||
|  | require.register = function (path, fn){ | |||
|  |     require.modules[path] = fn; | |||
|  |   }; | |||
|  | 
 | |||
|  | require.relative = function (parent) { | |||
|  |     return function(p){ | |||
|  |       if ('.' != p.charAt(0)) return require(p); | |||
|  | 
 | |||
|  |       var path = parent.split('/') | |||
|  |         , segs = p.split('/'); | |||
|  |       path.pop(); | |||
|  | 
 | |||
|  |       for (var i = 0; i < segs.length; i++) { | |||
|  |         var seg = segs[i]; | |||
|  |         if ('..' == seg) path.pop(); | |||
|  |         else if ('.' != seg) path.push(seg); | |||
|  |       } | |||
|  | 
 | |||
|  |       return require(path.join('/')); | |||
|  |     }; | |||
|  |   }; | |||
|  | 
 | |||
|  | 
 | |||
|  | require.register("browser/debug.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | module.exports = function(type){ | |||
|  |   return function(){ | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: browser/debug.js
 | |||
|  | 
 | |||
|  | require.register("browser/diff.js", function(module, exports, require){ | |||
|  | /* See LICENSE file for terms of use */ | |||
|  | 
 | |||
|  | /* | |||
|  |  * Text diff implementation. | |||
|  |  * | |||
|  |  * This library supports the following APIS: | |||
|  |  * JsDiff.diffChars: Character by character diff | |||
|  |  * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace | |||
|  |  * JsDiff.diffLines: Line based diff | |||
|  |  * | |||
|  |  * JsDiff.diffCss: Diff targeted at CSS content | |||
|  |  * | |||
|  |  * These methods are based on the implementation proposed in | |||
|  |  * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). | |||
|  |  * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
 | |||
|  |  */ | |||
|  | var JsDiff = (function() { | |||
|  |   /*jshint maxparams: 5*/ | |||
|  |   function clonePath(path) { | |||
|  |     return { newPos: path.newPos, components: path.components.slice(0) }; | |||
|  |   } | |||
|  |   function removeEmpty(array) { | |||
|  |     var ret = []; | |||
|  |     for (var i = 0; i < array.length; i++) { | |||
|  |       if (array[i]) { | |||
|  |         ret.push(array[i]); | |||
|  |       } | |||
|  |     } | |||
|  |     return ret; | |||
|  |   } | |||
|  |   function escapeHTML(s) { | |||
|  |     var n = s; | |||
|  |     n = n.replace(/&/g, '&'); | |||
|  |     n = n.replace(/</g, '<'); | |||
|  |     n = n.replace(/>/g, '>'); | |||
|  |     n = n.replace(/"/g, '"'); | |||
|  | 
 | |||
|  |     return n; | |||
|  |   } | |||
|  | 
 | |||
|  |   var Diff = function(ignoreWhitespace) { | |||
|  |     this.ignoreWhitespace = ignoreWhitespace; | |||
|  |   }; | |||
|  |   Diff.prototype = { | |||
|  |       diff: function(oldString, newString) { | |||
|  |         // Handle the identity case (this is due to unrolling editLength == 0
 | |||
|  |         if (newString === oldString) { | |||
|  |           return [{ value: newString }]; | |||
|  |         } | |||
|  |         if (!newString) { | |||
|  |           return [{ value: oldString, removed: true }]; | |||
|  |         } | |||
|  |         if (!oldString) { | |||
|  |           return [{ value: newString, added: true }]; | |||
|  |         } | |||
|  | 
 | |||
|  |         newString = this.tokenize(newString); | |||
|  |         oldString = this.tokenize(oldString); | |||
|  | 
 | |||
|  |         var newLen = newString.length, oldLen = oldString.length; | |||
|  |         var maxEditLength = newLen + oldLen; | |||
|  |         var bestPath = [{ newPos: -1, components: [] }]; | |||
|  | 
 | |||
|  |         // Seed editLength = 0
 | |||
|  |         var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); | |||
|  |         if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) { | |||
|  |           return bestPath[0].components; | |||
|  |         } | |||
|  | 
 | |||
|  |         for (var editLength = 1; editLength <= maxEditLength; editLength++) { | |||
|  |           for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) { | |||
|  |             var basePath; | |||
|  |             var addPath = bestPath[diagonalPath-1], | |||
|  |                 removePath = bestPath[diagonalPath+1]; | |||
|  |             oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; | |||
|  |             if (addPath) { | |||
|  |               // No one else is going to attempt to use this value, clear it
 | |||
|  |               bestPath[diagonalPath-1] = undefined; | |||
|  |             } | |||
|  | 
 | |||
|  |             var canAdd = addPath && addPath.newPos+1 < newLen; | |||
|  |             var canRemove = removePath && 0 <= oldPos && oldPos < oldLen; | |||
|  |             if (!canAdd && !canRemove) { | |||
|  |               bestPath[diagonalPath] = undefined; | |||
|  |               continue; | |||
|  |             } | |||
|  | 
 | |||
|  |             // Select the diagonal that we want to branch from. We select the prior
 | |||
|  |             // path whose position in the new string is the farthest from the origin
 | |||
|  |             // and does not pass the bounds of the diff graph
 | |||
|  |             if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { | |||
|  |               basePath = clonePath(removePath); | |||
|  |               this.pushComponent(basePath.components, oldString[oldPos], undefined, true); | |||
|  |             } else { | |||
|  |               basePath = clonePath(addPath); | |||
|  |               basePath.newPos++; | |||
|  |               this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined); | |||
|  |             } | |||
|  | 
 | |||
|  |             var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath); | |||
|  | 
 | |||
|  |             if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) { | |||
|  |               return basePath.components; | |||
|  |             } else { | |||
|  |               bestPath[diagonalPath] = basePath; | |||
|  |             } | |||
|  |           } | |||
|  |         } | |||
|  |       }, | |||
|  | 
 | |||
|  |       pushComponent: function(components, value, added, removed) { | |||
|  |         var last = components[components.length-1]; | |||
|  |         if (last && last.added === added && last.removed === removed) { | |||
|  |           // We need to clone here as the component clone operation is just
 | |||
|  |           // as shallow array clone
 | |||
|  |           components[components.length-1] = | |||
|  |             {value: this.join(last.value, value), added: added, removed: removed }; | |||
|  |         } else { | |||
|  |           components.push({value: value, added: added, removed: removed }); | |||
|  |         } | |||
|  |       }, | |||
|  |       extractCommon: function(basePath, newString, oldString, diagonalPath) { | |||
|  |         var newLen = newString.length, | |||
|  |             oldLen = oldString.length, | |||
|  |             newPos = basePath.newPos, | |||
|  |             oldPos = newPos - diagonalPath; | |||
|  |         while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) { | |||
|  |           newPos++; | |||
|  |           oldPos++; | |||
|  | 
 | |||
|  |           this.pushComponent(basePath.components, newString[newPos], undefined, undefined); | |||
|  |         } | |||
|  |         basePath.newPos = newPos; | |||
|  |         return oldPos; | |||
|  |       }, | |||
|  | 
 | |||
|  |       equals: function(left, right) { | |||
|  |         var reWhitespace = /\S/; | |||
|  |         if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) { | |||
|  |           return true; | |||
|  |         } else { | |||
|  |           return left === right; | |||
|  |         } | |||
|  |       }, | |||
|  |       join: function(left, right) { | |||
|  |         return left + right; | |||
|  |       }, | |||
|  |       tokenize: function(value) { | |||
|  |         return value; | |||
|  |       } | |||
|  |   }; | |||
|  | 
 | |||
|  |   var CharDiff = new Diff(); | |||
|  | 
 | |||
|  |   var WordDiff = new Diff(true); | |||
|  |   var WordWithSpaceDiff = new Diff(); | |||
|  |   WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) { | |||
|  |     return removeEmpty(value.split(/(\s+|\b)/)); | |||
|  |   }; | |||
|  | 
 | |||
|  |   var CssDiff = new Diff(true); | |||
|  |   CssDiff.tokenize = function(value) { | |||
|  |     return removeEmpty(value.split(/([{}:;,]|\s+)/)); | |||
|  |   }; | |||
|  | 
 | |||
|  |   var LineDiff = new Diff(); | |||
|  |   LineDiff.tokenize = function(value) { | |||
|  |     return value.split(/^/m); | |||
|  |   }; | |||
|  | 
 | |||
|  |   return { | |||
|  |     Diff: Diff, | |||
|  | 
 | |||
|  |     diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); }, | |||
|  |     diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); }, | |||
|  |     diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); }, | |||
|  |     diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); }, | |||
|  | 
 | |||
|  |     diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); }, | |||
|  | 
 | |||
|  |     createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { | |||
|  |       var ret = []; | |||
|  | 
 | |||
|  |       ret.push('Index: ' + fileName); | |||
|  |       ret.push('==================================================================='); | |||
|  |       ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader)); | |||
|  |       ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader)); | |||
|  | 
 | |||
|  |       var diff = LineDiff.diff(oldStr, newStr); | |||
|  |       if (!diff[diff.length-1].value) { | |||
|  |         diff.pop();   // Remove trailing newline add
 | |||
|  |       } | |||
|  |       diff.push({value: '', lines: []});   // Append an empty value to make cleanup easier
 | |||
|  | 
 | |||
|  |       function contextLines(lines) { | |||
|  |         return lines.map(function(entry) { return ' ' + entry; }); | |||
|  |       } | |||
|  |       function eofNL(curRange, i, current) { | |||
|  |         var last = diff[diff.length-2], | |||
|  |             isLast = i === diff.length-2, | |||
|  |             isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed); | |||
|  | 
 | |||
|  |         // Figure out if this is the last line for the given file and missing NL
 | |||
|  |         if (!/\n$/.test(current.value) && (isLast || isLastOfType)) { | |||
|  |           curRange.push('\\ No newline at end of file'); | |||
|  |         } | |||
|  |       } | |||
|  | 
 | |||
|  |       var oldRangeStart = 0, newRangeStart = 0, curRange = [], | |||
|  |           oldLine = 1, newLine = 1; | |||
|  |       for (var i = 0; i < diff.length; i++) { | |||
|  |         var current = diff[i], | |||
|  |             lines = current.lines || current.value.replace(/\n$/, '').split('\n'); | |||
|  |         current.lines = lines; | |||
|  | 
 | |||
|  |         if (current.added || current.removed) { | |||
|  |           if (!oldRangeStart) { | |||
|  |             var prev = diff[i-1]; | |||
|  |             oldRangeStart = oldLine; | |||
|  |             newRangeStart = newLine; | |||
|  | 
 | |||
|  |             if (prev) { | |||
|  |               curRange = contextLines(prev.lines.slice(-4)); | |||
|  |               oldRangeStart -= curRange.length; | |||
|  |               newRangeStart -= curRange.length; | |||
|  |             } | |||
|  |           } | |||
|  |           curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; })); | |||
|  |           eofNL(curRange, i, current); | |||
|  | 
 | |||
|  |           if (current.added) { | |||
|  |             newLine += lines.length; | |||
|  |           } else { | |||
|  |             oldLine += lines.length; | |||
|  |           } | |||
|  |         } else { | |||
|  |           if (oldRangeStart) { | |||
|  |             // Close out any changes that have been output (or join overlapping)
 | |||
|  |             if (lines.length <= 8 && i < diff.length-2) { | |||
|  |               // Overlapping
 | |||
|  |               curRange.push.apply(curRange, contextLines(lines)); | |||
|  |             } else { | |||
|  |               // end the range and output
 | |||
|  |               var contextSize = Math.min(lines.length, 4); | |||
|  |               ret.push( | |||
|  |                   '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize) | |||
|  |                   + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize) | |||
|  |                   + ' @@'); | |||
|  |               ret.push.apply(ret, curRange); | |||
|  |               ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); | |||
|  |               if (lines.length <= 4) { | |||
|  |                 eofNL(ret, i, current); | |||
|  |               } | |||
|  | 
 | |||
|  |               oldRangeStart = 0;  newRangeStart = 0; curRange = []; | |||
|  |             } | |||
|  |           } | |||
|  |           oldLine += lines.length; | |||
|  |           newLine += lines.length; | |||
|  |         } | |||
|  |       } | |||
|  | 
 | |||
|  |       return ret.join('\n') + '\n'; | |||
|  |     }, | |||
|  | 
 | |||
|  |     applyPatch: function(oldStr, uniDiff) { | |||
|  |       var diffstr = uniDiff.split('\n'); | |||
|  |       var diff = []; | |||
|  |       var remEOFNL = false, | |||
|  |           addEOFNL = false; | |||
|  | 
 | |||
|  |       for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) { | |||
|  |         if(diffstr[i][0] === '@') { | |||
|  |           var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/); | |||
|  |           diff.unshift({ | |||
|  |             start:meh[3], | |||
|  |             oldlength:meh[2], | |||
|  |             oldlines:[], | |||
|  |             newlength:meh[4], | |||
|  |             newlines:[] | |||
|  |           }); | |||
|  |         } else if(diffstr[i][0] === '+') { | |||
|  |           diff[0].newlines.push(diffstr[i].substr(1)); | |||
|  |         } else if(diffstr[i][0] === '-') { | |||
|  |           diff[0].oldlines.push(diffstr[i].substr(1)); | |||
|  |         } else if(diffstr[i][0] === ' ') { | |||
|  |           diff[0].newlines.push(diffstr[i].substr(1)); | |||
|  |           diff[0].oldlines.push(diffstr[i].substr(1)); | |||
|  |         } else if(diffstr[i][0] === '\\') { | |||
|  |           if (diffstr[i-1][0] === '+') { | |||
|  |             remEOFNL = true; | |||
|  |           } else if(diffstr[i-1][0] === '-') { | |||
|  |             addEOFNL = true; | |||
|  |           } | |||
|  |         } | |||
|  |       } | |||
|  | 
 | |||
|  |       var str = oldStr.split('\n'); | |||
|  |       for (var i = diff.length - 1; i >= 0; i--) { | |||
|  |         var d = diff[i]; | |||
|  |         for (var j = 0; j < d.oldlength; j++) { | |||
|  |           if(str[d.start-1+j] !== d.oldlines[j]) { | |||
|  |             return false; | |||
|  |           } | |||
|  |         } | |||
|  |         Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines)); | |||
|  |       } | |||
|  | 
 | |||
|  |       if (remEOFNL) { | |||
|  |         while (!str[str.length-1]) { | |||
|  |           str.pop(); | |||
|  |         } | |||
|  |       } else if (addEOFNL) { | |||
|  |         str.push(''); | |||
|  |       } | |||
|  |       return str.join('\n'); | |||
|  |     }, | |||
|  | 
 | |||
|  |     convertChangesToXML: function(changes){ | |||
|  |       var ret = []; | |||
|  |       for ( var i = 0; i < changes.length; i++) { | |||
|  |         var change = changes[i]; | |||
|  |         if (change.added) { | |||
|  |           ret.push('<ins>'); | |||
|  |         } else if (change.removed) { | |||
|  |           ret.push('<del>'); | |||
|  |         } | |||
|  | 
 | |||
|  |         ret.push(escapeHTML(change.value)); | |||
|  | 
 | |||
|  |         if (change.added) { | |||
|  |           ret.push('</ins>'); | |||
|  |         } else if (change.removed) { | |||
|  |           ret.push('</del>'); | |||
|  |         } | |||
|  |       } | |||
|  |       return ret.join(''); | |||
|  |     }, | |||
|  | 
 | |||
|  |     // See: http://code.google.com/p/google-diff-match-patch/wiki/API
 | |||
|  |     convertChangesToDMP: function(changes){ | |||
|  |       var ret = [], change; | |||
|  |       for ( var i = 0; i < changes.length; i++) { | |||
|  |         change = changes[i]; | |||
|  |         ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]); | |||
|  |       } | |||
|  |       return ret; | |||
|  |     } | |||
|  |   }; | |||
|  | })(); | |||
|  | 
 | |||
|  | if (typeof module !== 'undefined') { | |||
|  |     module.exports = JsDiff; | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: browser/diff.js
 | |||
|  | 
 | |||
|  | require.register("browser/events.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module exports. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.EventEmitter = EventEmitter; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Check if `obj` is an array. | |||
|  |  */ | |||
|  | 
 | |||
|  | function isArray(obj) { | |||
|  |   return '[object Array]' == {}.toString.call(obj); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Event emitter constructor. | |||
|  |  * | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function EventEmitter(){}; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Adds a listener. | |||
|  |  * | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | EventEmitter.prototype.on = function (name, fn) { | |||
|  |   if (!this.$events) { | |||
|  |     this.$events = {}; | |||
|  |   } | |||
|  | 
 | |||
|  |   if (!this.$events[name]) { | |||
|  |     this.$events[name] = fn; | |||
|  |   } else if (isArray(this.$events[name])) { | |||
|  |     this.$events[name].push(fn); | |||
|  |   } else { | |||
|  |     this.$events[name] = [this.$events[name], fn]; | |||
|  |   } | |||
|  | 
 | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | EventEmitter.prototype.addListener = EventEmitter.prototype.on; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Adds a volatile listener. | |||
|  |  * | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | EventEmitter.prototype.once = function (name, fn) { | |||
|  |   var self = this; | |||
|  | 
 | |||
|  |   function on () { | |||
|  |     self.removeListener(name, on); | |||
|  |     fn.apply(this, arguments); | |||
|  |   }; | |||
|  | 
 | |||
|  |   on.listener = fn; | |||
|  |   this.on(name, on); | |||
|  | 
 | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Removes a listener. | |||
|  |  * | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | EventEmitter.prototype.removeListener = function (name, fn) { | |||
|  |   if (this.$events && this.$events[name]) { | |||
|  |     var list = this.$events[name]; | |||
|  | 
 | |||
|  |     if (isArray(list)) { | |||
|  |       var pos = -1; | |||
|  | 
 | |||
|  |       for (var i = 0, l = list.length; i < l; i++) { | |||
|  |         if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { | |||
|  |           pos = i; | |||
|  |           break; | |||
|  |         } | |||
|  |       } | |||
|  | 
 | |||
|  |       if (pos < 0) { | |||
|  |         return this; | |||
|  |       } | |||
|  | 
 | |||
|  |       list.splice(pos, 1); | |||
|  | 
 | |||
|  |       if (!list.length) { | |||
|  |         delete this.$events[name]; | |||
|  |       } | |||
|  |     } else if (list === fn || (list.listener && list.listener === fn)) { | |||
|  |       delete this.$events[name]; | |||
|  |     } | |||
|  |   } | |||
|  | 
 | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Removes all listeners for an event. | |||
|  |  * | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | EventEmitter.prototype.removeAllListeners = function (name) { | |||
|  |   if (name === undefined) { | |||
|  |     this.$events = {}; | |||
|  |     return this; | |||
|  |   } | |||
|  | 
 | |||
|  |   if (this.$events && this.$events[name]) { | |||
|  |     this.$events[name] = null; | |||
|  |   } | |||
|  | 
 | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Gets all listeners for a certain event. | |||
|  |  * | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | EventEmitter.prototype.listeners = function (name) { | |||
|  |   if (!this.$events) { | |||
|  |     this.$events = {}; | |||
|  |   } | |||
|  | 
 | |||
|  |   if (!this.$events[name]) { | |||
|  |     this.$events[name] = []; | |||
|  |   } | |||
|  | 
 | |||
|  |   if (!isArray(this.$events[name])) { | |||
|  |     this.$events[name] = [this.$events[name]]; | |||
|  |   } | |||
|  | 
 | |||
|  |   return this.$events[name]; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Emits an event. | |||
|  |  * | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | EventEmitter.prototype.emit = function (name) { | |||
|  |   if (!this.$events) { | |||
|  |     return false; | |||
|  |   } | |||
|  | 
 | |||
|  |   var handler = this.$events[name]; | |||
|  | 
 | |||
|  |   if (!handler) { | |||
|  |     return false; | |||
|  |   } | |||
|  | 
 | |||
|  |   var args = [].slice.call(arguments, 1); | |||
|  | 
 | |||
|  |   if ('function' == typeof handler) { | |||
|  |     handler.apply(this, args); | |||
|  |   } else if (isArray(handler)) { | |||
|  |     var listeners = handler.slice(); | |||
|  | 
 | |||
|  |     for (var i = 0, l = listeners.length; i < l; i++) { | |||
|  |       listeners[i].apply(this, args); | |||
|  |     } | |||
|  |   } else { | |||
|  |     return false; | |||
|  |   } | |||
|  | 
 | |||
|  |   return true; | |||
|  | }; | |||
|  | }); // module: browser/events.js
 | |||
|  | 
 | |||
|  | require.register("browser/fs.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | }); // module: browser/fs.js
 | |||
|  | 
 | |||
|  | require.register("browser/path.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | }); // module: browser/path.js
 | |||
|  | 
 | |||
|  | require.register("browser/progress.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Progress`. | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = Progress; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Progress` indicator. | |||
|  |  */ | |||
|  | 
 | |||
|  | function Progress() { | |||
|  |   this.percent = 0; | |||
|  |   this.size(0); | |||
|  |   this.fontSize(11); | |||
|  |   this.font('helvetica, arial, sans-serif'); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set progress size to `n`. | |||
|  |  * | |||
|  |  * @param {Number} n | |||
|  |  * @return {Progress} for chaining | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Progress.prototype.size = function(n){ | |||
|  |   this._size = n; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set text to `str`. | |||
|  |  * | |||
|  |  * @param {String} str | |||
|  |  * @return {Progress} for chaining | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Progress.prototype.text = function(str){ | |||
|  |   this._text = str; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set font size to `n`. | |||
|  |  * | |||
|  |  * @param {Number} n | |||
|  |  * @return {Progress} for chaining | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Progress.prototype.fontSize = function(n){ | |||
|  |   this._fontSize = n; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set font `family`. | |||
|  |  * | |||
|  |  * @param {String} family | |||
|  |  * @return {Progress} for chaining | |||
|  |  */ | |||
|  | 
 | |||
|  | Progress.prototype.font = function(family){ | |||
|  |   this._font = family; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Update percentage to `n`. | |||
|  |  * | |||
|  |  * @param {Number} n | |||
|  |  * @return {Progress} for chaining | |||
|  |  */ | |||
|  | 
 | |||
|  | Progress.prototype.update = function(n){ | |||
|  |   this.percent = n; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Draw on `ctx`. | |||
|  |  * | |||
|  |  * @param {CanvasRenderingContext2d} ctx | |||
|  |  * @return {Progress} for chaining | |||
|  |  */ | |||
|  | 
 | |||
|  | Progress.prototype.draw = function(ctx){ | |||
|  |   var percent = Math.min(this.percent, 100) | |||
|  |     , size = this._size | |||
|  |     , half = size / 2 | |||
|  |     , x = half | |||
|  |     , y = half | |||
|  |     , rad = half - 1 | |||
|  |     , fontSize = this._fontSize; | |||
|  | 
 | |||
|  |   ctx.font = fontSize + 'px ' + this._font; | |||
|  | 
 | |||
|  |   var angle = Math.PI * 2 * (percent / 100); | |||
|  |   ctx.clearRect(0, 0, size, size); | |||
|  | 
 | |||
|  |   // outer circle
 | |||
|  |   ctx.strokeStyle = '#9f9f9f'; | |||
|  |   ctx.beginPath(); | |||
|  |   ctx.arc(x, y, rad, 0, angle, false); | |||
|  |   ctx.stroke(); | |||
|  | 
 | |||
|  |   // inner circle
 | |||
|  |   ctx.strokeStyle = '#eee'; | |||
|  |   ctx.beginPath(); | |||
|  |   ctx.arc(x, y, rad - 1, 0, angle, true); | |||
|  |   ctx.stroke(); | |||
|  | 
 | |||
|  |   // text
 | |||
|  |   var text = this._text || (percent | 0) + '%' | |||
|  |     , w = ctx.measureText(text).width; | |||
|  | 
 | |||
|  |   ctx.fillText( | |||
|  |       text | |||
|  |     , x - w / 2 + 1 | |||
|  |     , y + fontSize / 2 - 1); | |||
|  | 
 | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: browser/progress.js
 | |||
|  | 
 | |||
|  | require.register("browser/tty.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | exports.isatty = function(){ | |||
|  |   return true; | |||
|  | }; | |||
|  | 
 | |||
|  | exports.getWindowSize = function(){ | |||
|  |   if ('innerHeight' in global) { | |||
|  |     return [global.innerHeight, global.innerWidth]; | |||
|  |   } else { | |||
|  |     // In a Web Worker, the DOM Window is not available.
 | |||
|  |     return [640, 480]; | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: browser/tty.js
 | |||
|  | 
 | |||
|  | require.register("context.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Context`. | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = Context; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Context`. | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function Context(){} | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set or get the context `Runnable` to `runnable`. | |||
|  |  * | |||
|  |  * @param {Runnable} runnable | |||
|  |  * @return {Context} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Context.prototype.runnable = function(runnable){ | |||
|  |   if (0 == arguments.length) return this._runnable; | |||
|  |   this.test = this._runnable = runnable; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set test timeout `ms`. | |||
|  |  * | |||
|  |  * @param {Number} ms | |||
|  |  * @return {Context} self | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Context.prototype.timeout = function(ms){ | |||
|  |   this.runnable().timeout(ms); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set test slowness threshold `ms`. | |||
|  |  * | |||
|  |  * @param {Number} ms | |||
|  |  * @return {Context} self | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Context.prototype.slow = function(ms){ | |||
|  |   this.runnable().slow(ms); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inspect the context void of `._runnable`. | |||
|  |  * | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Context.prototype.inspect = function(){ | |||
|  |   return JSON.stringify(this, function(key, val){ | |||
|  |     if ('_runnable' == key) return; | |||
|  |     if ('test' == key) return; | |||
|  |     return val; | |||
|  |   }, 2); | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: context.js
 | |||
|  | 
 | |||
|  | require.register("hook.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Runnable = require('./runnable'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Hook`. | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = Hook; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Hook` with the given `title` and callback `fn`. | |||
|  |  * | |||
|  |  * @param {String} title | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function Hook(title, fn) { | |||
|  |   Runnable.call(this, title, fn); | |||
|  |   this.type = 'hook'; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Runnable.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Runnable.prototype; | |||
|  | Hook.prototype = new F; | |||
|  | Hook.prototype.constructor = Hook; | |||
|  | 
 | |||
|  | 
 | |||
|  | /** | |||
|  |  * Get or set the test `err`. | |||
|  |  * | |||
|  |  * @param {Error} err | |||
|  |  * @return {Error} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Hook.prototype.error = function(err){ | |||
|  |   if (0 == arguments.length) { | |||
|  |     var err = this._error; | |||
|  |     this._error = null; | |||
|  |     return err; | |||
|  |   } | |||
|  | 
 | |||
|  |   this._error = err; | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: hook.js
 | |||
|  | 
 | |||
|  | require.register("interfaces/bdd.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Suite = require('../suite') | |||
|  |   , Test = require('../test') | |||
|  |   , utils = require('../utils'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * BDD-style interface: | |||
|  |  * | |||
|  |  *      describe('Array', function(){ | |||
|  |  *        describe('#indexOf()', function(){ | |||
|  |  *          it('should return -1 when not present', function(){ | |||
|  |  * | |||
|  |  *          }); | |||
|  |  * | |||
|  |  *          it('should return the index when present', function(){ | |||
|  |  * | |||
|  |  *          }); | |||
|  |  *        }); | |||
|  |  *      }); | |||
|  |  * | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = function(suite){ | |||
|  |   var suites = [suite]; | |||
|  | 
 | |||
|  |   suite.on('pre-require', function(context, file, mocha){ | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute before running tests. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.before = function(fn){ | |||
|  |       suites[0].beforeAll(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute after running tests. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.after = function(fn){ | |||
|  |       suites[0].afterAll(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute before each test case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.beforeEach = function(fn){ | |||
|  |       suites[0].beforeEach(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute after each test case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.afterEach = function(fn){ | |||
|  |       suites[0].afterEach(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Describe a "suite" with the given `title` | |||
|  |      * and callback `fn` containing nested suites | |||
|  |      * and/or tests. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.describe = context.context = function(title, fn){ | |||
|  |       var suite = Suite.create(suites[0], title); | |||
|  |       suites.unshift(suite); | |||
|  |       fn.call(suite); | |||
|  |       suites.shift(); | |||
|  |       return suite; | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Pending describe. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.xdescribe = | |||
|  |     context.xcontext = | |||
|  |     context.describe.skip = function(title, fn){ | |||
|  |       var suite = Suite.create(suites[0], title); | |||
|  |       suite.pending = true; | |||
|  |       suites.unshift(suite); | |||
|  |       fn.call(suite); | |||
|  |       suites.shift(); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Exclusive suite. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.describe.only = function(title, fn){ | |||
|  |       var suite = context.describe(title, fn); | |||
|  |       mocha.grep(suite.fullTitle()); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Describe a specification or test-case | |||
|  |      * with the given `title` and callback `fn` | |||
|  |      * acting as a thunk. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.it = context.specify = function(title, fn){ | |||
|  |       var suite = suites[0]; | |||
|  |       if (suite.pending) var fn = null; | |||
|  |       var test = new Test(title, fn); | |||
|  |       suite.addTest(test); | |||
|  |       return test; | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Exclusive test-case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.it.only = function(title, fn){ | |||
|  |       var test = context.it(title, fn); | |||
|  |       var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; | |||
|  |       mocha.grep(new RegExp(reString)); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Pending test case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.xit = | |||
|  |     context.xspecify = | |||
|  |     context.it.skip = function(title){ | |||
|  |       context.it(title); | |||
|  |     }; | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: interfaces/bdd.js
 | |||
|  | 
 | |||
|  | require.register("interfaces/exports.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Suite = require('../suite') | |||
|  |   , Test = require('../test'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * TDD-style interface: | |||
|  |  * | |||
|  |  *     exports.Array = { | |||
|  |  *       '#indexOf()': { | |||
|  |  *         'should return -1 when the value is not present': function(){ | |||
|  |  * | |||
|  |  *         }, | |||
|  |  * | |||
|  |  *         'should return the correct index when the value is present': function(){ | |||
|  |  * | |||
|  |  *         } | |||
|  |  *       } | |||
|  |  *     }; | |||
|  |  * | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = function(suite){ | |||
|  |   var suites = [suite]; | |||
|  | 
 | |||
|  |   suite.on('require', visit); | |||
|  | 
 | |||
|  |   function visit(obj) { | |||
|  |     var suite; | |||
|  |     for (var key in obj) { | |||
|  |       if ('function' == typeof obj[key]) { | |||
|  |         var fn = obj[key]; | |||
|  |         switch (key) { | |||
|  |           case 'before': | |||
|  |             suites[0].beforeAll(fn); | |||
|  |             break; | |||
|  |           case 'after': | |||
|  |             suites[0].afterAll(fn); | |||
|  |             break; | |||
|  |           case 'beforeEach': | |||
|  |             suites[0].beforeEach(fn); | |||
|  |             break; | |||
|  |           case 'afterEach': | |||
|  |             suites[0].afterEach(fn); | |||
|  |             break; | |||
|  |           default: | |||
|  |             suites[0].addTest(new Test(key, fn)); | |||
|  |         } | |||
|  |       } else { | |||
|  |         var suite = Suite.create(suites[0], key); | |||
|  |         suites.unshift(suite); | |||
|  |         visit(obj[key]); | |||
|  |         suites.shift(); | |||
|  |       } | |||
|  |     } | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: interfaces/exports.js
 | |||
|  | 
 | |||
|  | require.register("interfaces/index.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | exports.bdd = require('./bdd'); | |||
|  | exports.tdd = require('./tdd'); | |||
|  | exports.qunit = require('./qunit'); | |||
|  | exports.exports = require('./exports'); | |||
|  | 
 | |||
|  | }); // module: interfaces/index.js
 | |||
|  | 
 | |||
|  | require.register("interfaces/qunit.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Suite = require('../suite') | |||
|  |   , Test = require('../test') | |||
|  |   , utils = require('../utils'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * QUnit-style interface: | |||
|  |  * | |||
|  |  *     suite('Array'); | |||
|  |  * | |||
|  |  *     test('#length', function(){ | |||
|  |  *       var arr = [1,2,3]; | |||
|  |  *       ok(arr.length == 3); | |||
|  |  *     }); | |||
|  |  * | |||
|  |  *     test('#indexOf()', function(){ | |||
|  |  *       var arr = [1,2,3]; | |||
|  |  *       ok(arr.indexOf(1) == 0); | |||
|  |  *       ok(arr.indexOf(2) == 1); | |||
|  |  *       ok(arr.indexOf(3) == 2); | |||
|  |  *     }); | |||
|  |  * | |||
|  |  *     suite('String'); | |||
|  |  * | |||
|  |  *     test('#length', function(){ | |||
|  |  *       ok('foo'.length == 3); | |||
|  |  *     }); | |||
|  |  * | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = function(suite){ | |||
|  |   var suites = [suite]; | |||
|  | 
 | |||
|  |   suite.on('pre-require', function(context, file, mocha){ | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute before running tests. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.before = function(fn){ | |||
|  |       suites[0].beforeAll(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute after running tests. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.after = function(fn){ | |||
|  |       suites[0].afterAll(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute before each test case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.beforeEach = function(fn){ | |||
|  |       suites[0].beforeEach(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute after each test case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.afterEach = function(fn){ | |||
|  |       suites[0].afterEach(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Describe a "suite" with the given `title`. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.suite = function(title){ | |||
|  |       if (suites.length > 1) suites.shift(); | |||
|  |       var suite = Suite.create(suites[0], title); | |||
|  |       suites.unshift(suite); | |||
|  |       return suite; | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Exclusive test-case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.suite.only = function(title, fn){ | |||
|  |       var suite = context.suite(title, fn); | |||
|  |       mocha.grep(suite.fullTitle()); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Describe a specification or test-case | |||
|  |      * with the given `title` and callback `fn` | |||
|  |      * acting as a thunk. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.test = function(title, fn){ | |||
|  |       var test = new Test(title, fn); | |||
|  |       suites[0].addTest(test); | |||
|  |       return test; | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Exclusive test-case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.test.only = function(title, fn){ | |||
|  |       var test = context.test(title, fn); | |||
|  |       var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; | |||
|  |       mocha.grep(new RegExp(reString)); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Pending test case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.test.skip = function(title){ | |||
|  |       context.test(title); | |||
|  |     }; | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: interfaces/qunit.js
 | |||
|  | 
 | |||
|  | require.register("interfaces/tdd.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Suite = require('../suite') | |||
|  |   , Test = require('../test') | |||
|  |   , utils = require('../utils');; | |||
|  | 
 | |||
|  | /** | |||
|  |  * TDD-style interface: | |||
|  |  * | |||
|  |  *      suite('Array', function(){ | |||
|  |  *        suite('#indexOf()', function(){ | |||
|  |  *          suiteSetup(function(){ | |||
|  |  * | |||
|  |  *          }); | |||
|  |  * | |||
|  |  *          test('should return -1 when not present', function(){ | |||
|  |  * | |||
|  |  *          }); | |||
|  |  * | |||
|  |  *          test('should return the index when present', function(){ | |||
|  |  * | |||
|  |  *          }); | |||
|  |  * | |||
|  |  *          suiteTeardown(function(){ | |||
|  |  * | |||
|  |  *          }); | |||
|  |  *        }); | |||
|  |  *      }); | |||
|  |  * | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = function(suite){ | |||
|  |   var suites = [suite]; | |||
|  | 
 | |||
|  |   suite.on('pre-require', function(context, file, mocha){ | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute before each test case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.setup = function(fn){ | |||
|  |       suites[0].beforeEach(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute after each test case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.teardown = function(fn){ | |||
|  |       suites[0].afterEach(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute before the suite. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.suiteSetup = function(fn){ | |||
|  |       suites[0].beforeAll(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Execute after the suite. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.suiteTeardown = function(fn){ | |||
|  |       suites[0].afterAll(fn); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Describe a "suite" with the given `title` | |||
|  |      * and callback `fn` containing nested suites | |||
|  |      * and/or tests. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.suite = function(title, fn){ | |||
|  |       var suite = Suite.create(suites[0], title); | |||
|  |       suites.unshift(suite); | |||
|  |       fn.call(suite); | |||
|  |       suites.shift(); | |||
|  |       return suite; | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Pending suite. | |||
|  |      */ | |||
|  |     context.suite.skip = function(title, fn) { | |||
|  |       var suite = Suite.create(suites[0], title); | |||
|  |       suite.pending = true; | |||
|  |       suites.unshift(suite); | |||
|  |       fn.call(suite); | |||
|  |       suites.shift(); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Exclusive test-case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.suite.only = function(title, fn){ | |||
|  |       var suite = context.suite(title, fn); | |||
|  |       mocha.grep(suite.fullTitle()); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Describe a specification or test-case | |||
|  |      * with the given `title` and callback `fn` | |||
|  |      * acting as a thunk. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.test = function(title, fn){ | |||
|  |       var suite = suites[0]; | |||
|  |       if (suite.pending) var fn = null; | |||
|  |       var test = new Test(title, fn); | |||
|  |       suite.addTest(test); | |||
|  |       return test; | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Exclusive test-case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.test.only = function(title, fn){ | |||
|  |       var test = context.test(title, fn); | |||
|  |       var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; | |||
|  |       mocha.grep(new RegExp(reString)); | |||
|  |     }; | |||
|  | 
 | |||
|  |     /** | |||
|  |      * Pending test case. | |||
|  |      */ | |||
|  | 
 | |||
|  |     context.test.skip = function(title){ | |||
|  |       context.test(title); | |||
|  |     }; | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: interfaces/tdd.js
 | |||
|  | 
 | |||
|  | require.register("mocha.js", function(module, exports, require){ | |||
|  | /*! | |||
|  |  * mocha | |||
|  |  * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca> | |||
|  |  * MIT Licensed | |||
|  |  */ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var path = require('browser/path') | |||
|  |   , utils = require('./utils'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Mocha`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Mocha; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose internals. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.utils = utils; | |||
|  | exports.interfaces = require('./interfaces'); | |||
|  | exports.reporters = require('./reporters'); | |||
|  | exports.Runnable = require('./runnable'); | |||
|  | exports.Context = require('./context'); | |||
|  | exports.Runner = require('./runner'); | |||
|  | exports.Suite = require('./suite'); | |||
|  | exports.Hook = require('./hook'); | |||
|  | exports.Test = require('./test'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return image `name` path. | |||
|  |  * | |||
|  |  * @param {String} name | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function image(name) { | |||
|  |   return __dirname + '/../images/' + name + '.png'; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Setup mocha with `options`. | |||
|  |  * | |||
|  |  * Options: | |||
|  |  * | |||
|  |  *   - `ui` name "bdd", "tdd", "exports" etc | |||
|  |  *   - `reporter` reporter instance, defaults to `mocha.reporters.Dot` | |||
|  |  *   - `globals` array of accepted globals | |||
|  |  *   - `timeout` timeout in milliseconds | |||
|  |  *   - `bail` bail on the first test failure | |||
|  |  *   - `slow` milliseconds to wait before considering a test slow | |||
|  |  *   - `ignoreLeaks` ignore global leaks | |||
|  |  *   - `grep` string or regexp to filter tests with | |||
|  |  * | |||
|  |  * @param {Object} options | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Mocha(options) { | |||
|  |   options = options || {}; | |||
|  |   this.files = []; | |||
|  |   this.options = options; | |||
|  |   this.grep(options.grep); | |||
|  |   this.suite = new exports.Suite('', new exports.Context); | |||
|  |   this.ui(options.ui); | |||
|  |   this.bail(options.bail); | |||
|  |   this.reporter(options.reporter); | |||
|  |   if (null != options.timeout) this.timeout(options.timeout); | |||
|  |   if (options.slow) this.slow(options.slow); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Enable or disable bailing on the first failure. | |||
|  |  * | |||
|  |  * @param {Boolean} [bail] | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.bail = function(bail){ | |||
|  |   if (0 == arguments.length) bail = true; | |||
|  |   this.suite.bail(bail); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Add test `file`. | |||
|  |  * | |||
|  |  * @param {String} file | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.addFile = function(file){ | |||
|  |   this.files.push(file); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set reporter to `reporter`, defaults to "dot". | |||
|  |  * | |||
|  |  * @param {String|Function} reporter name or constructor | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.reporter = function(reporter){ | |||
|  |   if ('function' == typeof reporter) { | |||
|  |     this._reporter = reporter; | |||
|  |   } else { | |||
|  |     reporter = reporter || 'dot'; | |||
|  |     try { | |||
|  |       this._reporter = require('./reporters/' + reporter); | |||
|  |     } catch (err) { | |||
|  |       this._reporter = require(reporter); | |||
|  |     } | |||
|  |     if (!this._reporter) throw new Error('invalid reporter "' + reporter + '"'); | |||
|  |   } | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set test UI `name`, defaults to "bdd". | |||
|  |  * | |||
|  |  * @param {String} bdd | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.ui = function(name){ | |||
|  |   name = name || 'bdd'; | |||
|  |   this._ui = exports.interfaces[name]; | |||
|  |   if (!this._ui) throw new Error('invalid interface "' + name + '"'); | |||
|  |   this._ui = this._ui(this.suite); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Load registered files. | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.loadFiles = function(fn){ | |||
|  |   var self = this; | |||
|  |   var suite = this.suite; | |||
|  |   var pending = this.files.length; | |||
|  |   this.files.forEach(function(file){ | |||
|  |     file = path.resolve(file); | |||
|  |     suite.emit('pre-require', global, file, self); | |||
|  |     suite.emit('require', require(file), file, self); | |||
|  |     suite.emit('post-require', global, file, self); | |||
|  |     --pending || (fn && fn()); | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Enable growl support. | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype._growl = function(runner, reporter) { | |||
|  |   var notify = require('growl'); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     var stats = reporter.stats; | |||
|  |     if (stats.failures) { | |||
|  |       var msg = stats.failures + ' of ' + runner.total + ' tests failed'; | |||
|  |       notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); | |||
|  |     } else { | |||
|  |       notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { | |||
|  |           name: 'mocha' | |||
|  |         , title: 'Passed' | |||
|  |         , image: image('ok') | |||
|  |       }); | |||
|  |     } | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Add regexp to grep, if `re` is a string it is escaped. | |||
|  |  * | |||
|  |  * @param {RegExp|String} re | |||
|  |  * @return {Mocha} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.grep = function(re){ | |||
|  |   this.options.grep = 'string' == typeof re | |||
|  |     ? new RegExp(utils.escapeRegexp(re)) | |||
|  |     : re; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Invert `.grep()` matches. | |||
|  |  * | |||
|  |  * @return {Mocha} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.invert = function(){ | |||
|  |   this.options.invert = true; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Ignore global leaks. | |||
|  |  * | |||
|  |  * @param {Boolean} ignore | |||
|  |  * @return {Mocha} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.ignoreLeaks = function(ignore){ | |||
|  |   this.options.ignoreLeaks = !!ignore; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Enable global leak checking. | |||
|  |  * | |||
|  |  * @return {Mocha} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.checkLeaks = function(){ | |||
|  |   this.options.ignoreLeaks = false; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Enable growl support. | |||
|  |  * | |||
|  |  * @return {Mocha} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.growl = function(){ | |||
|  |   this.options.growl = true; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Ignore `globals` array or string. | |||
|  |  * | |||
|  |  * @param {Array|String} globals | |||
|  |  * @return {Mocha} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.globals = function(globals){ | |||
|  |   this.options.globals = (this.options.globals || []).concat(globals); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set the timeout in milliseconds. | |||
|  |  * | |||
|  |  * @param {Number} timeout | |||
|  |  * @return {Mocha} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.timeout = function(timeout){ | |||
|  |   this.suite.timeout(timeout); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set slowness threshold in milliseconds. | |||
|  |  * | |||
|  |  * @param {Number} slow | |||
|  |  * @return {Mocha} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.slow = function(slow){ | |||
|  |   this.suite.slow(slow); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Makes all tests async (accepting a callback) | |||
|  |  * | |||
|  |  * @return {Mocha} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.asyncOnly = function(){ | |||
|  |   this.options.asyncOnly = true; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run tests and invoke `fn()` when complete. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @return {Runner} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.prototype.run = function(fn){ | |||
|  |   if (this.files.length) this.loadFiles(); | |||
|  |   var suite = this.suite; | |||
|  |   var options = this.options; | |||
|  |   var runner = new exports.Runner(suite); | |||
|  |   var reporter = new this._reporter(runner); | |||
|  |   runner.ignoreLeaks = false !== options.ignoreLeaks; | |||
|  |   runner.asyncOnly = options.asyncOnly; | |||
|  |   if (options.grep) runner.grep(options.grep, options.invert); | |||
|  |   if (options.globals) runner.globals(options.globals); | |||
|  |   if (options.growl) this._growl(runner, reporter); | |||
|  |   return runner.run(fn); | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: mocha.js
 | |||
|  | 
 | |||
|  | require.register("ms.js", function(module, exports, require){ | |||
|  | /** | |||
|  |  * Helpers. | |||
|  |  */ | |||
|  | 
 | |||
|  | var s = 1000; | |||
|  | var m = s * 60; | |||
|  | var h = m * 60; | |||
|  | var d = h * 24; | |||
|  | var y = d * 365.25; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Parse or format the given `val`. | |||
|  |  * | |||
|  |  * Options: | |||
|  |  * | |||
|  |  *  - `long` verbose formatting [false] | |||
|  |  * | |||
|  |  * @param {String|Number} val | |||
|  |  * @param {Object} options | |||
|  |  * @return {String|Number} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = function(val, options){ | |||
|  |   options = options || {}; | |||
|  |   if ('string' == typeof val) return parse(val); | |||
|  |   return options.long | |||
|  |     ? long(val) | |||
|  |     : short(val); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Parse the given `str` and return milliseconds. | |||
|  |  * | |||
|  |  * @param {String} str | |||
|  |  * @return {Number} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function parse(str) { | |||
|  |   var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); | |||
|  |   if (!match) return; | |||
|  |   var n = parseFloat(match[1]); | |||
|  |   var type = (match[2] || 'ms').toLowerCase(); | |||
|  |   switch (type) { | |||
|  |     case 'years': | |||
|  |     case 'year': | |||
|  |     case 'y': | |||
|  |       return n * y; | |||
|  |     case 'days': | |||
|  |     case 'day': | |||
|  |     case 'd': | |||
|  |       return n * d; | |||
|  |     case 'hours': | |||
|  |     case 'hour': | |||
|  |     case 'h': | |||
|  |       return n * h; | |||
|  |     case 'minutes': | |||
|  |     case 'minute': | |||
|  |     case 'm': | |||
|  |       return n * m; | |||
|  |     case 'seconds': | |||
|  |     case 'second': | |||
|  |     case 's': | |||
|  |       return n * s; | |||
|  |     case 'ms': | |||
|  |       return n; | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Short format for `ms`. | |||
|  |  * | |||
|  |  * @param {Number} ms | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function short(ms) { | |||
|  |   if (ms >= d) return Math.round(ms / d) + 'd'; | |||
|  |   if (ms >= h) return Math.round(ms / h) + 'h'; | |||
|  |   if (ms >= m) return Math.round(ms / m) + 'm'; | |||
|  |   if (ms >= s) return Math.round(ms / s) + 's'; | |||
|  |   return ms + 'ms'; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Long format for `ms`. | |||
|  |  * | |||
|  |  * @param {Number} ms | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function long(ms) { | |||
|  |   return plural(ms, d, 'day') | |||
|  |     || plural(ms, h, 'hour') | |||
|  |     || plural(ms, m, 'minute') | |||
|  |     || plural(ms, s, 'second') | |||
|  |     || ms + ' ms'; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Pluralization helper. | |||
|  |  */ | |||
|  | 
 | |||
|  | function plural(ms, n, name) { | |||
|  |   if (ms < n) return; | |||
|  |   if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; | |||
|  |   return Math.ceil(ms / n) + ' ' + name + 's'; | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: ms.js
 | |||
|  | 
 | |||
|  | require.register("reporters/base.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var tty = require('browser/tty') | |||
|  |   , diff = require('browser/diff') | |||
|  |   , ms = require('../ms'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Save timer references to avoid Sinon interfering (see GH-237). | |||
|  |  */ | |||
|  | 
 | |||
|  | var Date = global.Date | |||
|  |   , setTimeout = global.setTimeout | |||
|  |   , setInterval = global.setInterval | |||
|  |   , clearTimeout = global.clearTimeout | |||
|  |   , clearInterval = global.clearInterval; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Check if both stdio streams are associated with a tty. | |||
|  |  */ | |||
|  | 
 | |||
|  | var isatty = tty.isatty(1) && tty.isatty(2); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Base`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Base; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Enable coloring by default. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.useColors = isatty; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Default color map. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.colors = { | |||
|  |     'pass': 90 | |||
|  |   , 'fail': 31 | |||
|  |   , 'bright pass': 92 | |||
|  |   , 'bright fail': 91 | |||
|  |   , 'bright yellow': 93 | |||
|  |   , 'pending': 36 | |||
|  |   , 'suite': 0 | |||
|  |   , 'error title': 0 | |||
|  |   , 'error message': 31 | |||
|  |   , 'error stack': 90 | |||
|  |   , 'checkmark': 32 | |||
|  |   , 'fast': 90 | |||
|  |   , 'medium': 33 | |||
|  |   , 'slow': 31 | |||
|  |   , 'green': 32 | |||
|  |   , 'light': 90 | |||
|  |   , 'diff gutter': 90 | |||
|  |   , 'diff added': 42 | |||
|  |   , 'diff removed': 41 | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Default symbol map. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.symbols = { | |||
|  |   ok: '✓', | |||
|  |   err: '✖', | |||
|  |   dot: '․' | |||
|  | }; | |||
|  | 
 | |||
|  | // With node.js on Windows: use symbols available in terminal default fonts
 | |||
|  | if ('win32' == process.platform) { | |||
|  |   exports.symbols.ok = '\u221A'; | |||
|  |   exports.symbols.err = '\u00D7'; | |||
|  |   exports.symbols.dot = '.'; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Color `str` with the given `type`, | |||
|  |  * allowing colors to be disabled, | |||
|  |  * as well as user-defined color | |||
|  |  * schemes. | |||
|  |  * | |||
|  |  * @param {String} type | |||
|  |  * @param {String} str | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | var color = exports.color = function(type, str) { | |||
|  |   if (!exports.useColors) return str; | |||
|  |   return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose term window size, with some | |||
|  |  * defaults for when stderr is not a tty. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.window = { | |||
|  |   width: isatty | |||
|  |     ? process.stdout.getWindowSize | |||
|  |       ? process.stdout.getWindowSize(1)[0] | |||
|  |       : tty.getWindowSize()[1] | |||
|  |     : 75 | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose some basic cursor interactions | |||
|  |  * that are common among reporters. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.cursor = { | |||
|  |   hide: function(){ | |||
|  |     process.stdout.write('\u001b[?25l'); | |||
|  |   }, | |||
|  | 
 | |||
|  |   show: function(){ | |||
|  |     process.stdout.write('\u001b[?25h'); | |||
|  |   }, | |||
|  | 
 | |||
|  |   deleteLine: function(){ | |||
|  |     process.stdout.write('\u001b[2K'); | |||
|  |   }, | |||
|  | 
 | |||
|  |   beginningOfLine: function(){ | |||
|  |     process.stdout.write('\u001b[0G'); | |||
|  |   }, | |||
|  | 
 | |||
|  |   CR: function(){ | |||
|  |     exports.cursor.deleteLine(); | |||
|  |     exports.cursor.beginningOfLine(); | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Outut the given `failures` as a list. | |||
|  |  * | |||
|  |  * @param {Array} failures | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.list = function(failures){ | |||
|  |   console.error(); | |||
|  |   failures.forEach(function(test, i){ | |||
|  |     // format
 | |||
|  |     var fmt = color('error title', '  %s) %s:\n') | |||
|  |       + color('error message', '     %s') | |||
|  |       + color('error stack', '\n%s\n'); | |||
|  | 
 | |||
|  |     // msg
 | |||
|  |     var err = test.err | |||
|  |       , message = err.message || '' | |||
|  |       , stack = err.stack || message | |||
|  |       , index = stack.indexOf(message) + message.length | |||
|  |       , msg = stack.slice(0, index) | |||
|  |       , actual = err.actual | |||
|  |       , expected = err.expected | |||
|  |       , escape = true; | |||
|  | 
 | |||
|  |     // uncaught
 | |||
|  |     if (err.uncaught) { | |||
|  |       msg = 'Uncaught ' + msg; | |||
|  |     } | |||
|  | 
 | |||
|  |     // explicitly show diff
 | |||
|  |     if (err.showDiff && sameType(actual, expected)) { | |||
|  |       escape = false; | |||
|  |       err.actual = actual = stringify(actual); | |||
|  |       err.expected = expected = stringify(expected); | |||
|  |     } | |||
|  | 
 | |||
|  |     // actual / expected diff
 | |||
|  |     if ('string' == typeof actual && 'string' == typeof expected) { | |||
|  |       msg = errorDiff(err, 'WordsWithSpace', escape); | |||
|  | 
 | |||
|  |       // linenos
 | |||
|  |       var lines = msg.split('\n'); | |||
|  |       if (lines.length > 4) { | |||
|  |         var width = String(lines.length).length; | |||
|  |         msg = lines.map(function(str, i){ | |||
|  |           return pad(++i, width) + ' |' + ' ' + str; | |||
|  |         }).join('\n'); | |||
|  |       } | |||
|  | 
 | |||
|  |       // legend
 | |||
|  |       msg = '\n' | |||
|  |         + color('diff removed', 'actual') | |||
|  |         + ' ' | |||
|  |         + color('diff added', 'expected') | |||
|  |         + '\n\n' | |||
|  |         + msg | |||
|  |         + '\n'; | |||
|  | 
 | |||
|  |       // indent
 | |||
|  |       msg = msg.replace(/^/gm, '      '); | |||
|  | 
 | |||
|  |       fmt = color('error title', '  %s) %s:\n%s') | |||
|  |         + color('error stack', '\n%s\n'); | |||
|  |     } | |||
|  | 
 | |||
|  |     // indent stack trace without msg
 | |||
|  |     stack = stack.slice(index ? index + 1 : index) | |||
|  |       .replace(/^/gm, '  '); | |||
|  | 
 | |||
|  |     console.error(fmt, (i + 1), test.fullTitle(), msg, stack); | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Base` reporter. | |||
|  |  * | |||
|  |  * All other reporters generally | |||
|  |  * inherit from this reporter, providing | |||
|  |  * stats such as test duration, number | |||
|  |  * of tests passed / failed etc. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Base(runner) { | |||
|  |   var self = this | |||
|  |     , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } | |||
|  |     , failures = this.failures = []; | |||
|  | 
 | |||
|  |   if (!runner) return; | |||
|  |   this.runner = runner; | |||
|  | 
 | |||
|  |   runner.stats = stats; | |||
|  | 
 | |||
|  |   runner.on('start', function(){ | |||
|  |     stats.start = new Date; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('suite', function(suite){ | |||
|  |     stats.suites = stats.suites || 0; | |||
|  |     suite.root || stats.suites++; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('test end', function(test){ | |||
|  |     stats.tests = stats.tests || 0; | |||
|  |     stats.tests++; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     stats.passes = stats.passes || 0; | |||
|  | 
 | |||
|  |     var medium = test.slow() / 2; | |||
|  |     test.speed = test.duration > test.slow() | |||
|  |       ? 'slow' | |||
|  |       : test.duration > medium | |||
|  |         ? 'medium' | |||
|  |         : 'fast'; | |||
|  | 
 | |||
|  |     stats.passes++; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test, err){ | |||
|  |     stats.failures = stats.failures || 0; | |||
|  |     stats.failures++; | |||
|  |     test.err = err; | |||
|  |     failures.push(test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     stats.end = new Date; | |||
|  |     stats.duration = new Date - stats.start; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pending', function(){ | |||
|  |     stats.pending++; | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Output common epilogue used by many of | |||
|  |  * the bundled reporters. | |||
|  |  * | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Base.prototype.epilogue = function(){ | |||
|  |   var stats = this.stats; | |||
|  |   var tests; | |||
|  |   var fmt; | |||
|  | 
 | |||
|  |   console.log(); | |||
|  | 
 | |||
|  |   // passes
 | |||
|  |   fmt = color('bright pass', ' ') | |||
|  |     + color('green', ' %d passing') | |||
|  |     + color('light', ' (%s)'); | |||
|  | 
 | |||
|  |   console.log(fmt, | |||
|  |     stats.passes || 0, | |||
|  |     ms(stats.duration)); | |||
|  | 
 | |||
|  |   // pending
 | |||
|  |   if (stats.pending) { | |||
|  |     fmt = color('pending', ' ') | |||
|  |       + color('pending', ' %d pending'); | |||
|  | 
 | |||
|  |     console.log(fmt, stats.pending); | |||
|  |   } | |||
|  | 
 | |||
|  |   // failures
 | |||
|  |   if (stats.failures) { | |||
|  |     fmt = color('fail', '  %d failing'); | |||
|  | 
 | |||
|  |     console.error(fmt, | |||
|  |       stats.failures); | |||
|  | 
 | |||
|  |     Base.list(this.failures); | |||
|  |     console.error(); | |||
|  |   } | |||
|  | 
 | |||
|  |   console.log(); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Pad the given `str` to `len`. | |||
|  |  * | |||
|  |  * @param {String} str | |||
|  |  * @param {String} len | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function pad(str, len) { | |||
|  |   str = String(str); | |||
|  |   return Array(len - str.length + 1).join(' ') + str; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return a character diff for `err`. | |||
|  |  * | |||
|  |  * @param {Error} err | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function errorDiff(err, type, escape) { | |||
|  |   return diff['diff' + type](err.actual, err.expected).map(function(str){ | |||
|  |     if (escape) { | |||
|  |       str.value = str.value | |||
|  |         .replace(/\t/g, '<tab>') | |||
|  |         .replace(/\r/g, '<CR>') | |||
|  |         .replace(/\n/g, '<LF>\n'); | |||
|  |     } | |||
|  |     if (str.added) return colorLines('diff added', str.value); | |||
|  |     if (str.removed) return colorLines('diff removed', str.value); | |||
|  |     return str.value; | |||
|  |   }).join(''); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Color lines for `str`, using the color `name`. | |||
|  |  * | |||
|  |  * @param {String} name | |||
|  |  * @param {String} str | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function colorLines(name, str) { | |||
|  |   return str.split('\n').map(function(str){ | |||
|  |     return color(name, str); | |||
|  |   }).join('\n'); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Stringify `obj`. | |||
|  |  * | |||
|  |  * @param {Mixed} obj | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function stringify(obj) { | |||
|  |   if (obj instanceof RegExp) return obj.toString(); | |||
|  |   return JSON.stringify(obj, null, 2); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Check that a / b have the same type. | |||
|  |  * | |||
|  |  * @param {Object} a | |||
|  |  * @param {Object} b | |||
|  |  * @return {Boolean} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function sameType(a, b) { | |||
|  |   a = Object.prototype.toString.call(a); | |||
|  |   b = Object.prototype.toString.call(b); | |||
|  |   return a == b; | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: reporters/base.js
 | |||
|  | 
 | |||
|  | require.register("reporters/doc.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , utils = require('../utils'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Doc`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Doc; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Doc` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Doc(runner) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , total = runner.total | |||
|  |     , indents = 2; | |||
|  | 
 | |||
|  |   function indent() { | |||
|  |     return Array(indents).join('  '); | |||
|  |   } | |||
|  | 
 | |||
|  |   runner.on('suite', function(suite){ | |||
|  |     if (suite.root) return; | |||
|  |     ++indents; | |||
|  |     console.log('%s<section class="suite">', indent()); | |||
|  |     ++indents; | |||
|  |     console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title)); | |||
|  |     console.log('%s<dl>', indent()); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('suite end', function(suite){ | |||
|  |     if (suite.root) return; | |||
|  |     console.log('%s</dl>', indent()); | |||
|  |     --indents; | |||
|  |     console.log('%s</section>', indent()); | |||
|  |     --indents; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     console.log('%s  <dt>%s</dt>', indent(), utils.escape(test.title)); | |||
|  |     var code = utils.escape(utils.clean(test.fn.toString())); | |||
|  |     console.log('%s  <dd><pre><code>%s</code></pre></dd>', indent(), code); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: reporters/doc.js
 | |||
|  | 
 | |||
|  | require.register("reporters/dot.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , color = Base.color; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Dot`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Dot; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Dot` matrix test reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Dot(runner) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , width = Base.window.width * .75 | 0 | |||
|  |     , n = 0; | |||
|  | 
 | |||
|  |   runner.on('start', function(){ | |||
|  |     process.stdout.write('\n  '); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pending', function(test){ | |||
|  |     process.stdout.write(color('pending', Base.symbols.dot)); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     if (++n % width == 0) process.stdout.write('\n  '); | |||
|  |     if ('slow' == test.speed) { | |||
|  |       process.stdout.write(color('bright yellow', Base.symbols.dot)); | |||
|  |     } else { | |||
|  |       process.stdout.write(color(test.speed, Base.symbols.dot)); | |||
|  |     } | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test, err){ | |||
|  |     if (++n % width == 0) process.stdout.write('\n  '); | |||
|  |     process.stdout.write(color('fail', Base.symbols.dot)); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     console.log(); | |||
|  |     self.epilogue(); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Base.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Base.prototype; | |||
|  | Dot.prototype = new F; | |||
|  | Dot.prototype.constructor = Dot; | |||
|  | 
 | |||
|  | }); // module: reporters/dot.js
 | |||
|  | 
 | |||
|  | require.register("reporters/html-cov.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var JSONCov = require('./json-cov') | |||
|  |   , fs = require('browser/fs'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `HTMLCov`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = HTMLCov; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `JsCoverage` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function HTMLCov(runner) { | |||
|  |   var jade = require('jade') | |||
|  |     , file = __dirname + '/templates/coverage.jade' | |||
|  |     , str = fs.readFileSync(file, 'utf8') | |||
|  |     , fn = jade.compile(str, { filename: file }) | |||
|  |     , self = this; | |||
|  | 
 | |||
|  |   JSONCov.call(this, runner, false); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     process.stdout.write(fn({ | |||
|  |         cov: self.cov | |||
|  |       , coverageClass: coverageClass | |||
|  |     })); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return coverage class for `n`. | |||
|  |  * | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function coverageClass(n) { | |||
|  |   if (n >= 75) return 'high'; | |||
|  |   if (n >= 50) return 'medium'; | |||
|  |   if (n >= 25) return 'low'; | |||
|  |   return 'terrible'; | |||
|  | } | |||
|  | }); // module: reporters/html-cov.js
 | |||
|  | 
 | |||
|  | require.register("reporters/html.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , utils = require('../utils') | |||
|  |   , Progress = require('../browser/progress') | |||
|  |   , escape = utils.escape; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Save timer references to avoid Sinon interfering (see GH-237). | |||
|  |  */ | |||
|  | 
 | |||
|  | var Date = global.Date | |||
|  |   , setTimeout = global.setTimeout | |||
|  |   , setInterval = global.setInterval | |||
|  |   , clearTimeout = global.clearTimeout | |||
|  |   , clearInterval = global.clearInterval; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Doc`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = HTML; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Stats template. | |||
|  |  */ | |||
|  | 
 | |||
|  | var statsTemplate = '<ul id="mocha-stats">' | |||
|  |   + '<li class="progress"><canvas width="40" height="40"></canvas></li>' | |||
|  |   + '<li class="passes"><a href="#">passes:</a> <em>0</em></li>' | |||
|  |   + '<li class="failures"><a href="#">failures:</a> <em>0</em></li>' | |||
|  |   + '<li class="duration">duration: <em>0</em>s</li>' | |||
|  |   + '</ul>'; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Doc` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function HTML(runner, root) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , total = runner.total | |||
|  |     , stat = fragment(statsTemplate) | |||
|  |     , items = stat.getElementsByTagName('li') | |||
|  |     , passes = items[1].getElementsByTagName('em')[0] | |||
|  |     , passesLink = items[1].getElementsByTagName('a')[0] | |||
|  |     , failures = items[2].getElementsByTagName('em')[0] | |||
|  |     , failuresLink = items[2].getElementsByTagName('a')[0] | |||
|  |     , duration = items[3].getElementsByTagName('em')[0] | |||
|  |     , canvas = stat.getElementsByTagName('canvas')[0] | |||
|  |     , report = fragment('<ul id="mocha-report"></ul>') | |||
|  |     , stack = [report] | |||
|  |     , progress | |||
|  |     , ctx | |||
|  | 
 | |||
|  |   root = root || document.getElementById('mocha'); | |||
|  | 
 | |||
|  |   if (canvas.getContext) { | |||
|  |     var ratio = window.devicePixelRatio || 1; | |||
|  |     canvas.style.width = canvas.width; | |||
|  |     canvas.style.height = canvas.height; | |||
|  |     canvas.width *= ratio; | |||
|  |     canvas.height *= ratio; | |||
|  |     ctx = canvas.getContext('2d'); | |||
|  |     ctx.scale(ratio, ratio); | |||
|  |     progress = new Progress; | |||
|  |   } | |||
|  | 
 | |||
|  |   if (!root) return error('#mocha div missing, add it to your document'); | |||
|  | 
 | |||
|  |   // pass toggle
 | |||
|  |   on(passesLink, 'click', function(){ | |||
|  |     unhide(); | |||
|  |     var name = /pass/.test(report.className) ? '' : ' pass'; | |||
|  |     report.className = report.className.replace(/fail|pass/g, '') + name; | |||
|  |     if (report.className.trim()) hideSuitesWithout('test pass'); | |||
|  |   }); | |||
|  | 
 | |||
|  |   // failure toggle
 | |||
|  |   on(failuresLink, 'click', function(){ | |||
|  |     unhide(); | |||
|  |     var name = /fail/.test(report.className) ? '' : ' fail'; | |||
|  |     report.className = report.className.replace(/fail|pass/g, '') + name; | |||
|  |     if (report.className.trim()) hideSuitesWithout('test fail'); | |||
|  |   }); | |||
|  | 
 | |||
|  |   root.appendChild(stat); | |||
|  |   root.appendChild(report); | |||
|  | 
 | |||
|  |   if (progress) progress.size(40); | |||
|  | 
 | |||
|  |   runner.on('suite', function(suite){ | |||
|  |     if (suite.root) return; | |||
|  | 
 | |||
|  |     // suite
 | |||
|  |     var url = '?grep=' + encodeURIComponent(suite.fullTitle()); | |||
|  |     var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title)); | |||
|  | 
 | |||
|  |     // container
 | |||
|  |     stack[0].appendChild(el); | |||
|  |     stack.unshift(document.createElement('ul')); | |||
|  |     el.appendChild(stack[0]); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('suite end', function(suite){ | |||
|  |     if (suite.root) return; | |||
|  |     stack.shift(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test, err){ | |||
|  |     if ('hook' == test.type) runner.emit('test end', test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('test end', function(test){ | |||
|  |     // TODO: add to stats
 | |||
|  |     var percent = stats.tests / this.total * 100 | 0; | |||
|  |     if (progress) progress.update(percent).draw(ctx); | |||
|  | 
 | |||
|  |     // update stats
 | |||
|  |     var ms = new Date - stats.start; | |||
|  |     text(passes, stats.passes); | |||
|  |     text(failures, stats.failures); | |||
|  |     text(duration, (ms / 1000).toFixed(2)); | |||
|  | 
 | |||
|  |     // test
 | |||
|  |     if ('passed' == test.state) { | |||
|  |       var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="?grep=%e" class="replay">‣</a></h2></li>', test.speed, test.title, test.duration, encodeURIComponent(test.fullTitle())); | |||
|  |     } else if (test.pending) { | |||
|  |       var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title); | |||
|  |     } else { | |||
|  |       var el = fragment('<li class="test fail"><h2>%e <a href="?grep=%e" class="replay">‣</a></h2></li>', test.title, encodeURIComponent(test.fullTitle())); | |||
|  |       var str = test.err.stack || test.err.toString(); | |||
|  | 
 | |||
|  |       // FF / Opera do not add the message
 | |||
|  |       if (!~str.indexOf(test.err.message)) { | |||
|  |         str = test.err.message + '\n' + str; | |||
|  |       } | |||
|  | 
 | |||
|  |       // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
 | |||
|  |       // check for the result of the stringifying.
 | |||
|  |       if ('[object Error]' == str) str = test.err.message; | |||
|  | 
 | |||
|  |       // Safari doesn't give you a stack. Let's at least provide a source line.
 | |||
|  |       if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { | |||
|  |         str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; | |||
|  |       } | |||
|  | 
 | |||
|  |       el.appendChild(fragment('<pre class="error">%e</pre>', str)); | |||
|  |     } | |||
|  | 
 | |||
|  |     // toggle code
 | |||
|  |     // TODO: defer
 | |||
|  |     if (!test.pending) { | |||
|  |       var h2 = el.getElementsByTagName('h2')[0]; | |||
|  | 
 | |||
|  |       on(h2, 'click', function(){ | |||
|  |         pre.style.display = 'none' == pre.style.display | |||
|  |           ? 'block' | |||
|  |           : 'none'; | |||
|  |       }); | |||
|  | 
 | |||
|  |       var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString())); | |||
|  |       el.appendChild(pre); | |||
|  |       pre.style.display = 'none'; | |||
|  |     } | |||
|  | 
 | |||
|  |     // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.
 | |||
|  |     if (stack[0]) stack[0].appendChild(el); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Display error `msg`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function error(msg) { | |||
|  |   document.body.appendChild(fragment('<div id="mocha-error">%s</div>', msg)); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return a DOM fragment from `html`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function fragment(html) { | |||
|  |   var args = arguments | |||
|  |     , div = document.createElement('div') | |||
|  |     , i = 1; | |||
|  | 
 | |||
|  |   div.innerHTML = html.replace(/%([se])/g, function(_, type){ | |||
|  |     switch (type) { | |||
|  |       case 's': return String(args[i++]); | |||
|  |       case 'e': return escape(args[i++]); | |||
|  |     } | |||
|  |   }); | |||
|  | 
 | |||
|  |   return div.firstChild; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Check for suites that do not have elements | |||
|  |  * with `classname`, and hide them. | |||
|  |  */ | |||
|  | 
 | |||
|  | function hideSuitesWithout(classname) { | |||
|  |   var suites = document.getElementsByClassName('suite'); | |||
|  |   for (var i = 0; i < suites.length; i++) { | |||
|  |     var els = suites[i].getElementsByClassName(classname); | |||
|  |     if (0 == els.length) suites[i].className += ' hidden'; | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Unhide .hidden suites. | |||
|  |  */ | |||
|  | 
 | |||
|  | function unhide() { | |||
|  |   var els = document.getElementsByClassName('suite hidden'); | |||
|  |   for (var i = 0; i < els.length; ++i) { | |||
|  |     els[i].className = els[i].className.replace('suite hidden', 'suite'); | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set `el` text to `str`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function text(el, str) { | |||
|  |   if (el.textContent) { | |||
|  |     el.textContent = str; | |||
|  |   } else { | |||
|  |     el.innerText = str; | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Listen on `event` with callback `fn`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function on(el, event, fn) { | |||
|  |   if (el.addEventListener) { | |||
|  |     el.addEventListener(event, fn, false); | |||
|  |   } else { | |||
|  |     el.attachEvent('on' + event, fn); | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: reporters/html.js
 | |||
|  | 
 | |||
|  | require.register("reporters/index.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | exports.Base = require('./base'); | |||
|  | exports.Dot = require('./dot'); | |||
|  | exports.Doc = require('./doc'); | |||
|  | exports.TAP = require('./tap'); | |||
|  | exports.JSON = require('./json'); | |||
|  | exports.HTML = require('./html'); | |||
|  | exports.List = require('./list'); | |||
|  | exports.Min = require('./min'); | |||
|  | exports.Spec = require('./spec'); | |||
|  | exports.Nyan = require('./nyan'); | |||
|  | exports.XUnit = require('./xunit'); | |||
|  | exports.Markdown = require('./markdown'); | |||
|  | exports.Progress = require('./progress'); | |||
|  | exports.Landing = require('./landing'); | |||
|  | exports.JSONCov = require('./json-cov'); | |||
|  | exports.HTMLCov = require('./html-cov'); | |||
|  | exports.JSONStream = require('./json-stream'); | |||
|  | exports.Teamcity = require('./teamcity'); | |||
|  | 
 | |||
|  | }); // module: reporters/index.js
 | |||
|  | 
 | |||
|  | require.register("reporters/json-cov.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `JSONCov`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = JSONCov; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `JsCoverage` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @param {Boolean} output | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function JSONCov(runner, output) { | |||
|  |   var self = this | |||
|  |     , output = 1 == arguments.length ? true : output; | |||
|  | 
 | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var tests = [] | |||
|  |     , failures = [] | |||
|  |     , passes = []; | |||
|  | 
 | |||
|  |   runner.on('test end', function(test){ | |||
|  |     tests.push(test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     passes.push(test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test){ | |||
|  |     failures.push(test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     var cov = global._$jscoverage || {}; | |||
|  |     var result = self.cov = map(cov); | |||
|  |     result.stats = self.stats; | |||
|  |     result.tests = tests.map(clean); | |||
|  |     result.failures = failures.map(clean); | |||
|  |     result.passes = passes.map(clean); | |||
|  |     if (!output) return; | |||
|  |     process.stdout.write(JSON.stringify(result, null, 2 )); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Map jscoverage data to a JSON structure | |||
|  |  * suitable for reporting. | |||
|  |  * | |||
|  |  * @param {Object} cov | |||
|  |  * @return {Object} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function map(cov) { | |||
|  |   var ret = { | |||
|  |       instrumentation: 'node-jscoverage' | |||
|  |     , sloc: 0 | |||
|  |     , hits: 0 | |||
|  |     , misses: 0 | |||
|  |     , coverage: 0 | |||
|  |     , files: [] | |||
|  |   }; | |||
|  | 
 | |||
|  |   for (var filename in cov) { | |||
|  |     var data = coverage(filename, cov[filename]); | |||
|  |     ret.files.push(data); | |||
|  |     ret.hits += data.hits; | |||
|  |     ret.misses += data.misses; | |||
|  |     ret.sloc += data.sloc; | |||
|  |   } | |||
|  | 
 | |||
|  |   ret.files.sort(function(a, b) { | |||
|  |     return a.filename.localeCompare(b.filename); | |||
|  |   }); | |||
|  | 
 | |||
|  |   if (ret.sloc > 0) { | |||
|  |     ret.coverage = (ret.hits / ret.sloc) * 100; | |||
|  |   } | |||
|  | 
 | |||
|  |   return ret; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Map jscoverage data for a single source file | |||
|  |  * to a JSON structure suitable for reporting. | |||
|  |  * | |||
|  |  * @param {String} filename name of the source file | |||
|  |  * @param {Object} data jscoverage coverage data | |||
|  |  * @return {Object} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function coverage(filename, data) { | |||
|  |   var ret = { | |||
|  |     filename: filename, | |||
|  |     coverage: 0, | |||
|  |     hits: 0, | |||
|  |     misses: 0, | |||
|  |     sloc: 0, | |||
|  |     source: {} | |||
|  |   }; | |||
|  | 
 | |||
|  |   data.source.forEach(function(line, num){ | |||
|  |     num++; | |||
|  | 
 | |||
|  |     if (data[num] === 0) { | |||
|  |       ret.misses++; | |||
|  |       ret.sloc++; | |||
|  |     } else if (data[num] !== undefined) { | |||
|  |       ret.hits++; | |||
|  |       ret.sloc++; | |||
|  |     } | |||
|  | 
 | |||
|  |     ret.source[num] = { | |||
|  |         source: line | |||
|  |       , coverage: data[num] === undefined | |||
|  |         ? '' | |||
|  |         : data[num] | |||
|  |     }; | |||
|  |   }); | |||
|  | 
 | |||
|  |   ret.coverage = ret.hits / ret.sloc * 100; | |||
|  | 
 | |||
|  |   return ret; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return a plain-object representation of `test` | |||
|  |  * free of cyclic properties etc. | |||
|  |  * | |||
|  |  * @param {Object} test | |||
|  |  * @return {Object} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function clean(test) { | |||
|  |   return { | |||
|  |       title: test.title | |||
|  |     , fullTitle: test.fullTitle() | |||
|  |     , duration: test.duration | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: reporters/json-cov.js
 | |||
|  | 
 | |||
|  | require.register("reporters/json-stream.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , color = Base.color; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `List`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = List; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `List` test reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function List(runner) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , total = runner.total; | |||
|  | 
 | |||
|  |   runner.on('start', function(){ | |||
|  |     console.log(JSON.stringify(['start', { total: total }])); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     console.log(JSON.stringify(['pass', clean(test)])); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test, err){ | |||
|  |     console.log(JSON.stringify(['fail', clean(test)])); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     process.stdout.write(JSON.stringify(['end', self.stats])); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return a plain-object representation of `test` | |||
|  |  * free of cyclic properties etc. | |||
|  |  * | |||
|  |  * @param {Object} test | |||
|  |  * @return {Object} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function clean(test) { | |||
|  |   return { | |||
|  |       title: test.title | |||
|  |     , fullTitle: test.fullTitle() | |||
|  |     , duration: test.duration | |||
|  |   } | |||
|  | } | |||
|  | }); // module: reporters/json-stream.js
 | |||
|  | 
 | |||
|  | require.register("reporters/json.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , cursor = Base.cursor | |||
|  |   , color = Base.color; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `JSON`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = JSONReporter; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `JSON` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function JSONReporter(runner) { | |||
|  |   var self = this; | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var tests = [] | |||
|  |     , failures = [] | |||
|  |     , passes = []; | |||
|  | 
 | |||
|  |   runner.on('test end', function(test){ | |||
|  |     tests.push(test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     passes.push(test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test){ | |||
|  |     failures.push(test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     var obj = { | |||
|  |         stats: self.stats | |||
|  |       , tests: tests.map(clean) | |||
|  |       , failures: failures.map(clean) | |||
|  |       , passes: passes.map(clean) | |||
|  |     }; | |||
|  | 
 | |||
|  |     process.stdout.write(JSON.stringify(obj, null, 2)); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return a plain-object representation of `test` | |||
|  |  * free of cyclic properties etc. | |||
|  |  * | |||
|  |  * @param {Object} test | |||
|  |  * @return {Object} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function clean(test) { | |||
|  |   return { | |||
|  |       title: test.title | |||
|  |     , fullTitle: test.fullTitle() | |||
|  |     , duration: test.duration | |||
|  |   } | |||
|  | } | |||
|  | }); // module: reporters/json.js
 | |||
|  | 
 | |||
|  | require.register("reporters/landing.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , cursor = Base.cursor | |||
|  |   , color = Base.color; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Landing`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Landing; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Airplane color. | |||
|  |  */ | |||
|  | 
 | |||
|  | Base.colors.plane = 0; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Airplane crash color. | |||
|  |  */ | |||
|  | 
 | |||
|  | Base.colors['plane crash'] = 31; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Runway color. | |||
|  |  */ | |||
|  | 
 | |||
|  | Base.colors.runway = 90; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Landing` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Landing(runner) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , width = Base.window.width * .75 | 0 | |||
|  |     , total = runner.total | |||
|  |     , stream = process.stdout | |||
|  |     , plane = color('plane', '✈') | |||
|  |     , crashed = -1 | |||
|  |     , n = 0; | |||
|  | 
 | |||
|  |   function runway() { | |||
|  |     var buf = Array(width).join('-'); | |||
|  |     return '  ' + color('runway', buf); | |||
|  |   } | |||
|  | 
 | |||
|  |   runner.on('start', function(){ | |||
|  |     stream.write('\n  '); | |||
|  |     cursor.hide(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('test end', function(test){ | |||
|  |     // check if the plane crashed
 | |||
|  |     var col = -1 == crashed | |||
|  |       ? width * ++n / total | 0 | |||
|  |       : crashed; | |||
|  | 
 | |||
|  |     // show the crash
 | |||
|  |     if ('failed' == test.state) { | |||
|  |       plane = color('plane crash', '✈'); | |||
|  |       crashed = col; | |||
|  |     } | |||
|  | 
 | |||
|  |     // render landing strip
 | |||
|  |     stream.write('\u001b[4F\n\n'); | |||
|  |     stream.write(runway()); | |||
|  |     stream.write('\n  '); | |||
|  |     stream.write(color('runway', Array(col).join('⋅'))); | |||
|  |     stream.write(plane) | |||
|  |     stream.write(color('runway', Array(width - col).join('⋅') + '\n')); | |||
|  |     stream.write(runway()); | |||
|  |     stream.write('\u001b[0m'); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     cursor.show(); | |||
|  |     console.log(); | |||
|  |     self.epilogue(); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Base.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Base.prototype; | |||
|  | Landing.prototype = new F; | |||
|  | Landing.prototype.constructor = Landing; | |||
|  | 
 | |||
|  | }); // module: reporters/landing.js
 | |||
|  | 
 | |||
|  | require.register("reporters/list.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , cursor = Base.cursor | |||
|  |   , color = Base.color; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `List`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = List; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `List` test reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function List(runner) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , n = 0; | |||
|  | 
 | |||
|  |   runner.on('start', function(){ | |||
|  |     console.log(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('test', function(test){ | |||
|  |     process.stdout.write(color('pass', '    ' + test.fullTitle() + ': ')); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pending', function(test){ | |||
|  |     var fmt = color('checkmark', '  -') | |||
|  |       + color('pending', ' %s'); | |||
|  |     console.log(fmt, test.fullTitle()); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     var fmt = color('checkmark', '  '+Base.symbols.dot) | |||
|  |       + color('pass', ' %s: ') | |||
|  |       + color(test.speed, '%dms'); | |||
|  |     cursor.CR(); | |||
|  |     console.log(fmt, test.fullTitle(), test.duration); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test, err){ | |||
|  |     cursor.CR(); | |||
|  |     console.log(color('fail', '  %d) %s'), ++n, test.fullTitle()); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', self.epilogue.bind(self)); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Base.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Base.prototype; | |||
|  | List.prototype = new F; | |||
|  | List.prototype.constructor = List; | |||
|  | 
 | |||
|  | 
 | |||
|  | }); // module: reporters/list.js
 | |||
|  | 
 | |||
|  | require.register("reporters/markdown.js", function(module, exports, require){ | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , utils = require('../utils'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Markdown`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Markdown; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Markdown` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Markdown(runner) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , level = 0 | |||
|  |     , buf = ''; | |||
|  | 
 | |||
|  |   function title(str) { | |||
|  |     return Array(level).join('#') + ' ' + str; | |||
|  |   } | |||
|  | 
 | |||
|  |   function indent() { | |||
|  |     return Array(level).join('  '); | |||
|  |   } | |||
|  | 
 | |||
|  |   function mapTOC(suite, obj) { | |||
|  |     var ret = obj; | |||
|  |     obj = obj[suite.title] = obj[suite.title] || { suite: suite }; | |||
|  |     suite.suites.forEach(function(suite){ | |||
|  |       mapTOC(suite, obj); | |||
|  |     }); | |||
|  |     return ret; | |||
|  |   } | |||
|  | 
 | |||
|  |   function stringifyTOC(obj, level) { | |||
|  |     ++level; | |||
|  |     var buf = ''; | |||
|  |     var link; | |||
|  |     for (var key in obj) { | |||
|  |       if ('suite' == key) continue; | |||
|  |       if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; | |||
|  |       if (key) buf += Array(level).join('  ') + link; | |||
|  |       buf += stringifyTOC(obj[key], level); | |||
|  |     } | |||
|  |     --level; | |||
|  |     return buf; | |||
|  |   } | |||
|  | 
 | |||
|  |   function generateTOC(suite) { | |||
|  |     var obj = mapTOC(suite, {}); | |||
|  |     return stringifyTOC(obj, 0); | |||
|  |   } | |||
|  | 
 | |||
|  |   generateTOC(runner.suite); | |||
|  | 
 | |||
|  |   runner.on('suite', function(suite){ | |||
|  |     ++level; | |||
|  |     var slug = utils.slug(suite.fullTitle()); | |||
|  |     buf += '<a name="' + slug + '"></a>' + '\n'; | |||
|  |     buf += title(suite.title) + '\n'; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('suite end', function(suite){ | |||
|  |     --level; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     var code = utils.clean(test.fn.toString()); | |||
|  |     buf += test.title + '.\n'; | |||
|  |     buf += '\n```js\n'; | |||
|  |     buf += code + '\n'; | |||
|  |     buf += '```\n\n'; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     process.stdout.write('# TOC\n'); | |||
|  |     process.stdout.write(generateTOC(runner.suite)); | |||
|  |     process.stdout.write(buf); | |||
|  |   }); | |||
|  | } | |||
|  | }); // module: reporters/markdown.js
 | |||
|  | 
 | |||
|  | require.register("reporters/min.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Min`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Min; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Min` minimal test reporter (best used with --watch). | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Min(runner) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   runner.on('start', function(){ | |||
|  |     // clear screen
 | |||
|  |     process.stdout.write('\u001b[2J'); | |||
|  |     // set cursor position
 | |||
|  |     process.stdout.write('\u001b[1;3H'); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', this.epilogue.bind(this)); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Base.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Base.prototype; | |||
|  | Min.prototype = new F; | |||
|  | Min.prototype.constructor = Min; | |||
|  | 
 | |||
|  | 
 | |||
|  | }); // module: reporters/min.js
 | |||
|  | 
 | |||
|  | require.register("reporters/nyan.js", function(module, exports, require){ | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , color = Base.color; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Dot`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = NyanCat; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Dot` matrix test reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function NyanCat(runner) { | |||
|  |   Base.call(this, runner); | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , width = Base.window.width * .75 | 0 | |||
|  |     , rainbowColors = this.rainbowColors = self.generateColors() | |||
|  |     , colorIndex = this.colorIndex = 0 | |||
|  |     , numerOfLines = this.numberOfLines = 4 | |||
|  |     , trajectories = this.trajectories = [[], [], [], []] | |||
|  |     , nyanCatWidth = this.nyanCatWidth = 11 | |||
|  |     , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) | |||
|  |     , scoreboardWidth = this.scoreboardWidth = 5 | |||
|  |     , tick = this.tick = 0 | |||
|  |     , n = 0; | |||
|  | 
 | |||
|  |   runner.on('start', function(){ | |||
|  |     Base.cursor.hide(); | |||
|  |     self.draw(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pending', function(test){ | |||
|  |     self.draw(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     self.draw(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test, err){ | |||
|  |     self.draw(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     Base.cursor.show(); | |||
|  |     for (var i = 0; i < self.numberOfLines; i++) write('\n'); | |||
|  |     self.epilogue(); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Draw the nyan cat | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.draw = function(){ | |||
|  |   this.appendRainbow(); | |||
|  |   this.drawScoreboard(); | |||
|  |   this.drawRainbow(); | |||
|  |   this.drawNyanCat(); | |||
|  |   this.tick = !this.tick; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Draw the "scoreboard" showing the number | |||
|  |  * of passes, failures and pending tests. | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.drawScoreboard = function(){ | |||
|  |   var stats = this.stats; | |||
|  |   var colors = Base.colors; | |||
|  | 
 | |||
|  |   function draw(color, n) { | |||
|  |     write(' '); | |||
|  |     write('\u001b[' + color + 'm' + n + '\u001b[0m'); | |||
|  |     write('\n'); | |||
|  |   } | |||
|  | 
 | |||
|  |   draw(colors.green, stats.passes); | |||
|  |   draw(colors.fail, stats.failures); | |||
|  |   draw(colors.pending, stats.pending); | |||
|  |   write('\n'); | |||
|  | 
 | |||
|  |   this.cursorUp(this.numberOfLines); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Append the rainbow. | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.appendRainbow = function(){ | |||
|  |   var segment = this.tick ? '_' : '-'; | |||
|  |   var rainbowified = this.rainbowify(segment); | |||
|  | 
 | |||
|  |   for (var index = 0; index < this.numberOfLines; index++) { | |||
|  |     var trajectory = this.trajectories[index]; | |||
|  |     if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); | |||
|  |     trajectory.push(rainbowified); | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Draw the rainbow. | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.drawRainbow = function(){ | |||
|  |   var self = this; | |||
|  | 
 | |||
|  |   this.trajectories.forEach(function(line, index) { | |||
|  |     write('\u001b[' + self.scoreboardWidth + 'C'); | |||
|  |     write(line.join('')); | |||
|  |     write('\n'); | |||
|  |   }); | |||
|  | 
 | |||
|  |   this.cursorUp(this.numberOfLines); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Draw the nyan cat | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.drawNyanCat = function() { | |||
|  |   var self = this; | |||
|  |   var startWidth = this.scoreboardWidth + this.trajectories[0].length; | |||
|  |   var color = '\u001b[' + startWidth + 'C'; | |||
|  |   var padding = ''; | |||
|  | 
 | |||
|  |   write(color); | |||
|  |   write('_,------,'); | |||
|  |   write('\n'); | |||
|  | 
 | |||
|  |   write(color); | |||
|  |   padding = self.tick ? '  ' : '   '; | |||
|  |   write('_|' + padding + '/\\_/\\ '); | |||
|  |   write('\n'); | |||
|  | 
 | |||
|  |   write(color); | |||
|  |   padding = self.tick ? '_' : '__'; | |||
|  |   var tail = self.tick ? '~' : '^'; | |||
|  |   var face; | |||
|  |   write(tail + '|' + padding + this.face() + ' '); | |||
|  |   write('\n'); | |||
|  | 
 | |||
|  |   write(color); | |||
|  |   padding = self.tick ? ' ' : '  '; | |||
|  |   write(padding + '""  "" '); | |||
|  |   write('\n'); | |||
|  | 
 | |||
|  |   this.cursorUp(this.numberOfLines); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Draw nyan cat face. | |||
|  |  * | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.face = function() { | |||
|  |   var stats = this.stats; | |||
|  |   if (stats.failures) { | |||
|  |     return '( x .x)'; | |||
|  |   } else if (stats.pending) { | |||
|  |     return '( o .o)'; | |||
|  |   } else if(stats.passes) { | |||
|  |     return '( ^ .^)'; | |||
|  |   } else { | |||
|  |     return '( - .-)'; | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Move cursor up `n`. | |||
|  |  * | |||
|  |  * @param {Number} n | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.cursorUp = function(n) { | |||
|  |   write('\u001b[' + n + 'A'); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Move cursor down `n`. | |||
|  |  * | |||
|  |  * @param {Number} n | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.cursorDown = function(n) { | |||
|  |   write('\u001b[' + n + 'B'); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Generate rainbow colors. | |||
|  |  * | |||
|  |  * @return {Array} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.generateColors = function(){ | |||
|  |   var colors = []; | |||
|  | 
 | |||
|  |   for (var i = 0; i < (6 * 7); i++) { | |||
|  |     var pi3 = Math.floor(Math.PI / 3); | |||
|  |     var n = (i * (1.0 / 6)); | |||
|  |     var r = Math.floor(3 * Math.sin(n) + 3); | |||
|  |     var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); | |||
|  |     var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); | |||
|  |     colors.push(36 * r + 6 * g + b + 16); | |||
|  |   } | |||
|  | 
 | |||
|  |   return colors; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Apply rainbow to the given `str`. | |||
|  |  * | |||
|  |  * @param {String} str | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | NyanCat.prototype.rainbowify = function(str){ | |||
|  |   var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; | |||
|  |   this.colorIndex += 1; | |||
|  |   return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Stdout helper. | |||
|  |  */ | |||
|  | 
 | |||
|  | function write(string) { | |||
|  |   process.stdout.write(string); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Base.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Base.prototype; | |||
|  | NyanCat.prototype = new F; | |||
|  | NyanCat.prototype.constructor = NyanCat; | |||
|  | 
 | |||
|  | 
 | |||
|  | }); // module: reporters/nyan.js
 | |||
|  | 
 | |||
|  | require.register("reporters/progress.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , cursor = Base.cursor | |||
|  |   , color = Base.color; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Progress`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Progress; | |||
|  | 
 | |||
|  | /** | |||
|  |  * General progress bar color. | |||
|  |  */ | |||
|  | 
 | |||
|  | Base.colors.progress = 90; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Progress` bar test reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @param {Object} options | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Progress(runner, options) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , options = options || {} | |||
|  |     , stats = this.stats | |||
|  |     , width = Base.window.width * .50 | 0 | |||
|  |     , total = runner.total | |||
|  |     , complete = 0 | |||
|  |     , max = Math.max; | |||
|  | 
 | |||
|  |   // default chars
 | |||
|  |   options.open = options.open || '['; | |||
|  |   options.complete = options.complete || '▬'; | |||
|  |   options.incomplete = options.incomplete || Base.symbols.dot; | |||
|  |   options.close = options.close || ']'; | |||
|  |   options.verbose = false; | |||
|  | 
 | |||
|  |   // tests started
 | |||
|  |   runner.on('start', function(){ | |||
|  |     console.log(); | |||
|  |     cursor.hide(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   // tests complete
 | |||
|  |   runner.on('test end', function(){ | |||
|  |     complete++; | |||
|  |     var incomplete = total - complete | |||
|  |       , percent = complete / total | |||
|  |       , n = width * percent | 0 | |||
|  |       , i = width - n; | |||
|  | 
 | |||
|  |     cursor.CR(); | |||
|  |     process.stdout.write('\u001b[J'); | |||
|  |     process.stdout.write(color('progress', '  ' + options.open)); | |||
|  |     process.stdout.write(Array(n).join(options.complete)); | |||
|  |     process.stdout.write(Array(i).join(options.incomplete)); | |||
|  |     process.stdout.write(color('progress', options.close)); | |||
|  |     if (options.verbose) { | |||
|  |       process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); | |||
|  |     } | |||
|  |   }); | |||
|  | 
 | |||
|  |   // tests are complete, output some stats
 | |||
|  |   // and the failures if any
 | |||
|  |   runner.on('end', function(){ | |||
|  |     cursor.show(); | |||
|  |     console.log(); | |||
|  |     self.epilogue(); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Base.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Base.prototype; | |||
|  | Progress.prototype = new F; | |||
|  | Progress.prototype.constructor = Progress; | |||
|  | 
 | |||
|  | 
 | |||
|  | }); // module: reporters/progress.js
 | |||
|  | 
 | |||
|  | require.register("reporters/spec.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , cursor = Base.cursor | |||
|  |   , color = Base.color; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Spec`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Spec; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Spec` test reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Spec(runner) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , indents = 0 | |||
|  |     , n = 0; | |||
|  | 
 | |||
|  |   function indent() { | |||
|  |     return Array(indents).join('  ') | |||
|  |   } | |||
|  | 
 | |||
|  |   runner.on('start', function(){ | |||
|  |     console.log(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('suite', function(suite){ | |||
|  |     ++indents; | |||
|  |     console.log(color('suite', '%s%s'), indent(), suite.title); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('suite end', function(suite){ | |||
|  |     --indents; | |||
|  |     if (1 == indents) console.log(); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('test', function(test){ | |||
|  |     process.stdout.write(indent() + color('pass', '  ◦ ' + test.title + ': ')); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pending', function(test){ | |||
|  |     var fmt = indent() + color('pending', '  - %s'); | |||
|  |     console.log(fmt, test.title); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     if ('fast' == test.speed) { | |||
|  |       var fmt = indent() | |||
|  |         + color('checkmark', '  ' + Base.symbols.ok) | |||
|  |         + color('pass', ' %s '); | |||
|  |       cursor.CR(); | |||
|  |       console.log(fmt, test.title); | |||
|  |     } else { | |||
|  |       var fmt = indent() | |||
|  |         + color('checkmark', '  ' + Base.symbols.ok) | |||
|  |         + color('pass', ' %s ') | |||
|  |         + color(test.speed, '(%dms)'); | |||
|  |       cursor.CR(); | |||
|  |       console.log(fmt, test.title, test.duration); | |||
|  |     } | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test, err){ | |||
|  |     cursor.CR(); | |||
|  |     console.log(indent() + color('fail', '  %d) %s'), ++n, test.title); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', self.epilogue.bind(self)); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Base.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Base.prototype; | |||
|  | Spec.prototype = new F; | |||
|  | Spec.prototype.constructor = Spec; | |||
|  | 
 | |||
|  | 
 | |||
|  | }); // module: reporters/spec.js
 | |||
|  | 
 | |||
|  | require.register("reporters/tap.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , cursor = Base.cursor | |||
|  |   , color = Base.color; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `TAP`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = TAP; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `TAP` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function TAP(runner) { | |||
|  |   Base.call(this, runner); | |||
|  | 
 | |||
|  |   var self = this | |||
|  |     , stats = this.stats | |||
|  |     , n = 1 | |||
|  |     , passes = 0 | |||
|  |     , failures = 0; | |||
|  | 
 | |||
|  |   runner.on('start', function(){ | |||
|  |     var total = runner.grepTotal(runner.suite); | |||
|  |     console.log('%d..%d', 1, total); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('test end', function(){ | |||
|  |     ++n; | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pending', function(test){ | |||
|  |     console.log('ok %d %s # SKIP -', n, title(test)); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     passes++; | |||
|  |     console.log('ok %d %s', n, title(test)); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test, err){ | |||
|  |     failures++; | |||
|  |     console.log('not ok %d %s', n, title(test)); | |||
|  |     if (err.stack) console.log(err.stack.replace(/^/gm, '  ')); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     console.log('# tests ' + (passes + failures)); | |||
|  |     console.log('# pass ' + passes); | |||
|  |     console.log('# fail ' + failures); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return a TAP-safe title of `test` | |||
|  |  * | |||
|  |  * @param {Object} test | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function title(test) { | |||
|  |   return test.fullTitle().replace(/#/g, ''); | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: reporters/tap.js
 | |||
|  | 
 | |||
|  | require.register("reporters/teamcity.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Teamcity`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Teamcity; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Teamcity` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Teamcity(runner) { | |||
|  |   Base.call(this, runner); | |||
|  |   var stats = this.stats; | |||
|  | 
 | |||
|  |   runner.on('start', function() { | |||
|  |     console.log("##teamcity[testSuiteStarted name='mocha.suite']"); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('test', function(test) { | |||
|  |     console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']"); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test, err) { | |||
|  |     console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']"); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('pending', function(test) { | |||
|  |     console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('test end', function(test) { | |||
|  |     console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']"); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function() { | |||
|  |     console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Escape the given `str`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function escape(str) { | |||
|  |   return str | |||
|  |     .replace(/\|/g, "||") | |||
|  |     .replace(/\n/g, "|n") | |||
|  |     .replace(/\r/g, "|r") | |||
|  |     .replace(/\[/g, "|[") | |||
|  |     .replace(/\]/g, "|]") | |||
|  |     .replace(/\u0085/g, "|x") | |||
|  |     .replace(/\u2028/g, "|l") | |||
|  |     .replace(/\u2029/g, "|p") | |||
|  |     .replace(/'/g, "|'"); | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: reporters/teamcity.js
 | |||
|  | 
 | |||
|  | require.register("reporters/xunit.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Base = require('./base') | |||
|  |   , utils = require('../utils') | |||
|  |   , escape = utils.escape; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Save timer references to avoid Sinon interfering (see GH-237). | |||
|  |  */ | |||
|  | 
 | |||
|  | var Date = global.Date | |||
|  |   , setTimeout = global.setTimeout | |||
|  |   , setInterval = global.setInterval | |||
|  |   , clearTimeout = global.clearTimeout | |||
|  |   , clearInterval = global.clearInterval; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `XUnit`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = XUnit; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `XUnit` reporter. | |||
|  |  * | |||
|  |  * @param {Runner} runner | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function XUnit(runner) { | |||
|  |   Base.call(this, runner); | |||
|  |   var stats = this.stats | |||
|  |     , tests = [] | |||
|  |     , self = this; | |||
|  | 
 | |||
|  |   runner.on('pass', function(test){ | |||
|  |     tests.push(test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('fail', function(test){ | |||
|  |     tests.push(test); | |||
|  |   }); | |||
|  | 
 | |||
|  |   runner.on('end', function(){ | |||
|  |     console.log(tag('testsuite', { | |||
|  |         name: 'Mocha Tests' | |||
|  |       , tests: stats.tests | |||
|  |       , failures: stats.failures | |||
|  |       , errors: stats.failures | |||
|  |       , skipped: stats.tests - stats.failures - stats.passes | |||
|  |       , timestamp: (new Date).toUTCString() | |||
|  |       , time: (stats.duration / 1000) || 0 | |||
|  |     }, false)); | |||
|  | 
 | |||
|  |     tests.forEach(test); | |||
|  |     console.log('</testsuite>'); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Base.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Base.prototype; | |||
|  | XUnit.prototype = new F; | |||
|  | XUnit.prototype.constructor = XUnit; | |||
|  | 
 | |||
|  | 
 | |||
|  | /** | |||
|  |  * Output tag for the given `test.` | |||
|  |  */ | |||
|  | 
 | |||
|  | function test(test) { | |||
|  |   var attrs = { | |||
|  |       classname: test.parent.fullTitle() | |||
|  |     , name: test.title | |||
|  |     , time: test.duration / 1000 | |||
|  |   }; | |||
|  | 
 | |||
|  |   if ('failed' == test.state) { | |||
|  |     var err = test.err; | |||
|  |     attrs.message = escape(err.message); | |||
|  |     console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); | |||
|  |   } else if (test.pending) { | |||
|  |     console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); | |||
|  |   } else { | |||
|  |     console.log(tag('testcase', attrs, true) ); | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * HTML tag helper. | |||
|  |  */ | |||
|  | 
 | |||
|  | function tag(name, attrs, close, content) { | |||
|  |   var end = close ? '/>' : '>' | |||
|  |     , pairs = [] | |||
|  |     , tag; | |||
|  | 
 | |||
|  |   for (var key in attrs) { | |||
|  |     pairs.push(key + '="' + escape(attrs[key]) + '"'); | |||
|  |   } | |||
|  | 
 | |||
|  |   tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; | |||
|  |   if (content) tag += content + '</' + name + end; | |||
|  |   return tag; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return cdata escaped CDATA `str`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function cdata(str) { | |||
|  |   return '<![CDATA[' + escape(str) + ']]>'; | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: reporters/xunit.js
 | |||
|  | 
 | |||
|  | require.register("runnable.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var EventEmitter = require('browser/events').EventEmitter | |||
|  |   , debug = require('browser/debug')('mocha:runnable') | |||
|  |   , milliseconds = require('./ms'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Save timer references to avoid Sinon interfering (see GH-237). | |||
|  |  */ | |||
|  | 
 | |||
|  | var Date = global.Date | |||
|  |   , setTimeout = global.setTimeout | |||
|  |   , setInterval = global.setInterval | |||
|  |   , clearTimeout = global.clearTimeout | |||
|  |   , clearInterval = global.clearInterval; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Object#toString(). | |||
|  |  */ | |||
|  | 
 | |||
|  | var toString = Object.prototype.toString; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Runnable`. | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = Runnable; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Runnable` with the given `title` and callback `fn`. | |||
|  |  * | |||
|  |  * @param {String} title | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function Runnable(title, fn) { | |||
|  |   this.title = title; | |||
|  |   this.fn = fn; | |||
|  |   this.async = fn && fn.length; | |||
|  |   this.sync = ! this.async; | |||
|  |   this._timeout = 2000; | |||
|  |   this._slow = 75; | |||
|  |   this.timedOut = false; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `EventEmitter.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = EventEmitter.prototype; | |||
|  | Runnable.prototype = new F; | |||
|  | Runnable.prototype.constructor = Runnable; | |||
|  | 
 | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set & get timeout `ms`. | |||
|  |  * | |||
|  |  * @param {Number|String} ms | |||
|  |  * @return {Runnable|Number} ms or self | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runnable.prototype.timeout = function(ms){ | |||
|  |   if (0 == arguments.length) return this._timeout; | |||
|  |   if ('string' == typeof ms) ms = milliseconds(ms); | |||
|  |   debug('timeout %d', ms); | |||
|  |   this._timeout = ms; | |||
|  |   if (this.timer) this.resetTimeout(); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set & get slow `ms`. | |||
|  |  * | |||
|  |  * @param {Number|String} ms | |||
|  |  * @return {Runnable|Number} ms or self | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runnable.prototype.slow = function(ms){ | |||
|  |   if (0 === arguments.length) return this._slow; | |||
|  |   if ('string' == typeof ms) ms = milliseconds(ms); | |||
|  |   debug('timeout %d', ms); | |||
|  |   this._slow = ms; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return the full title generated by recursively | |||
|  |  * concatenating the parent's full title. | |||
|  |  * | |||
|  |  * @return {String} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Runnable.prototype.fullTitle = function(){ | |||
|  |   return this.parent.fullTitle() + ' ' + this.title; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Clear the timeout. | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runnable.prototype.clearTimeout = function(){ | |||
|  |   clearTimeout(this.timer); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inspect the runnable void of private properties. | |||
|  |  * | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runnable.prototype.inspect = function(){ | |||
|  |   return JSON.stringify(this, function(key, val){ | |||
|  |     if ('_' == key[0]) return; | |||
|  |     if ('parent' == key) return '#<Suite>'; | |||
|  |     if ('ctx' == key) return '#<Context>'; | |||
|  |     return val; | |||
|  |   }, 2); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Reset the timeout. | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runnable.prototype.resetTimeout = function(){ | |||
|  |   var self = this; | |||
|  |   var ms = this.timeout() || 1e9; | |||
|  | 
 | |||
|  |   this.clearTimeout(); | |||
|  |   this.timer = setTimeout(function(){ | |||
|  |     self.callback(new Error('timeout of ' + ms + 'ms exceeded')); | |||
|  |     self.timedOut = true; | |||
|  |   }, ms); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run the test and invoke `fn(err)`. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runnable.prototype.run = function(fn){ | |||
|  |   var self = this | |||
|  |     , ms = this.timeout() | |||
|  |     , start = new Date | |||
|  |     , ctx = this.ctx | |||
|  |     , finished | |||
|  |     , emitted; | |||
|  | 
 | |||
|  |   if (ctx) ctx.runnable(this); | |||
|  | 
 | |||
|  |   // timeout
 | |||
|  |   if (this.async) { | |||
|  |     if (ms) { | |||
|  |       this.timer = setTimeout(function(){ | |||
|  |         done(new Error('timeout of ' + ms + 'ms exceeded')); | |||
|  |         self.timedOut = true; | |||
|  |       }, ms); | |||
|  |     } | |||
|  |   } | |||
|  | 
 | |||
|  |   // called multiple times
 | |||
|  |   function multiple(err) { | |||
|  |     if (emitted) return; | |||
|  |     emitted = true; | |||
|  |     self.emit('error', err || new Error('done() called multiple times')); | |||
|  |   } | |||
|  | 
 | |||
|  |   // finished
 | |||
|  |   function done(err) { | |||
|  |     if (self.timedOut) return; | |||
|  |     if (finished) return multiple(err); | |||
|  |     self.clearTimeout(); | |||
|  |     self.duration = new Date - start; | |||
|  |     finished = true; | |||
|  |     fn(err); | |||
|  |   } | |||
|  | 
 | |||
|  |   // for .resetTimeout()
 | |||
|  |   this.callback = done; | |||
|  | 
 | |||
|  |   // async
 | |||
|  |   if (this.async) { | |||
|  |     try { | |||
|  |       this.fn.call(ctx, function(err){ | |||
|  |         if (err instanceof Error || toString.call(err) === "[object Error]") return done(err); | |||
|  |         if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); | |||
|  |         done(); | |||
|  |       }); | |||
|  |     } catch (err) { | |||
|  |       done(err); | |||
|  |     } | |||
|  |     return; | |||
|  |   } | |||
|  | 
 | |||
|  |   if (this.asyncOnly) { | |||
|  |     return done(new Error('--async-only option in use without declaring `done()`')); | |||
|  |   } | |||
|  | 
 | |||
|  |   // sync
 | |||
|  |   try { | |||
|  |     if (!this.pending) this.fn.call(ctx); | |||
|  |     this.duration = new Date - start; | |||
|  |     fn(); | |||
|  |   } catch (err) { | |||
|  |     fn(err); | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: runnable.js
 | |||
|  | 
 | |||
|  | require.register("runner.js", function(module, exports, require){ | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var EventEmitter = require('browser/events').EventEmitter | |||
|  |   , debug = require('browser/debug')('mocha:runner') | |||
|  |   , Test = require('./test') | |||
|  |   , utils = require('./utils') | |||
|  |   , filter = utils.filter | |||
|  |   , keys = utils.keys; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Non-enumerable globals. | |||
|  |  */ | |||
|  | 
 | |||
|  | var globals = [ | |||
|  |   'setTimeout', | |||
|  |   'clearTimeout', | |||
|  |   'setInterval', | |||
|  |   'clearInterval', | |||
|  |   'XMLHttpRequest', | |||
|  |   'Date' | |||
|  | ]; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Runner`. | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = Runner; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a `Runner` for the given `suite`. | |||
|  |  * | |||
|  |  * Events: | |||
|  |  * | |||
|  |  *   - `start`  execution started | |||
|  |  *   - `end`  execution complete | |||
|  |  *   - `suite`  (suite) test suite execution started | |||
|  |  *   - `suite end`  (suite) all tests (and sub-suites) have finished | |||
|  |  *   - `test`  (test) test execution started | |||
|  |  *   - `test end`  (test) test completed | |||
|  |  *   - `hook`  (hook) hook execution started | |||
|  |  *   - `hook end`  (hook) hook complete | |||
|  |  *   - `pass`  (test) test passed | |||
|  |  *   - `fail`  (test, err) test failed | |||
|  |  *   - `pending`  (test) test pending | |||
|  |  * | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | function Runner(suite) { | |||
|  |   var self = this; | |||
|  |   this._globals = []; | |||
|  |   this.suite = suite; | |||
|  |   this.total = suite.total(); | |||
|  |   this.failures = 0; | |||
|  |   this.on('test end', function(test){ self.checkGlobals(test); }); | |||
|  |   this.on('hook end', function(hook){ self.checkGlobals(hook); }); | |||
|  |   this.grep(/.*/); | |||
|  |   this.globals(this.globalProps().concat(['errno'])); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Wrapper for setImmediate, process.nextTick, or browser polyfill. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.immediately = global.setImmediate || process.nextTick; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `EventEmitter.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = EventEmitter.prototype; | |||
|  | Runner.prototype = new F; | |||
|  | Runner.prototype.constructor = Runner; | |||
|  | 
 | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run tests with full titles matching `re`. Updates runner.total | |||
|  |  * with number of tests matched. | |||
|  |  * | |||
|  |  * @param {RegExp} re | |||
|  |  * @param {Boolean} invert | |||
|  |  * @return {Runner} for chaining | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.grep = function(re, invert){ | |||
|  |   debug('grep %s', re); | |||
|  |   this._grep = re; | |||
|  |   this._invert = invert; | |||
|  |   this.total = this.grepTotal(this.suite); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Returns the number of tests matching the grep search for the | |||
|  |  * given suite. | |||
|  |  * | |||
|  |  * @param {Suite} suite | |||
|  |  * @return {Number} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.grepTotal = function(suite) { | |||
|  |   var self = this; | |||
|  |   var total = 0; | |||
|  | 
 | |||
|  |   suite.eachTest(function(test){ | |||
|  |     var match = self._grep.test(test.fullTitle()); | |||
|  |     if (self._invert) match = !match; | |||
|  |     if (match) total++; | |||
|  |   }); | |||
|  | 
 | |||
|  |   return total; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return a list of global properties. | |||
|  |  * | |||
|  |  * @return {Array} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.globalProps = function() { | |||
|  |   var props = utils.keys(global); | |||
|  | 
 | |||
|  |   // non-enumerables
 | |||
|  |   for (var i = 0; i < globals.length; ++i) { | |||
|  |     if (~utils.indexOf(props, globals[i])) continue; | |||
|  |     props.push(globals[i]); | |||
|  |   } | |||
|  | 
 | |||
|  |   return props; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Allow the given `arr` of globals. | |||
|  |  * | |||
|  |  * @param {Array} arr | |||
|  |  * @return {Runner} for chaining | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.globals = function(arr){ | |||
|  |   if (0 == arguments.length) return this._globals; | |||
|  |   debug('globals %j', arr); | |||
|  |   utils.forEach(arr, function(arr){ | |||
|  |     this._globals.push(arr); | |||
|  |   }, this); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Check for global variable leaks. | |||
|  |  * | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.checkGlobals = function(test){ | |||
|  |   if (this.ignoreLeaks) return; | |||
|  |   var ok = this._globals; | |||
|  |   var globals = this.globalProps(); | |||
|  |   var isNode = process.kill; | |||
|  |   var leaks; | |||
|  | 
 | |||
|  |   // check length - 2 ('errno' and 'location' globals)
 | |||
|  |   if (isNode && 1 == ok.length - globals.length) return; | |||
|  |   else if (2 == ok.length - globals.length) return; | |||
|  | 
 | |||
|  |   if(this.prevGlobalsLength == globals.length) return; | |||
|  |   this.prevGlobalsLength = globals.length; | |||
|  | 
 | |||
|  |   //console.time('filterLeaksTime');
 | |||
|  |   leaks = filterLeaks(ok, globals); | |||
|  |   //console.timeEnd('filterLeaksTime');
 | |||
|  |   this._globals = this._globals.concat(leaks); | |||
|  | 
 | |||
|  |   if (leaks.length > 1) { | |||
|  |     this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); | |||
|  |   } else if (leaks.length) { | |||
|  |     this.fail(test, new Error('global leak detected: ' + leaks[0])); | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Fail the given `test`. | |||
|  |  * | |||
|  |  * @param {Test} test | |||
|  |  * @param {Error} err | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.fail = function(test, err){ | |||
|  |   ++this.failures; | |||
|  |   test.state = 'failed'; | |||
|  | 
 | |||
|  |   if ('string' == typeof err) { | |||
|  |     err = new Error('the string "' + err + '" was thrown, throw an Error :)'); | |||
|  |   } | |||
|  | 
 | |||
|  |   this.emit('fail', test, err); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Fail the given `hook` with `err`. | |||
|  |  * | |||
|  |  * Hook failures (currently) hard-end due | |||
|  |  * to that fact that a failing hook will | |||
|  |  * surely cause subsequent tests to fail, | |||
|  |  * causing jumbled reporting. | |||
|  |  * | |||
|  |  * @param {Hook} hook | |||
|  |  * @param {Error} err | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.failHook = function(hook, err){ | |||
|  |   this.fail(hook, err); | |||
|  |   this.emit('end'); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run hook `name` callbacks and then invoke `fn()`. | |||
|  |  * | |||
|  |  * @param {String} name | |||
|  |  * @param {Function} function | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.hook = function(name, fn){ | |||
|  |   var suite = this.suite | |||
|  |     , hooks = suite['_' + name] | |||
|  |     , self = this | |||
|  |     , timer; | |||
|  | 
 | |||
|  |   function next(i) { | |||
|  |     var hook = hooks[i]; | |||
|  |     if (!hook) return fn(); | |||
|  |     if (self.failures && suite.bail()) return fn(); | |||
|  |     self.currentRunnable = hook; | |||
|  | 
 | |||
|  |     hook.ctx.currentTest = self.test; | |||
|  | 
 | |||
|  |     self.emit('hook', hook); | |||
|  | 
 | |||
|  |     hook.on('error', function(err){ | |||
|  |       self.failHook(hook, err); | |||
|  |     }); | |||
|  | 
 | |||
|  |     hook.run(function(err){ | |||
|  |       hook.removeAllListeners('error'); | |||
|  |       var testError = hook.error(); | |||
|  |       if (testError) self.fail(self.test, testError); | |||
|  |       if (err) return self.failHook(hook, err); | |||
|  |       self.emit('hook end', hook); | |||
|  |       delete hook.ctx.currentTest; | |||
|  |       next(++i); | |||
|  |     }); | |||
|  |   } | |||
|  | 
 | |||
|  |   Runner.immediately(function(){ | |||
|  |     next(0); | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run hook `name` for the given array of `suites` | |||
|  |  * in order, and callback `fn(err)`. | |||
|  |  * | |||
|  |  * @param {String} name | |||
|  |  * @param {Array} suites | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.hooks = function(name, suites, fn){ | |||
|  |   var self = this | |||
|  |     , orig = this.suite; | |||
|  | 
 | |||
|  |   function next(suite) { | |||
|  |     self.suite = suite; | |||
|  | 
 | |||
|  |     if (!suite) { | |||
|  |       self.suite = orig; | |||
|  |       return fn(); | |||
|  |     } | |||
|  | 
 | |||
|  |     self.hook(name, function(err){ | |||
|  |       if (err) { | |||
|  |         self.suite = orig; | |||
|  |         return fn(err); | |||
|  |       } | |||
|  | 
 | |||
|  |       next(suites.pop()); | |||
|  |     }); | |||
|  |   } | |||
|  | 
 | |||
|  |   next(suites.pop()); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run hooks from the top level down. | |||
|  |  * | |||
|  |  * @param {String} name | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.hookUp = function(name, fn){ | |||
|  |   var suites = [this.suite].concat(this.parents()).reverse(); | |||
|  |   this.hooks(name, suites, fn); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run hooks from the bottom up. | |||
|  |  * | |||
|  |  * @param {String} name | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.hookDown = function(name, fn){ | |||
|  |   var suites = [this.suite].concat(this.parents()); | |||
|  |   this.hooks(name, suites, fn); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return an array of parent Suites from | |||
|  |  * closest to furthest. | |||
|  |  * | |||
|  |  * @return {Array} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.parents = function(){ | |||
|  |   var suite = this.suite | |||
|  |     , suites = []; | |||
|  |   while (suite = suite.parent) suites.push(suite); | |||
|  |   return suites; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run the current test and callback `fn(err)`. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.runTest = function(fn){ | |||
|  |   var test = this.test | |||
|  |     , self = this; | |||
|  | 
 | |||
|  |   if (this.asyncOnly) test.asyncOnly = true; | |||
|  | 
 | |||
|  |   try { | |||
|  |     test.on('error', function(err){ | |||
|  |       self.fail(test, err); | |||
|  |     }); | |||
|  |     test.run(fn); | |||
|  |   } catch (err) { | |||
|  |     fn(err); | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run tests in the given `suite` and invoke | |||
|  |  * the callback `fn()` when complete. | |||
|  |  * | |||
|  |  * @param {Suite} suite | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.runTests = function(suite, fn){ | |||
|  |   var self = this | |||
|  |     , tests = suite.tests.slice() | |||
|  |     , test; | |||
|  | 
 | |||
|  |   function next(err) { | |||
|  |     // if we bail after first err
 | |||
|  |     if (self.failures && suite._bail) return fn(); | |||
|  | 
 | |||
|  |     // next test
 | |||
|  |     test = tests.shift(); | |||
|  | 
 | |||
|  |     // all done
 | |||
|  |     if (!test) return fn(); | |||
|  | 
 | |||
|  |     // grep
 | |||
|  |     var match = self._grep.test(test.fullTitle()); | |||
|  |     if (self._invert) match = !match; | |||
|  |     if (!match) return next(); | |||
|  | 
 | |||
|  |     // pending
 | |||
|  |     if (test.pending) { | |||
|  |       self.emit('pending', test); | |||
|  |       self.emit('test end', test); | |||
|  |       return next(); | |||
|  |     } | |||
|  | 
 | |||
|  |     // execute test and hook(s)
 | |||
|  |     self.emit('test', self.test = test); | |||
|  |     self.hookDown('beforeEach', function(){ | |||
|  |       self.currentRunnable = self.test; | |||
|  |       self.runTest(function(err){ | |||
|  |         test = self.test; | |||
|  | 
 | |||
|  |         if (err) { | |||
|  |           self.fail(test, err); | |||
|  |           self.emit('test end', test); | |||
|  |           return self.hookUp('afterEach', next); | |||
|  |         } | |||
|  | 
 | |||
|  |         test.state = 'passed'; | |||
|  |         self.emit('pass', test); | |||
|  |         self.emit('test end', test); | |||
|  |         self.hookUp('afterEach', next); | |||
|  |       }); | |||
|  |     }); | |||
|  |   } | |||
|  | 
 | |||
|  |   this.next = next; | |||
|  |   next(); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run the given `suite` and invoke the | |||
|  |  * callback `fn()` when complete. | |||
|  |  * | |||
|  |  * @param {Suite} suite | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.runSuite = function(suite, fn){ | |||
|  |   var total = this.grepTotal(suite) | |||
|  |     , self = this | |||
|  |     , i = 0; | |||
|  | 
 | |||
|  |   debug('run suite %s', suite.fullTitle()); | |||
|  | 
 | |||
|  |   if (!total) return fn(); | |||
|  | 
 | |||
|  |   this.emit('suite', this.suite = suite); | |||
|  | 
 | |||
|  |   function next() { | |||
|  |     var curr = suite.suites[i++]; | |||
|  |     if (!curr) return done(); | |||
|  |     self.runSuite(curr, next); | |||
|  |   } | |||
|  | 
 | |||
|  |   function done() { | |||
|  |     self.suite = suite; | |||
|  |     self.hook('afterAll', function(){ | |||
|  |       self.emit('suite end', suite); | |||
|  |       fn(); | |||
|  |     }); | |||
|  |   } | |||
|  | 
 | |||
|  |   this.hook('beforeAll', function(){ | |||
|  |     self.runTests(suite, next); | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Handle uncaught exceptions. | |||
|  |  * | |||
|  |  * @param {Error} err | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.uncaught = function(err){ | |||
|  |   debug('uncaught exception %s', err.message); | |||
|  |   var runnable = this.currentRunnable; | |||
|  |   if (!runnable || 'failed' == runnable.state) return; | |||
|  |   runnable.clearTimeout(); | |||
|  |   err.uncaught = true; | |||
|  |   this.fail(runnable, err); | |||
|  | 
 | |||
|  |   // recover from test
 | |||
|  |   if ('test' == runnable.type) { | |||
|  |     this.emit('test end', runnable); | |||
|  |     this.hookUp('afterEach', this.next); | |||
|  |     return; | |||
|  |   } | |||
|  | 
 | |||
|  |   // bail on hooks
 | |||
|  |   this.emit('end'); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run the root suite and invoke `fn(failures)` | |||
|  |  * on completion. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @return {Runner} for chaining | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Runner.prototype.run = function(fn){ | |||
|  |   var self = this | |||
|  |     , fn = fn || function(){}; | |||
|  | 
 | |||
|  |   function uncaught(err){ | |||
|  |     self.uncaught(err); | |||
|  |   } | |||
|  | 
 | |||
|  |   debug('start'); | |||
|  | 
 | |||
|  |   // callback
 | |||
|  |   this.on('end', function(){ | |||
|  |     debug('end'); | |||
|  |     process.removeListener('uncaughtException', uncaught); | |||
|  |     fn(self.failures); | |||
|  |   }); | |||
|  | 
 | |||
|  |   // run suites
 | |||
|  |   this.emit('start'); | |||
|  |   this.runSuite(this.suite, function(){ | |||
|  |     debug('finished running'); | |||
|  |     self.emit('end'); | |||
|  |   }); | |||
|  | 
 | |||
|  |   // uncaught exception
 | |||
|  |   process.on('uncaughtException', uncaught); | |||
|  | 
 | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Filter leaks with the given globals flagged as `ok`. | |||
|  |  * | |||
|  |  * @param {Array} ok | |||
|  |  * @param {Array} globals | |||
|  |  * @return {Array} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function filterLeaks(ok, globals) { | |||
|  |   return filter(globals, function(key){ | |||
|  |     // Firefox and Chrome exposes iframes as index inside the window object
 | |||
|  |     if (/^d+/.test(key)) return false; | |||
|  | 
 | |||
|  |     // in firefox
 | |||
|  |     // if runner runs in an iframe, this iframe's window.getInterface method not init at first
 | |||
|  |     // it is assigned in some seconds
 | |||
|  |     if (global.navigator && /^getInterface/.test(key)) return false; | |||
|  | 
 | |||
|  |     // an iframe could be approached by window[iframeIndex]
 | |||
|  |     // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak
 | |||
|  |     if (global.navigator && /^\d+/.test(key)) return false; | |||
|  | 
 | |||
|  |     // Opera and IE expose global variables for HTML element IDs (issue #243)
 | |||
|  |     if (/^mocha-/.test(key)) return false; | |||
|  | 
 | |||
|  |     var matched = filter(ok, function(ok){ | |||
|  |       if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); | |||
|  |       return key == ok; | |||
|  |     }); | |||
|  |     return matched.length == 0 && (!global.navigator || 'onerror' !== key); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | }); // module: runner.js
 | |||
|  | 
 | |||
|  | require.register("suite.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var EventEmitter = require('browser/events').EventEmitter | |||
|  |   , debug = require('browser/debug')('mocha:suite') | |||
|  |   , milliseconds = require('./ms') | |||
|  |   , utils = require('./utils') | |||
|  |   , Hook = require('./hook'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Suite`. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports = module.exports = Suite; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Create a new `Suite` with the given `title` | |||
|  |  * and parent `Suite`. When a suite with the | |||
|  |  * same title is already present, that suite | |||
|  |  * is returned to provide nicer reporter | |||
|  |  * and more flexible meta-testing. | |||
|  |  * | |||
|  |  * @param {Suite} parent | |||
|  |  * @param {String} title | |||
|  |  * @return {Suite} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.create = function(parent, title){ | |||
|  |   var suite = new Suite(title, parent.ctx); | |||
|  |   suite.parent = parent; | |||
|  |   if (parent.pending) suite.pending = true; | |||
|  |   title = suite.fullTitle(); | |||
|  |   parent.addSuite(suite); | |||
|  |   return suite; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Suite` with the given | |||
|  |  * `title` and `ctx`. | |||
|  |  * | |||
|  |  * @param {String} title | |||
|  |  * @param {Context} ctx | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function Suite(title, ctx) { | |||
|  |   this.title = title; | |||
|  |   this.ctx = ctx; | |||
|  |   this.suites = []; | |||
|  |   this.tests = []; | |||
|  |   this.pending = false; | |||
|  |   this._beforeEach = []; | |||
|  |   this._beforeAll = []; | |||
|  |   this._afterEach = []; | |||
|  |   this._afterAll = []; | |||
|  |   this.root = !title; | |||
|  |   this._timeout = 2000; | |||
|  |   this._slow = 75; | |||
|  |   this._bail = false; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `EventEmitter.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = EventEmitter.prototype; | |||
|  | Suite.prototype = new F; | |||
|  | Suite.prototype.constructor = Suite; | |||
|  | 
 | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return a clone of this `Suite`. | |||
|  |  * | |||
|  |  * @return {Suite} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.clone = function(){ | |||
|  |   var suite = new Suite(this.title); | |||
|  |   debug('clone'); | |||
|  |   suite.ctx = this.ctx; | |||
|  |   suite.timeout(this.timeout()); | |||
|  |   suite.slow(this.slow()); | |||
|  |   suite.bail(this.bail()); | |||
|  |   return suite; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set timeout `ms` or short-hand such as "2s". | |||
|  |  * | |||
|  |  * @param {Number|String} ms | |||
|  |  * @return {Suite|Number} for chaining | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.timeout = function(ms){ | |||
|  |   if (0 == arguments.length) return this._timeout; | |||
|  |   if ('string' == typeof ms) ms = milliseconds(ms); | |||
|  |   debug('timeout %d', ms); | |||
|  |   this._timeout = parseInt(ms, 10); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Set slow `ms` or short-hand such as "2s". | |||
|  |  * | |||
|  |  * @param {Number|String} ms | |||
|  |  * @return {Suite|Number} for chaining | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.slow = function(ms){ | |||
|  |   if (0 === arguments.length) return this._slow; | |||
|  |   if ('string' == typeof ms) ms = milliseconds(ms); | |||
|  |   debug('slow %d', ms); | |||
|  |   this._slow = ms; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Sets whether to bail after first error. | |||
|  |  * | |||
|  |  * @parma {Boolean} bail | |||
|  |  * @return {Suite|Number} for chaining | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.bail = function(bail){ | |||
|  |   if (0 == arguments.length) return this._bail; | |||
|  |   debug('bail %s', bail); | |||
|  |   this._bail = bail; | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run `fn(test[, done])` before running tests. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @return {Suite} for chaining | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.beforeAll = function(fn){ | |||
|  |   if (this.pending) return this; | |||
|  |   var hook = new Hook('"before all" hook', fn); | |||
|  |   hook.parent = this; | |||
|  |   hook.timeout(this.timeout()); | |||
|  |   hook.slow(this.slow()); | |||
|  |   hook.ctx = this.ctx; | |||
|  |   this._beforeAll.push(hook); | |||
|  |   this.emit('beforeAll', hook); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run `fn(test[, done])` after running tests. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @return {Suite} for chaining | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.afterAll = function(fn){ | |||
|  |   if (this.pending) return this; | |||
|  |   var hook = new Hook('"after all" hook', fn); | |||
|  |   hook.parent = this; | |||
|  |   hook.timeout(this.timeout()); | |||
|  |   hook.slow(this.slow()); | |||
|  |   hook.ctx = this.ctx; | |||
|  |   this._afterAll.push(hook); | |||
|  |   this.emit('afterAll', hook); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run `fn(test[, done])` before each test case. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @return {Suite} for chaining | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.beforeEach = function(fn){ | |||
|  |   if (this.pending) return this; | |||
|  |   var hook = new Hook('"before each" hook', fn); | |||
|  |   hook.parent = this; | |||
|  |   hook.timeout(this.timeout()); | |||
|  |   hook.slow(this.slow()); | |||
|  |   hook.ctx = this.ctx; | |||
|  |   this._beforeEach.push(hook); | |||
|  |   this.emit('beforeEach', hook); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run `fn(test[, done])` after each test case. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @return {Suite} for chaining | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.afterEach = function(fn){ | |||
|  |   if (this.pending) return this; | |||
|  |   var hook = new Hook('"after each" hook', fn); | |||
|  |   hook.parent = this; | |||
|  |   hook.timeout(this.timeout()); | |||
|  |   hook.slow(this.slow()); | |||
|  |   hook.ctx = this.ctx; | |||
|  |   this._afterEach.push(hook); | |||
|  |   this.emit('afterEach', hook); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Add a test `suite`. | |||
|  |  * | |||
|  |  * @param {Suite} suite | |||
|  |  * @return {Suite} for chaining | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.addSuite = function(suite){ | |||
|  |   suite.parent = this; | |||
|  |   suite.timeout(this.timeout()); | |||
|  |   suite.slow(this.slow()); | |||
|  |   suite.bail(this.bail()); | |||
|  |   this.suites.push(suite); | |||
|  |   this.emit('suite', suite); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Add a `test` to this suite. | |||
|  |  * | |||
|  |  * @param {Test} test | |||
|  |  * @return {Suite} for chaining | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.addTest = function(test){ | |||
|  |   test.parent = this; | |||
|  |   test.timeout(this.timeout()); | |||
|  |   test.slow(this.slow()); | |||
|  |   test.ctx = this.ctx; | |||
|  |   this.tests.push(test); | |||
|  |   this.emit('test', test); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return the full title generated by recursively | |||
|  |  * concatenating the parent's full title. | |||
|  |  * | |||
|  |  * @return {String} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.fullTitle = function(){ | |||
|  |   if (this.parent) { | |||
|  |     var full = this.parent.fullTitle(); | |||
|  |     if (full) return full + ' ' + this.title; | |||
|  |   } | |||
|  |   return this.title; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Return the total number of tests. | |||
|  |  * | |||
|  |  * @return {Number} | |||
|  |  * @api public | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.total = function(){ | |||
|  |   return utils.reduce(this.suites, function(sum, suite){ | |||
|  |     return sum + suite.total(); | |||
|  |   }, 0) + this.tests.length; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Iterates through each suite recursively to find | |||
|  |  * all tests. Applies a function in the format | |||
|  |  * `fn(test)`. | |||
|  |  * | |||
|  |  * @param {Function} fn | |||
|  |  * @return {Suite} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | Suite.prototype.eachTest = function(fn){ | |||
|  |   utils.forEach(this.tests, fn); | |||
|  |   utils.forEach(this.suites, function(suite){ | |||
|  |     suite.eachTest(fn); | |||
|  |   }); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: suite.js
 | |||
|  | 
 | |||
|  | require.register("test.js", function(module, exports, require){ | |||
|  | 
 | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Runnable = require('./runnable'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose `Test`. | |||
|  |  */ | |||
|  | 
 | |||
|  | module.exports = Test; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Initialize a new `Test` with the given `title` and callback `fn`. | |||
|  |  * | |||
|  |  * @param {String} title | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function Test(title, fn) { | |||
|  |   Runnable.call(this, title, fn); | |||
|  |   this.pending = !fn; | |||
|  |   this.type = 'test'; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Inherit from `Runnable.prototype`. | |||
|  |  */ | |||
|  | 
 | |||
|  | function F(){}; | |||
|  | F.prototype = Runnable.prototype; | |||
|  | Test.prototype = new F; | |||
|  | Test.prototype.constructor = Test; | |||
|  | 
 | |||
|  | 
 | |||
|  | }); // module: test.js
 | |||
|  | 
 | |||
|  | require.register("utils.js", function(module, exports, require){ | |||
|  | /** | |||
|  |  * Module dependencies. | |||
|  |  */ | |||
|  | 
 | |||
|  | var fs = require('browser/fs') | |||
|  |   , path = require('browser/path') | |||
|  |   , join = path.join | |||
|  |   , debug = require('browser/debug')('mocha:watch'); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Ignored directories. | |||
|  |  */ | |||
|  | 
 | |||
|  | var ignore = ['node_modules', '.git']; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Escape special characters in the given string of html. | |||
|  |  * | |||
|  |  * @param  {String} html | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.escape = function(html){ | |||
|  |   return String(html) | |||
|  |     .replace(/&/g, '&') | |||
|  |     .replace(/"/g, '"') | |||
|  |     .replace(/</g, '<') | |||
|  |     .replace(/>/g, '>'); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Array#forEach (<=IE8) | |||
|  |  * | |||
|  |  * @param {Array} array | |||
|  |  * @param {Function} fn | |||
|  |  * @param {Object} scope | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.forEach = function(arr, fn, scope){ | |||
|  |   for (var i = 0, l = arr.length; i < l; i++) | |||
|  |     fn.call(scope, arr[i], i); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Array#indexOf (<=IE8) | |||
|  |  * | |||
|  |  * @parma {Array} arr | |||
|  |  * @param {Object} obj to find index of | |||
|  |  * @param {Number} start | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.indexOf = function(arr, obj, start){ | |||
|  |   for (var i = start || 0, l = arr.length; i < l; i++) { | |||
|  |     if (arr[i] === obj) | |||
|  |       return i; | |||
|  |   } | |||
|  |   return -1; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Array#reduce (<=IE8) | |||
|  |  * | |||
|  |  * @param {Array} array | |||
|  |  * @param {Function} fn | |||
|  |  * @param {Object} initial value | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.reduce = function(arr, fn, val){ | |||
|  |   var rval = val; | |||
|  | 
 | |||
|  |   for (var i = 0, l = arr.length; i < l; i++) { | |||
|  |     rval = fn(rval, arr[i], i, arr); | |||
|  |   } | |||
|  | 
 | |||
|  |   return rval; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Array#filter (<=IE8) | |||
|  |  * | |||
|  |  * @param {Array} array | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.filter = function(arr, fn){ | |||
|  |   var ret = []; | |||
|  | 
 | |||
|  |   for (var i = 0, l = arr.length; i < l; i++) { | |||
|  |     var val = arr[i]; | |||
|  |     if (fn(val, i, arr)) ret.push(val); | |||
|  |   } | |||
|  | 
 | |||
|  |   return ret; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Object.keys (<=IE8) | |||
|  |  * | |||
|  |  * @param {Object} obj | |||
|  |  * @return {Array} keys | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.keys = Object.keys || function(obj) { | |||
|  |   var keys = [] | |||
|  |     , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
 | |||
|  | 
 | |||
|  |   for (var key in obj) { | |||
|  |     if (has.call(obj, key)) { | |||
|  |       keys.push(key); | |||
|  |     } | |||
|  |   } | |||
|  | 
 | |||
|  |   return keys; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Watch the given `files` for changes | |||
|  |  * and invoke `fn(file)` on modification. | |||
|  |  * | |||
|  |  * @param {Array} files | |||
|  |  * @param {Function} fn | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.watch = function(files, fn){ | |||
|  |   var options = { interval: 100 }; | |||
|  |   files.forEach(function(file){ | |||
|  |     debug('file %s', file); | |||
|  |     fs.watchFile(file, options, function(curr, prev){ | |||
|  |       if (prev.mtime < curr.mtime) fn(file); | |||
|  |     }); | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Ignored files. | |||
|  |  */ | |||
|  | 
 | |||
|  | function ignored(path){ | |||
|  |   return !~ignore.indexOf(path); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Lookup files in the given `dir`. | |||
|  |  * | |||
|  |  * @return {Array} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.files = function(dir, ret){ | |||
|  |   ret = ret || []; | |||
|  | 
 | |||
|  |   fs.readdirSync(dir) | |||
|  |   .filter(ignored) | |||
|  |   .forEach(function(path){ | |||
|  |     path = join(dir, path); | |||
|  |     if (fs.statSync(path).isDirectory()) { | |||
|  |       exports.files(path, ret); | |||
|  |     } else if (path.match(/\.(js|coffee|litcoffee|coffee.md)$/)) { | |||
|  |       ret.push(path); | |||
|  |     } | |||
|  |   }); | |||
|  | 
 | |||
|  |   return ret; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Compute a slug from the given `str`. | |||
|  |  * | |||
|  |  * @param {String} str | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.slug = function(str){ | |||
|  |   return str | |||
|  |     .toLowerCase() | |||
|  |     .replace(/ +/g, '-') | |||
|  |     .replace(/[^-\w]/g, ''); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Strip the function definition from `str`, | |||
|  |  * and re-indent for pre whitespace. | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.clean = function(str) { | |||
|  |   str = str | |||
|  |     .replace(/^function *\(.*\) *{/, '') | |||
|  |     .replace(/\s+\}$/, ''); | |||
|  | 
 | |||
|  |   var whitespace = str.match(/^\n?(\s*)/)[1] | |||
|  |     , re = new RegExp('^' + whitespace, 'gm'); | |||
|  | 
 | |||
|  |   str = str.replace(re, ''); | |||
|  | 
 | |||
|  |   return exports.trim(str); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Escape regular expression characters in `str`. | |||
|  |  * | |||
|  |  * @param {String} str | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.escapeRegexp = function(str){ | |||
|  |   return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Trim the given `str`. | |||
|  |  * | |||
|  |  * @param {String} str | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.trim = function(str){ | |||
|  |   return str.replace(/^\s+|\s+$/g, ''); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Parse the given `qs`. | |||
|  |  * | |||
|  |  * @param {String} qs | |||
|  |  * @return {Object} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.parseQuery = function(qs){ | |||
|  |   return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ | |||
|  |     var i = pair.indexOf('=') | |||
|  |       , key = pair.slice(0, i) | |||
|  |       , val = pair.slice(++i); | |||
|  | 
 | |||
|  |     obj[key] = decodeURIComponent(val); | |||
|  |     return obj; | |||
|  |   }, {}); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Highlight the given string of `js`. | |||
|  |  * | |||
|  |  * @param {String} js | |||
|  |  * @return {String} | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | function highlight(js) { | |||
|  |   return js | |||
|  |     .replace(/</g, '<') | |||
|  |     .replace(/>/g, '>') | |||
|  |     .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>') | |||
|  |     .replace(/('.*?')/gm, '<span class="string">$1</span>') | |||
|  |     .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>') | |||
|  |     .replace(/(\d+)/gm, '<span class="number">$1</span>') | |||
|  |     .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>') | |||
|  |     .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>') | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Highlight the contents of tag `name`. | |||
|  |  * | |||
|  |  * @param {String} name | |||
|  |  * @api private | |||
|  |  */ | |||
|  | 
 | |||
|  | exports.highlightTags = function(name) { | |||
|  |   var code = document.getElementsByTagName(name); | |||
|  |   for (var i = 0, len = code.length; i < len; ++i) { | |||
|  |     code[i].innerHTML = highlight(code[i].innerHTML); | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | }); // module: utils.js
 | |||
|  | // The global object is "self" in Web Workers.
 | |||
|  | global = (function() { return this; })(); | |||
|  | 
 | |||
|  | /** | |||
|  |  * Save timer references to avoid Sinon interfering (see GH-237). | |||
|  |  */ | |||
|  | 
 | |||
|  | var Date = global.Date; | |||
|  | var setTimeout = global.setTimeout; | |||
|  | var setInterval = global.setInterval; | |||
|  | var clearTimeout = global.clearTimeout; | |||
|  | var clearInterval = global.clearInterval; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Node shims. | |||
|  |  * | |||
|  |  * These are meant only to allow | |||
|  |  * mocha.js to run untouched, not | |||
|  |  * to allow running node code in | |||
|  |  * the browser. | |||
|  |  */ | |||
|  | 
 | |||
|  | var process = {}; | |||
|  | process.exit = function(status){}; | |||
|  | process.stdout = {}; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Remove uncaughtException listener. | |||
|  |  */ | |||
|  | 
 | |||
|  | process.removeListener = function(e){ | |||
|  |   if ('uncaughtException' == e) { | |||
|  |     global.onerror = function() {}; | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Implements uncaughtException listener. | |||
|  |  */ | |||
|  | 
 | |||
|  | process.on = function(e, fn){ | |||
|  |   if ('uncaughtException' == e) { | |||
|  |     global.onerror = function(err, url, line){ | |||
|  |       fn(new Error(err + ' (' + url + ':' + line + ')')); | |||
|  |     }; | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose mocha. | |||
|  |  */ | |||
|  | 
 | |||
|  | var Mocha = global.Mocha = require('mocha'), | |||
|  |     mocha = global.mocha = new Mocha({ reporter: 'html' }); | |||
|  | 
 | |||
|  | var immediateQueue = [] | |||
|  |   , immediateTimeout; | |||
|  | 
 | |||
|  | function timeslice() { | |||
|  |   var immediateStart = new Date().getTime(); | |||
|  |   while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) { | |||
|  |     immediateQueue.shift()(); | |||
|  |   } | |||
|  |   if (immediateQueue.length) { | |||
|  |     immediateTimeout = setTimeout(timeslice, 0); | |||
|  |   } else { | |||
|  |     immediateTimeout = null; | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * High-performance override of Runner.immediately. | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.Runner.immediately = function(callback) { | |||
|  |   immediateQueue.push(callback); | |||
|  |   if (!immediateTimeout) { | |||
|  |     immediateTimeout = setTimeout(timeslice, 0); | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Override ui to ensure that the ui functions are initialized. | |||
|  |  * Normally this would happen in Mocha.prototype.loadFiles. | |||
|  |  */ | |||
|  | 
 | |||
|  | mocha.ui = function(ui){ | |||
|  |   Mocha.prototype.ui.call(this, ui); | |||
|  |   this.suite.emit('pre-require', global, null, this); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Setup mocha with the given setting options. | |||
|  |  */ | |||
|  | 
 | |||
|  | mocha.setup = function(opts){ | |||
|  |   if ('string' == typeof opts) opts = { ui: opts }; | |||
|  |   for (var opt in opts) this[opt](opts[opt]); | |||
|  |   return this; | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run mocha, returning the Runner. | |||
|  |  */ | |||
|  | 
 | |||
|  | mocha.run = function(fn){ | |||
|  |   var options = mocha.options; | |||
|  |   mocha.globals('location'); | |||
|  | 
 | |||
|  |   var query = Mocha.utils.parseQuery(global.location.search || ''); | |||
|  |   if (query.grep) mocha.grep(query.grep); | |||
|  |   if (query.invert) mocha.invert(); | |||
|  | 
 | |||
|  |   return Mocha.prototype.run.call(mocha, function(){ | |||
|  |     // The DOM Document is not available in Web Workers.
 | |||
|  |     if (global.document) { | |||
|  |       Mocha.utils.highlightTags('code'); | |||
|  |     } | |||
|  |     if (fn) fn(); | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * Expose the process shim. | |||
|  |  */ | |||
|  | 
 | |||
|  | Mocha.process = process; | |||
|  | })(); |