teabag 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ })();