Passed
Push — master ( 1713a6...bcb549 )
by Peter
02:05
created

FuzzEd/static/lib/mocha/mocha-1.21.4.js   F

Complexity

Total Complexity 870
Complexity/F 1.9

Size

Lines of Code 5983
Function Count 458

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
dl 0
loc 5983
rs 2.4
c 0
b 0
f 0
wmc 870
nc 0
mnd 8
bc 664
fnc 458
bpm 1.4497
cpm 1.8995
noi 178

How to fix   Complexity   

Complexity

Complex classes like FuzzEd/static/lib/mocha/mocha-1.21.4.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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