teabag 0.3.1 → 0.3.2

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