konacha 1.1.3 → 1.2.0

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,4139 @@
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 publci
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 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
+ this._runnable = runnable;
419
+ return this;
420
+ };
421
+
422
+ /**
423
+ * Set test timeout `ms`.
424
+ *
425
+ * @param {Number} ms
426
+ * @return {Context} self
427
+ * @api private
428
+ */
429
+
430
+ Context.prototype.timeout = function(ms){
431
+ this._runnable.timeout(ms);
432
+ return this;
433
+ };
434
+
435
+ /**
436
+ * Inspect the context void of `._runnable`.
437
+ *
438
+ * @return {String}
439
+ * @api private
440
+ */
441
+
442
+ Context.prototype.inspect = function(){
443
+ return JSON.stringify(this, function(key, val){
444
+ return '_runnable' == key
445
+ ? undefined
446
+ : val;
447
+ }, 2);
448
+ };
449
+
450
+ }); // module: context.js
451
+
452
+ require.register("hook.js", function(module, exports, require){
453
+
454
+ /**
455
+ * Module dependencies.
456
+ */
457
+
458
+ var Runnable = require('./runnable');
459
+
460
+ /**
461
+ * Expose `Hook`.
462
+ */
463
+
464
+ module.exports = Hook;
465
+
466
+ /**
467
+ * Initialize a new `Hook` with the given `title` and callback `fn`.
468
+ *
469
+ * @param {String} title
470
+ * @param {Function} fn
471
+ * @api private
472
+ */
473
+
474
+ function Hook(title, fn) {
475
+ Runnable.call(this, title, fn);
476
+ this.type = 'hook';
477
+ }
478
+
479
+ /**
480
+ * Inherit from `Runnable.prototype`.
481
+ */
482
+
483
+ Hook.prototype = new Runnable;
484
+ Hook.prototype.constructor = Hook;
485
+
486
+
487
+ }); // module: hook.js
488
+
489
+ require.register("interfaces/bdd.js", function(module, exports, require){
490
+
491
+ /**
492
+ * Module dependencies.
493
+ */
494
+
495
+ var Suite = require('../suite')
496
+ , Test = require('../test');
497
+
498
+ /**
499
+ * BDD-style interface:
500
+ *
501
+ * describe('Array', function(){
502
+ * describe('#indexOf()', function(){
503
+ * it('should return -1 when not present', function(){
504
+ *
505
+ * });
506
+ *
507
+ * it('should return the index when present', function(){
508
+ *
509
+ * });
510
+ * });
511
+ * });
512
+ *
513
+ */
514
+
515
+ module.exports = function(suite){
516
+ var suites = [suite];
517
+
518
+ suite.on('pre-require', function(context){
519
+
520
+ // noop variants
521
+
522
+ context.xdescribe = function(){};
523
+ context.xit = function(){};
524
+
525
+ /**
526
+ * Execute before running tests.
527
+ */
528
+
529
+ context.before = function(fn){
530
+ suites[0].beforeAll(fn);
531
+ };
532
+
533
+ /**
534
+ * Execute after running tests.
535
+ */
536
+
537
+ context.after = function(fn){
538
+ suites[0].afterAll(fn);
539
+ };
540
+
541
+ /**
542
+ * Execute before each test case.
543
+ */
544
+
545
+ context.beforeEach = function(fn){
546
+ suites[0].beforeEach(fn);
547
+ };
548
+
549
+ /**
550
+ * Execute after each test case.
551
+ */
552
+
553
+ context.afterEach = function(fn){
554
+ suites[0].afterEach(fn);
555
+ };
556
+
557
+ /**
558
+ * Describe a "suite" with the given `title`
559
+ * and callback `fn` containing nested suites
560
+ * and/or tests.
561
+ */
562
+
563
+ context.describe = function(title, fn){
564
+ var suite = Suite.create(suites[0], title);
565
+ suites.unshift(suite);
566
+ fn();
567
+ suites.shift();
568
+ };
569
+
570
+ /**
571
+ * Describe a specification or test-case
572
+ * with the given `title` and callback `fn`
573
+ * acting as a thunk.
574
+ */
575
+
576
+ context.it = function(title, fn){
577
+ suites[0].addTest(new Test(title, fn));
578
+ };
579
+ });
580
+ };
581
+
582
+ }); // module: interfaces/bdd.js
583
+
584
+ require.register("interfaces/exports.js", function(module, exports, require){
585
+
586
+ /**
587
+ * Module dependencies.
588
+ */
589
+
590
+ var Suite = require('../suite')
591
+ , Test = require('../test');
592
+
593
+ /**
594
+ * TDD-style interface:
595
+ *
596
+ * exports.Array = {
597
+ * '#indexOf()': {
598
+ * 'should return -1 when the value is not present': function(){
599
+ *
600
+ * },
601
+ *
602
+ * 'should return the correct index when the value is present': function(){
603
+ *
604
+ * }
605
+ * }
606
+ * };
607
+ *
608
+ */
609
+
610
+ module.exports = function(suite){
611
+ var suites = [suite];
612
+
613
+ suite.on('require', visit);
614
+
615
+ function visit(obj) {
616
+ var suite;
617
+ for (var key in obj) {
618
+ if ('function' == typeof obj[key]) {
619
+ var fn = obj[key];
620
+ switch (key) {
621
+ case 'before':
622
+ suites[0].beforeAll(fn);
623
+ break;
624
+ case 'after':
625
+ suites[0].afterAll(fn);
626
+ break;
627
+ case 'beforeEach':
628
+ suites[0].beforeEach(fn);
629
+ break;
630
+ case 'afterEach':
631
+ suites[0].afterEach(fn);
632
+ break;
633
+ default:
634
+ suites[0].addTest(new Test(key, fn));
635
+ }
636
+ } else {
637
+ var suite = Suite.create(suites[0], key);
638
+ suites.unshift(suite);
639
+ visit(obj[key]);
640
+ suites.shift();
641
+ }
642
+ }
643
+ }
644
+ };
645
+ }); // module: interfaces/exports.js
646
+
647
+ require.register("interfaces/index.js", function(module, exports, require){
648
+
649
+ exports.bdd = require('./bdd');
650
+ exports.tdd = require('./tdd');
651
+ exports.qunit = require('./qunit');
652
+ exports.exports = require('./exports');
653
+
654
+ }); // module: interfaces/index.js
655
+
656
+ require.register("interfaces/qunit.js", function(module, exports, require){
657
+
658
+ /**
659
+ * Module dependencies.
660
+ */
661
+
662
+ var Suite = require('../suite')
663
+ , Test = require('../test');
664
+
665
+ /**
666
+ * QUnit-style interface:
667
+ *
668
+ * suite('Array');
669
+ *
670
+ * test('#length', function(){
671
+ * var arr = [1,2,3];
672
+ * ok(arr.length == 3);
673
+ * });
674
+ *
675
+ * test('#indexOf()', function(){
676
+ * var arr = [1,2,3];
677
+ * ok(arr.indexOf(1) == 0);
678
+ * ok(arr.indexOf(2) == 1);
679
+ * ok(arr.indexOf(3) == 2);
680
+ * });
681
+ *
682
+ * suite('String');
683
+ *
684
+ * test('#length', function(){
685
+ * ok('foo'.length == 3);
686
+ * });
687
+ *
688
+ */
689
+
690
+ module.exports = function(suite){
691
+ var suites = [suite];
692
+
693
+ suite.on('pre-require', function(context){
694
+
695
+ /**
696
+ * Execute before running tests.
697
+ */
698
+
699
+ context.before = function(fn){
700
+ suites[0].beforeAll(fn);
701
+ };
702
+
703
+ /**
704
+ * Execute after running tests.
705
+ */
706
+
707
+ context.after = function(fn){
708
+ suites[0].afterAll(fn);
709
+ };
710
+
711
+ /**
712
+ * Execute before each test case.
713
+ */
714
+
715
+ context.beforeEach = function(fn){
716
+ suites[0].beforeEach(fn);
717
+ };
718
+
719
+ /**
720
+ * Execute after each test case.
721
+ */
722
+
723
+ context.afterEach = function(fn){
724
+ suites[0].afterEach(fn);
725
+ };
726
+
727
+ /**
728
+ * Describe a "suite" with the given `title`.
729
+ */
730
+
731
+ context.suite = function(title){
732
+ if (suites.length > 1) suites.shift();
733
+ var suite = Suite.create(suites[0], title);
734
+ suites.unshift(suite);
735
+ };
736
+
737
+ /**
738
+ * Describe a specification or test-case
739
+ * with the given `title` and callback `fn`
740
+ * acting as a thunk.
741
+ */
742
+
743
+ context.test = function(title, fn){
744
+ suites[0].addTest(new Test(title, fn));
745
+ };
746
+ });
747
+ };
748
+
749
+ }); // module: interfaces/qunit.js
750
+
751
+ require.register("interfaces/tdd.js", function(module, exports, require){
752
+
753
+ /**
754
+ * Module dependencies.
755
+ */
756
+
757
+ var Suite = require('../suite')
758
+ , Test = require('../test');
759
+
760
+ /**
761
+ * TDD-style interface:
762
+ *
763
+ * suite('Array', function(){
764
+ * suite('#indexOf()', function(){
765
+ * suiteSetup(function(){
766
+ *
767
+ * });
768
+ *
769
+ * test('should return -1 when not present', function(){
770
+ *
771
+ * });
772
+ *
773
+ * test('should return the index when present', function(){
774
+ *
775
+ * });
776
+ *
777
+ * suiteTeardown(function(){
778
+ *
779
+ * });
780
+ * });
781
+ * });
782
+ *
783
+ */
784
+
785
+ module.exports = function(suite){
786
+ var suites = [suite];
787
+
788
+ suite.on('pre-require', function(context){
789
+
790
+ /**
791
+ * Execute before each test case.
792
+ */
793
+
794
+ context.setup = function(fn){
795
+ suites[0].beforeEach(fn);
796
+ };
797
+
798
+ /**
799
+ * Execute after each test case.
800
+ */
801
+
802
+ context.teardown = function(fn){
803
+ suites[0].afterEach(fn);
804
+ };
805
+
806
+ /**
807
+ * Execute before the suite.
808
+ */
809
+
810
+ context.suiteSetup = function(fn){
811
+ suites[0].beforeAll(fn);
812
+ };
813
+
814
+ /**
815
+ * Execute after the suite.
816
+ */
817
+
818
+ context.suiteTeardown = function(fn){
819
+ suites[0].afterAll(fn);
820
+ };
821
+
822
+ /**
823
+ * Describe a "suite" with the given `title`
824
+ * and callback `fn` containing nested suites
825
+ * and/or tests.
826
+ */
827
+
828
+ context.suite = function(title, fn){
829
+ var suite = Suite.create(suites[0], title);
830
+ suites.unshift(suite);
831
+ fn();
832
+ suites.shift();
833
+ };
834
+
835
+ /**
836
+ * Describe a specification or test-case
837
+ * with the given `title` and callback `fn`
838
+ * acting as a thunk.
839
+ */
840
+
841
+ context.test = function(title, fn){
842
+ suites[0].addTest(new Test(title, fn));
843
+ };
844
+ });
845
+ };
846
+
847
+ }); // module: interfaces/tdd.js
848
+
849
+ require.register("mocha.js", function(module, exports, require){
850
+
851
+ /*!
852
+ * mocha
853
+ * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
854
+ * MIT Licensed
855
+ */
856
+
857
+ /**
858
+ * Module dependencies.
859
+ */
860
+
861
+ var path = require('browser/path');
862
+
863
+ /**
864
+ * Expose `Mocha`.
865
+ */
866
+
867
+ exports = module.exports = Mocha;
868
+
869
+ /**
870
+ * Library version.
871
+ */
872
+
873
+ exports.version = '1.0.2';
874
+
875
+ /**
876
+ * Expose internals.
877
+ */
878
+
879
+ exports.utils = require('./utils');
880
+ exports.interfaces = require('./interfaces');
881
+ exports.reporters = require('./reporters');
882
+ exports.Runnable = require('./runnable');
883
+ exports.Context = require('./context');
884
+ exports.Runner = require('./runner');
885
+ exports.Suite = require('./suite');
886
+ exports.Hook = require('./hook');
887
+ exports.Test = require('./test');
888
+
889
+ /**
890
+ * Return image `name` path.
891
+ *
892
+ * @param {String} name
893
+ * @return {String}
894
+ * @api private
895
+ */
896
+
897
+ function image(name) {
898
+ return __dirname + '/../images/' + name + '.png';
899
+ }
900
+
901
+ /**
902
+ * Setup mocha with `options`.
903
+ *
904
+ * Options:
905
+ *
906
+ * - `ui` name "bdd", "tdd", "exports" etc
907
+ * - `reporter` reporter instance, defaults to `mocha.reporters.Dot`
908
+ * - `globals` array of accepted globals
909
+ * - `timeout` timeout in milliseconds
910
+ * - `ignoreLeaks` ignore global leaks
911
+ *
912
+ * @param {Object} options
913
+ * @api public
914
+ */
915
+
916
+ function Mocha(options) {
917
+ options = options || {};
918
+ this.files = [];
919
+ this.options = options;
920
+ this.suite = new exports.Suite('', new exports.Context);
921
+ this.ui(options.ui);
922
+ this.reporter(options.reporter);
923
+ if (options.timeout) this.suite.timeout(options.timeout);
924
+ }
925
+
926
+ /**
927
+ * Add test `file`.
928
+ *
929
+ * @param {String} file
930
+ * @api public
931
+ */
932
+
933
+ Mocha.prototype.addFile = function(file){
934
+ this.files.push(file);
935
+ return this;
936
+ };
937
+
938
+ /**
939
+ * Set reporter to `name`, defaults to "dot".
940
+ *
941
+ * @param {String} name
942
+ * @api public
943
+ */
944
+
945
+ Mocha.prototype.reporter = function(name){
946
+ name = name || 'dot';
947
+ this._reporter = require('./reporters/' + name);
948
+ if (!this._reporter) throw new Error('invalid reporter "' + name + '"');
949
+ return this;
950
+ };
951
+
952
+ /**
953
+ * Set test UI `name`, defaults to "bdd".
954
+ *
955
+ * @param {String} bdd
956
+ * @api public
957
+ */
958
+
959
+ Mocha.prototype.ui = function(name){
960
+ name = name || 'bdd';
961
+ this._ui = exports.interfaces[name];
962
+ if (!this._ui) throw new Error('invalid interface "' + name + '"');
963
+ this._ui = this._ui(this.suite);
964
+ return this;
965
+ };
966
+
967
+ /**
968
+ * Load registered files.
969
+ *
970
+ * @api private
971
+ */
972
+
973
+ Mocha.prototype.loadFiles = function(){
974
+ var suite = this.suite;
975
+ this.files.forEach(function(file){
976
+ file = path.resolve(file);
977
+ suite.emit('pre-require', global, file);
978
+ suite.emit('require', require(file), file);
979
+ suite.emit('post-require', global, file);
980
+ });
981
+ };
982
+
983
+ /**
984
+ * Enable growl support.
985
+ *
986
+ * @api private
987
+ */
988
+
989
+ Mocha.prototype.growl = function(runner, reporter) {
990
+ var notify = require('growl');
991
+
992
+ runner.on('end', function(){
993
+ var stats = reporter.stats;
994
+ if (stats.failures) {
995
+ var msg = stats.failures + ' of ' + runner.total + ' tests failed';
996
+ notify(msg, { title: 'Failed', image: image('fail') });
997
+ } else {
998
+ notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
999
+ title: 'Passed'
1000
+ , image: image('pass')
1001
+ });
1002
+ }
1003
+ });
1004
+ };
1005
+
1006
+ /**
1007
+ * Run tests and invoke `fn()` when complete.
1008
+ *
1009
+ * @param {Function} fn
1010
+ * @return {Runner}
1011
+ * @api public
1012
+ */
1013
+
1014
+ Mocha.prototype.run = function(fn){
1015
+ this.loadFiles();
1016
+ var suite = this.suite;
1017
+ var options = this.options;
1018
+ var runner = new exports.Runner(suite);
1019
+ var reporter = new this._reporter(runner);
1020
+ runner.ignoreLeaks = options.ignoreLeaks;
1021
+ if (options.grep) runner.grep(options.grep);
1022
+ if (options.globals) runner.globals(options.globals);
1023
+ if (options.growl) this.growl(runner, reporter);
1024
+ return runner.run(fn);
1025
+ };
1026
+
1027
+ }); // module: mocha.js
1028
+
1029
+ require.register("reporters/base.js", function(module, exports, require){
1030
+
1031
+ /**
1032
+ * Module dependencies.
1033
+ */
1034
+
1035
+ var tty = require('browser/tty')
1036
+ , diff = require('browser/diff');
1037
+
1038
+ /**
1039
+ * Check if both stdio streams are associated with a tty.
1040
+ */
1041
+
1042
+ var isatty = tty.isatty(1) && tty.isatty(2);
1043
+
1044
+ /**
1045
+ * Expose `Base`.
1046
+ */
1047
+
1048
+ exports = module.exports = Base;
1049
+
1050
+ /**
1051
+ * Enable coloring by default.
1052
+ */
1053
+
1054
+ exports.useColors = isatty;
1055
+
1056
+ /**
1057
+ * Default color map.
1058
+ */
1059
+
1060
+ exports.colors = {
1061
+ 'pass': 90
1062
+ , 'fail': 31
1063
+ , 'bright pass': 92
1064
+ , 'bright fail': 91
1065
+ , 'bright yellow': 93
1066
+ , 'pending': 36
1067
+ , 'suite': 0
1068
+ , 'error title': 0
1069
+ , 'error message': 31
1070
+ , 'error stack': 90
1071
+ , 'checkmark': 32
1072
+ , 'fast': 90
1073
+ , 'medium': 33
1074
+ , 'slow': 31
1075
+ , 'green': 32
1076
+ , 'light': 90
1077
+ , 'diff gutter': 90
1078
+ , 'diff added': 42
1079
+ , 'diff removed': 41
1080
+ };
1081
+
1082
+ /**
1083
+ * Color `str` with the given `type`,
1084
+ * allowing colors to be disabled,
1085
+ * as well as user-defined color
1086
+ * schemes.
1087
+ *
1088
+ * @param {String} type
1089
+ * @param {String} str
1090
+ * @return {String}
1091
+ * @api private
1092
+ */
1093
+
1094
+ var color = exports.color = function(type, str) {
1095
+ if (!exports.useColors) return str;
1096
+ return '\033[' + exports.colors[type] + 'm' + str + '\033[0m';
1097
+ };
1098
+
1099
+ /**
1100
+ * Expose term window size, with some
1101
+ * defaults for when stderr is not a tty.
1102
+ */
1103
+
1104
+ exports.window = {
1105
+ width: isatty
1106
+ ? process.stdout.getWindowSize
1107
+ ? process.stdout.getWindowSize(1)[0]
1108
+ : tty.getWindowSize()[1]
1109
+ : 75
1110
+ };
1111
+
1112
+ /**
1113
+ * Expose some basic cursor interactions
1114
+ * that are common among reporters.
1115
+ */
1116
+
1117
+ exports.cursor = {
1118
+ hide: function(){
1119
+ process.stdout.write('\033[?25l');
1120
+ },
1121
+
1122
+ show: function(){
1123
+ process.stdout.write('\033[?25h');
1124
+ },
1125
+
1126
+ deleteLine: function(){
1127
+ process.stdout.write('\033[2K');
1128
+ },
1129
+
1130
+ beginningOfLine: function(){
1131
+ process.stdout.write('\033[0G');
1132
+ },
1133
+
1134
+ CR: function(){
1135
+ exports.cursor.deleteLine();
1136
+ exports.cursor.beginningOfLine();
1137
+ }
1138
+ };
1139
+
1140
+ /**
1141
+ * A test is considered slow if it
1142
+ * exceeds the following value in milliseconds.
1143
+ */
1144
+
1145
+ exports.slow = 75;
1146
+
1147
+ /**
1148
+ * Outut the given `failures` as a list.
1149
+ *
1150
+ * @param {Array} failures
1151
+ * @api public
1152
+ */
1153
+
1154
+ exports.list = function(failures){
1155
+ console.error();
1156
+ failures.forEach(function(test, i){
1157
+ // format
1158
+ var fmt = color('error title', ' %s) %s:\n')
1159
+ + color('error message', ' %s')
1160
+ + color('error stack', '\n%s\n');
1161
+
1162
+ // msg
1163
+ var err = test.err
1164
+ , message = err.message || ''
1165
+ , stack = err.stack || message
1166
+ , index = stack.indexOf(message) + message.length
1167
+ , msg = stack.slice(0, index)
1168
+ , actual = err.actual
1169
+ , expected = err.expected;
1170
+
1171
+ // actual / expected diff
1172
+ if ('string' == typeof actual && 'string' == typeof expected) {
1173
+ var len = Math.max(actual.length, expected.length);
1174
+
1175
+ if (len < 20) msg = errorDiff(err, 'Chars');
1176
+ else msg = errorDiff(err, 'Words');
1177
+
1178
+ // linenos
1179
+ var lines = msg.split('\n');
1180
+ if (lines.length > 4) {
1181
+ var width = String(lines.length).length;
1182
+ msg = lines.map(function(str, i){
1183
+ return pad(++i, width) + ' |' + ' ' + str;
1184
+ }).join('\n');
1185
+ }
1186
+
1187
+ // legend
1188
+ msg = '\n'
1189
+ + color('diff removed', 'actual')
1190
+ + ' '
1191
+ + color('diff added', 'expected')
1192
+ + '\n\n'
1193
+ + msg
1194
+ + '\n';
1195
+
1196
+ // indent
1197
+ msg = msg.replace(/^/gm, ' ');
1198
+
1199
+ fmt = color('error title', ' %s) %s:\n%s')
1200
+ + color('error stack', '\n%s\n');
1201
+ }
1202
+
1203
+ // indent stack trace without msg
1204
+ stack = stack.slice(index ? index + 1 : index)
1205
+ .replace(/^/gm, ' ');
1206
+
1207
+ console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
1208
+ });
1209
+ };
1210
+
1211
+ /**
1212
+ * Initialize a new `Base` reporter.
1213
+ *
1214
+ * All other reporters generally
1215
+ * inherit from this reporter, providing
1216
+ * stats such as test duration, number
1217
+ * of tests passed / failed etc.
1218
+ *
1219
+ * @param {Runner} runner
1220
+ * @api public
1221
+ */
1222
+
1223
+ function Base(runner) {
1224
+ var self = this
1225
+ , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
1226
+ , failures = this.failures = [];
1227
+
1228
+ if (!runner) return;
1229
+ this.runner = runner;
1230
+
1231
+ runner.on('start', function(){
1232
+ stats.start = new Date;
1233
+ });
1234
+
1235
+ runner.on('suite', function(suite){
1236
+ stats.suites = stats.suites || 0;
1237
+ suite.root || stats.suites++;
1238
+ });
1239
+
1240
+ runner.on('test end', function(test){
1241
+ stats.tests = stats.tests || 0;
1242
+ stats.tests++;
1243
+ });
1244
+
1245
+ runner.on('pass', function(test){
1246
+ stats.passes = stats.passes || 0;
1247
+
1248
+ var medium = exports.slow / 2;
1249
+ test.speed = test.duration > exports.slow
1250
+ ? 'slow'
1251
+ : test.duration > medium
1252
+ ? 'medium'
1253
+ : 'fast';
1254
+
1255
+ stats.passes++;
1256
+ });
1257
+
1258
+ runner.on('fail', function(test, err){
1259
+ stats.failures = stats.failures || 0;
1260
+ stats.failures++;
1261
+ test.err = err;
1262
+ failures.push(test);
1263
+ });
1264
+
1265
+ runner.on('end', function(){
1266
+ stats.end = new Date;
1267
+ stats.duration = new Date - stats.start;
1268
+ });
1269
+
1270
+ runner.on('pending', function(){
1271
+ stats.pending++;
1272
+ });
1273
+ }
1274
+
1275
+ /**
1276
+ * Output common epilogue used by many of
1277
+ * the bundled reporters.
1278
+ *
1279
+ * @api public
1280
+ */
1281
+
1282
+ Base.prototype.epilogue = function(){
1283
+ var stats = this.stats
1284
+ , fmt
1285
+ , tests;
1286
+
1287
+ console.log();
1288
+
1289
+ function pluralize(n) {
1290
+ return 1 == n ? 'test' : 'tests';
1291
+ }
1292
+
1293
+ // failure
1294
+ if (stats.failures) {
1295
+ fmt = color('bright fail', ' ✖')
1296
+ + color('fail', ' %d of %d %s failed')
1297
+ + color('light', ':')
1298
+
1299
+ console.error(fmt,
1300
+ stats.failures,
1301
+ this.runner.total,
1302
+ pluralize(this.runner.total));
1303
+
1304
+ Base.list(this.failures);
1305
+ console.error();
1306
+ return;
1307
+ }
1308
+
1309
+ // pass
1310
+ fmt = color('bright pass', ' ✔')
1311
+ + color('green', ' %d %s complete')
1312
+ + color('light', ' (%dms)');
1313
+
1314
+ console.log(fmt,
1315
+ stats.tests || 0,
1316
+ pluralize(stats.tests),
1317
+ stats.duration);
1318
+
1319
+ // pending
1320
+ if (stats.pending) {
1321
+ fmt = color('pending', ' •')
1322
+ + color('pending', ' %d %s pending');
1323
+
1324
+ console.log(fmt, stats.pending, pluralize(stats.pending));
1325
+ }
1326
+
1327
+ console.log();
1328
+ };
1329
+
1330
+ /**
1331
+ * Pad the given `str` to `len`.
1332
+ *
1333
+ * @param {String} str
1334
+ * @param {String} len
1335
+ * @return {String}
1336
+ * @api private
1337
+ */
1338
+
1339
+ function pad(str, len) {
1340
+ str = String(str);
1341
+ return Array(len - str.length + 1).join(' ') + str;
1342
+ }
1343
+
1344
+ /**
1345
+ * Return a character diff for `err`.
1346
+ *
1347
+ * @param {Error} err
1348
+ * @return {String}
1349
+ * @api private
1350
+ */
1351
+
1352
+ function errorDiff(err, type) {
1353
+ return diff['diff' + type](err.actual, err.expected).map(function(str){
1354
+ if (str.value == '\n') str.value = '<newline>\n';
1355
+ if (str.added) return colorLines('diff added', str.value);
1356
+ if (str.removed) return colorLines('diff removed', str.value);
1357
+ return str.value;
1358
+ }).join('');
1359
+ }
1360
+
1361
+ /**
1362
+ * Color lines for `str`, using the color `name`.
1363
+ *
1364
+ * @param {String} name
1365
+ * @param {String} str
1366
+ * @return {String}
1367
+ * @api private
1368
+ */
1369
+
1370
+ function colorLines(name, str) {
1371
+ return str.split('\n').map(function(str){
1372
+ return color(name, str);
1373
+ }).join('\n');
1374
+ }
1375
+
1376
+ }); // module: reporters/base.js
1377
+
1378
+ require.register("reporters/doc.js", function(module, exports, require){
1379
+
1380
+ /**
1381
+ * Module dependencies.
1382
+ */
1383
+
1384
+ var Base = require('./base')
1385
+ , utils = require('../utils');
1386
+
1387
+ /**
1388
+ * Expose `Doc`.
1389
+ */
1390
+
1391
+ exports = module.exports = Doc;
1392
+
1393
+ /**
1394
+ * Initialize a new `Doc` reporter.
1395
+ *
1396
+ * @param {Runner} runner
1397
+ * @api public
1398
+ */
1399
+
1400
+ function Doc(runner) {
1401
+ Base.call(this, runner);
1402
+
1403
+ var self = this
1404
+ , stats = this.stats
1405
+ , total = runner.total
1406
+ , indents = 2;
1407
+
1408
+ function indent() {
1409
+ return Array(indents).join(' ');
1410
+ }
1411
+
1412
+ runner.on('suite', function(suite){
1413
+ if (suite.root) return;
1414
+ ++indents;
1415
+ console.log('%s<section class="suite">', indent());
1416
+ ++indents;
1417
+ console.log('%s<h1>%s</h1>', indent(), suite.title);
1418
+ console.log('%s<dl>', indent());
1419
+ });
1420
+
1421
+ runner.on('suite end', function(suite){
1422
+ if (suite.root) return;
1423
+ console.log('%s</dl>', indent());
1424
+ --indents;
1425
+ console.log('%s</section>', indent());
1426
+ --indents;
1427
+ });
1428
+
1429
+ runner.on('pass', function(test){
1430
+ console.log('%s <dt>%s</dt>', indent(), test.title);
1431
+ var code = utils.escape(clean(test.fn.toString()));
1432
+ console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code);
1433
+ });
1434
+ }
1435
+
1436
+ /**
1437
+ * Strip the function definition from `str`,
1438
+ * and re-indent for pre whitespace.
1439
+ */
1440
+
1441
+ function clean(str) {
1442
+ str = str
1443
+ .replace(/^function *\(.*\) *{/, '')
1444
+ .replace(/\s+\}$/, '');
1445
+
1446
+ var spaces = str.match(/^\n?( *)/)[1].length
1447
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
1448
+
1449
+ str = str.replace(re, '');
1450
+
1451
+ return str;
1452
+ }
1453
+ }); // module: reporters/doc.js
1454
+
1455
+ require.register("reporters/dot.js", function(module, exports, require){
1456
+
1457
+ /**
1458
+ * Module dependencies.
1459
+ */
1460
+
1461
+ var Base = require('./base')
1462
+ , color = Base.color;
1463
+
1464
+ /**
1465
+ * Expose `Dot`.
1466
+ */
1467
+
1468
+ exports = module.exports = Dot;
1469
+
1470
+ /**
1471
+ * Initialize a new `Dot` matrix test reporter.
1472
+ *
1473
+ * @param {Runner} runner
1474
+ * @api public
1475
+ */
1476
+
1477
+ function Dot(runner) {
1478
+ Base.call(this, runner);
1479
+
1480
+ var self = this
1481
+ , stats = this.stats
1482
+ , width = Base.window.width * .75 | 0
1483
+ , n = 0;
1484
+
1485
+ runner.on('start', function(){
1486
+ process.stdout.write('\n ');
1487
+ });
1488
+
1489
+ runner.on('pending', function(test){
1490
+ process.stdout.write(color('pending', '.'));
1491
+ });
1492
+
1493
+ runner.on('pass', function(test){
1494
+ if (++n % width == 0) process.stdout.write('\n ');
1495
+ if ('slow' == test.speed) {
1496
+ process.stdout.write(color('bright yellow', '.'));
1497
+ } else {
1498
+ process.stdout.write(color(test.speed, '.'));
1499
+ }
1500
+ });
1501
+
1502
+ runner.on('fail', function(test, err){
1503
+ if (++n % width == 0) process.stdout.write('\n ');
1504
+ process.stdout.write(color('fail', '.'));
1505
+ });
1506
+
1507
+ runner.on('end', function(){
1508
+ console.log();
1509
+ self.epilogue();
1510
+ });
1511
+ }
1512
+
1513
+ /**
1514
+ * Inherit from `Base.prototype`.
1515
+ */
1516
+
1517
+ Dot.prototype = new Base;
1518
+ Dot.prototype.constructor = Dot;
1519
+
1520
+ }); // module: reporters/dot.js
1521
+
1522
+ require.register("reporters/html-cov.js", function(module, exports, require){
1523
+
1524
+ /**
1525
+ * Module dependencies.
1526
+ */
1527
+
1528
+ var JSONCov = require('./json-cov')
1529
+ , fs = require('browser/fs');
1530
+
1531
+ /**
1532
+ * Expose `HTMLCov`.
1533
+ */
1534
+
1535
+ exports = module.exports = HTMLCov;
1536
+
1537
+ /**
1538
+ * Initialize a new `JsCoverage` reporter.
1539
+ *
1540
+ * @param {Runner} runner
1541
+ * @api public
1542
+ */
1543
+
1544
+ function HTMLCov(runner) {
1545
+ var jade = require('jade')
1546
+ , file = __dirname + '/templates/coverage.jade'
1547
+ , str = fs.readFileSync(file, 'utf8')
1548
+ , fn = jade.compile(str, { filename: file })
1549
+ , self = this;
1550
+
1551
+ JSONCov.call(this, runner, false);
1552
+
1553
+ runner.on('end', function(){
1554
+ process.stdout.write(fn({
1555
+ cov: self.cov
1556
+ , coverageClass: coverageClass
1557
+ }));
1558
+ });
1559
+ }
1560
+
1561
+ function coverageClass(n) {
1562
+ if (n >= 75) return 'high';
1563
+ if (n >= 50) return 'medium';
1564
+ if (n >= 25) return 'low';
1565
+ return 'terrible';
1566
+ }
1567
+ }); // module: reporters/html-cov.js
1568
+
1569
+ require.register("reporters/html.js", function(module, exports, require){
1570
+
1571
+ /**
1572
+ * Module dependencies.
1573
+ */
1574
+
1575
+ var Base = require('./base')
1576
+ , utils = require('../utils')
1577
+ , Progress = require('../browser/progress')
1578
+ , escape = utils.escape;
1579
+
1580
+ /**
1581
+ * Expose `Doc`.
1582
+ */
1583
+
1584
+ exports = module.exports = HTML;
1585
+
1586
+ /**
1587
+ * Stats template.
1588
+ */
1589
+
1590
+ var statsTemplate = '<ul id="stats">'
1591
+ + '<li class="progress"><canvas width="40" height="40"></canvas></li>'
1592
+ + '<li class="passes">passes: <em>0</em></li>'
1593
+ + '<li class="failures">failures: <em>0</em></li>'
1594
+ + '<li class="duration">duration: <em>0</em>s</li>'
1595
+ + '</ul>';
1596
+
1597
+ /**
1598
+ * Initialize a new `Doc` reporter.
1599
+ *
1600
+ * @param {Runner} runner
1601
+ * @api public
1602
+ */
1603
+
1604
+ function HTML(runner) {
1605
+ Base.call(this, runner);
1606
+
1607
+ var self = this
1608
+ , stats = this.stats
1609
+ , total = runner.total
1610
+ , root = document.getElementById('mocha')
1611
+ , stat = fragment(statsTemplate)
1612
+ , items = stat.getElementsByTagName('li')
1613
+ , passes = items[1].getElementsByTagName('em')[0]
1614
+ , failures = items[2].getElementsByTagName('em')[0]
1615
+ , duration = items[3].getElementsByTagName('em')[0]
1616
+ , canvas = stat.getElementsByTagName('canvas')[0]
1617
+ , stack = [root]
1618
+ , progress
1619
+ , ctx
1620
+
1621
+ if (canvas.getContext) {
1622
+ ctx = canvas.getContext('2d');
1623
+ progress = new Progress;
1624
+ }
1625
+
1626
+ if (!root) return error('#mocha div missing, add it to your document');
1627
+
1628
+ root.appendChild(stat);
1629
+
1630
+ if (progress) progress.size(40);
1631
+
1632
+ runner.on('suite', function(suite){
1633
+ if (suite.root) return;
1634
+
1635
+ // suite
1636
+ var el = fragment('<div class="suite"><h1>%s</h1></div>', suite.title);
1637
+
1638
+ // container
1639
+ stack[0].appendChild(el);
1640
+ stack.unshift(document.createElement('div'));
1641
+ el.appendChild(stack[0]);
1642
+ });
1643
+
1644
+ runner.on('suite end', function(suite){
1645
+ if (suite.root) return;
1646
+ stack.shift();
1647
+ });
1648
+
1649
+ runner.on('fail', function(test, err){
1650
+ if ('hook' == test.type || err.uncaught) runner.emit('test end', test);
1651
+ });
1652
+
1653
+ runner.on('test end', function(test){
1654
+ // TODO: add to stats
1655
+ var percent = stats.tests / total * 100 | 0;
1656
+ if (progress) progress.update(percent).draw(ctx);
1657
+
1658
+ // update stats
1659
+ var ms = new Date - stats.start;
1660
+ text(passes, stats.passes);
1661
+ text(failures, stats.failures);
1662
+ text(duration, (ms / 1000).toFixed(2));
1663
+
1664
+ // test
1665
+ if ('passed' == test.state) {
1666
+ var el = fragment('<div class="test pass %e"><h2>%e<span class="duration">%ems</span></h2></div>', test.speed, test.title, test.duration);
1667
+ } else if (test.pending) {
1668
+ var el = fragment('<div class="test pass pending"><h2>%e</h2></div>', test.title);
1669
+ } else {
1670
+ var el = fragment('<div class="test fail"><h2>%e</h2></div>', test.title);
1671
+ var str = test.err.stack || test.err.toString();
1672
+
1673
+ // FF / Opera do not add the message
1674
+ if (!~str.indexOf(test.err.message)) {
1675
+ str = test.err.message + '\n' + str;
1676
+ }
1677
+
1678
+ // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
1679
+ // check for the result of the stringifying.
1680
+ if ('[object Error]' == str) str = test.err.message;
1681
+
1682
+ // Safari doesn't give you a stack. Let's at least provide a source line.
1683
+ if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
1684
+ str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
1685
+ }
1686
+
1687
+ el.appendChild(fragment('<pre class="error">%e</pre>', str));
1688
+ }
1689
+
1690
+ // toggle code
1691
+ var h2 = el.getElementsByTagName('h2')[0];
1692
+
1693
+ on(h2, 'click', function(){
1694
+ pre.style.display = 'none' == pre.style.display
1695
+ ? 'block'
1696
+ : 'none';
1697
+ });
1698
+
1699
+ // code
1700
+ // TODO: defer
1701
+ if (!test.pending) {
1702
+ var pre = fragment('<pre><code>%e</code></pre>', clean(test.fn.toString()));
1703
+ el.appendChild(pre);
1704
+ pre.style.display = 'none';
1705
+ }
1706
+
1707
+ stack[0].appendChild(el);
1708
+ });
1709
+ }
1710
+
1711
+ /**
1712
+ * Display error `msg`.
1713
+ */
1714
+
1715
+ function error(msg) {
1716
+ document.body.appendChild(fragment('<div id="error">%s</div>', msg));
1717
+ }
1718
+
1719
+ /**
1720
+ * Return a DOM fragment from `html`.
1721
+ */
1722
+
1723
+ function fragment(html) {
1724
+ var args = arguments
1725
+ , div = document.createElement('div')
1726
+ , i = 1;
1727
+
1728
+ div.innerHTML = html.replace(/%([se])/g, function(_, type){
1729
+ switch (type) {
1730
+ case 's': return String(args[i++]);
1731
+ case 'e': return escape(args[i++]);
1732
+ }
1733
+ });
1734
+
1735
+ return div.firstChild;
1736
+ }
1737
+
1738
+ /**
1739
+ * Set `el` text to `str`.
1740
+ */
1741
+
1742
+ function text(el, str) {
1743
+ if (el.textContent) {
1744
+ el.textContent = str;
1745
+ } else {
1746
+ el.innerText = str;
1747
+ }
1748
+ }
1749
+
1750
+ /**
1751
+ * Listen on `event` with callback `fn`.
1752
+ */
1753
+
1754
+ function on(el, event, fn) {
1755
+ if (el.addEventListener) {
1756
+ el.addEventListener(event, fn, false);
1757
+ } else {
1758
+ el.attachEvent('on' + event, fn);
1759
+ }
1760
+ }
1761
+
1762
+ /**
1763
+ * Strip the function definition from `str`,
1764
+ * and re-indent for pre whitespace.
1765
+ */
1766
+
1767
+ function clean(str) {
1768
+ str = str
1769
+ .replace(/^function *\(.*\) *{/, '')
1770
+ .replace(/\s+\}$/, '');
1771
+
1772
+ var spaces = str.match(/^\n?( *)/)[1].length
1773
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
1774
+
1775
+ str = str
1776
+ .replace(re, '')
1777
+ .replace(/^\s+/, '');
1778
+
1779
+ return str;
1780
+ }
1781
+
1782
+ }); // module: reporters/html.js
1783
+
1784
+ require.register("reporters/index.js", function(module, exports, require){
1785
+
1786
+ exports.Base = require('./base');
1787
+ exports.Dot = require('./dot');
1788
+ exports.Doc = require('./doc');
1789
+ exports.TAP = require('./tap');
1790
+ exports.JSON = require('./json');
1791
+ exports.HTML = require('./html');
1792
+ exports.List = require('./list');
1793
+ exports.Min = require('./min');
1794
+ exports.Spec = require('./spec');
1795
+ exports.Progress = require('./progress');
1796
+ exports.Landing = require('./landing');
1797
+ exports.JSONCov = require('./json-cov');
1798
+ exports.HTMLCov = require('./html-cov');
1799
+ exports.JSONStream = require('./json-stream');
1800
+ exports.XUnit = require('./xunit')
1801
+ exports.Teamcity = require('./teamcity')
1802
+
1803
+ }); // module: reporters/index.js
1804
+
1805
+ require.register("reporters/json-cov.js", function(module, exports, require){
1806
+
1807
+ /**
1808
+ * Module dependencies.
1809
+ */
1810
+
1811
+ var Base = require('./base');
1812
+
1813
+ /**
1814
+ * Expose `JSONCov`.
1815
+ */
1816
+
1817
+ exports = module.exports = JSONCov;
1818
+
1819
+ /**
1820
+ * Initialize a new `JsCoverage` reporter.
1821
+ *
1822
+ * @param {Runner} runner
1823
+ * @param {Boolean} output
1824
+ * @api public
1825
+ */
1826
+
1827
+ function JSONCov(runner, output) {
1828
+ var self = this
1829
+ , output = 1 == arguments.length ? true : output;
1830
+
1831
+ Base.call(this, runner);
1832
+
1833
+ var tests = []
1834
+ , failures = []
1835
+ , passes = [];
1836
+
1837
+ runner.on('test end', function(test){
1838
+ tests.push(test);
1839
+ });
1840
+
1841
+ runner.on('pass', function(test){
1842
+ passes.push(test);
1843
+ });
1844
+
1845
+ runner.on('fail', function(test){
1846
+ failures.push(test);
1847
+ });
1848
+
1849
+ runner.on('end', function(){
1850
+ var cov = global._$jscoverage || {};
1851
+ var result = self.cov = map(cov);
1852
+ result.stats = self.stats;
1853
+ result.tests = tests.map(clean);
1854
+ result.failures = failures.map(clean);
1855
+ result.passes = passes.map(clean);
1856
+ if (!output) return;
1857
+ process.stdout.write(JSON.stringify(result, null, 2 ));
1858
+ });
1859
+ }
1860
+
1861
+ /**
1862
+ * Map jscoverage data to a JSON structure
1863
+ * suitable for reporting.
1864
+ *
1865
+ * @param {Object} cov
1866
+ * @return {Object}
1867
+ * @api private
1868
+ */
1869
+
1870
+ function map(cov) {
1871
+ var ret = {
1872
+ instrumentation: 'node-jscoverage'
1873
+ , sloc: 0
1874
+ , hits: 0
1875
+ , misses: 0
1876
+ , coverage: 0
1877
+ , files: []
1878
+ };
1879
+
1880
+ for (var filename in cov) {
1881
+ var data = coverage(filename, cov[filename]);
1882
+ ret.files.push(data);
1883
+ ret.hits += data.hits;
1884
+ ret.misses += data.misses;
1885
+ ret.sloc += data.sloc;
1886
+ }
1887
+
1888
+ if (ret.sloc > 0) {
1889
+ ret.coverage = (ret.hits / ret.sloc) * 100;
1890
+ }
1891
+
1892
+ return ret;
1893
+ };
1894
+
1895
+ /**
1896
+ * Map jscoverage data for a single source file
1897
+ * to a JSON structure suitable for reporting.
1898
+ *
1899
+ * @param {String} filename name of the source file
1900
+ * @param {Object} data jscoverage coverage data
1901
+ * @return {Object}
1902
+ * @api private
1903
+ */
1904
+
1905
+ function coverage(filename, data) {
1906
+ var ret = {
1907
+ filename: filename,
1908
+ coverage: 0,
1909
+ hits: 0,
1910
+ misses: 0,
1911
+ sloc: 0,
1912
+ source: {}
1913
+ };
1914
+
1915
+ data.source.forEach(function(line, num){
1916
+ num++;
1917
+
1918
+ if (data[num] === 0) {
1919
+ ret.misses++;
1920
+ ret.sloc++;
1921
+ } else if (data[num] !== undefined) {
1922
+ ret.hits++;
1923
+ ret.sloc++;
1924
+ }
1925
+
1926
+ ret.source[num] = {
1927
+ source: line
1928
+ , coverage: data[num] === undefined
1929
+ ? ''
1930
+ : data[num]
1931
+ };
1932
+ });
1933
+
1934
+ ret.coverage = ret.hits / ret.sloc * 100;
1935
+
1936
+ return ret;
1937
+ }
1938
+
1939
+ /**
1940
+ * Return a plain-object representation of `test`
1941
+ * free of cyclic properties etc.
1942
+ *
1943
+ * @param {Object} test
1944
+ * @return {Object}
1945
+ * @api private
1946
+ */
1947
+
1948
+ function clean(test) {
1949
+ return {
1950
+ title: test.title
1951
+ , fullTitle: test.fullTitle()
1952
+ , duration: test.duration
1953
+ }
1954
+ }
1955
+
1956
+ }); // module: reporters/json-cov.js
1957
+
1958
+ require.register("reporters/json-stream.js", function(module, exports, require){
1959
+
1960
+ /**
1961
+ * Module dependencies.
1962
+ */
1963
+
1964
+ var Base = require('./base')
1965
+ , color = Base.color;
1966
+
1967
+ /**
1968
+ * Expose `List`.
1969
+ */
1970
+
1971
+ exports = module.exports = List;
1972
+
1973
+ /**
1974
+ * Initialize a new `List` test reporter.
1975
+ *
1976
+ * @param {Runner} runner
1977
+ * @api public
1978
+ */
1979
+
1980
+ function List(runner) {
1981
+ Base.call(this, runner);
1982
+
1983
+ var self = this
1984
+ , stats = this.stats
1985
+ , total = runner.total;
1986
+
1987
+ runner.on('start', function(){
1988
+ console.log(JSON.stringify(['start', { total: total }]));
1989
+ });
1990
+
1991
+ runner.on('pass', function(test){
1992
+ console.log(JSON.stringify(['pass', clean(test)]));
1993
+ });
1994
+
1995
+ runner.on('fail', function(test, err){
1996
+ console.log(JSON.stringify(['fail', clean(test)]));
1997
+ });
1998
+
1999
+ runner.on('end', function(){
2000
+ process.stdout.write(JSON.stringify(['end', self.stats]));
2001
+ });
2002
+ }
2003
+
2004
+ /**
2005
+ * Return a plain-object representation of `test`
2006
+ * free of cyclic properties etc.
2007
+ *
2008
+ * @param {Object} test
2009
+ * @return {Object}
2010
+ * @api private
2011
+ */
2012
+
2013
+ function clean(test) {
2014
+ return {
2015
+ title: test.title
2016
+ , fullTitle: test.fullTitle()
2017
+ , duration: test.duration
2018
+ }
2019
+ }
2020
+ }); // module: reporters/json-stream.js
2021
+
2022
+ require.register("reporters/json.js", function(module, exports, require){
2023
+
2024
+ /**
2025
+ * Module dependencies.
2026
+ */
2027
+
2028
+ var Base = require('./base')
2029
+ , cursor = Base.cursor
2030
+ , color = Base.color;
2031
+
2032
+ /**
2033
+ * Expose `JSON`.
2034
+ */
2035
+
2036
+ exports = module.exports = JSONReporter;
2037
+
2038
+ /**
2039
+ * Initialize a new `JSON` reporter.
2040
+ *
2041
+ * @param {Runner} runner
2042
+ * @api public
2043
+ */
2044
+
2045
+ function JSONReporter(runner) {
2046
+ var self = this;
2047
+ Base.call(this, runner);
2048
+
2049
+ var tests = []
2050
+ , failures = []
2051
+ , passes = [];
2052
+
2053
+ runner.on('test end', function(test){
2054
+ tests.push(test);
2055
+ });
2056
+
2057
+ runner.on('pass', function(test){
2058
+ passes.push(test);
2059
+ });
2060
+
2061
+ runner.on('fail', function(test){
2062
+ failures.push(test);
2063
+ });
2064
+
2065
+ runner.on('end', function(){
2066
+ var obj = {
2067
+ stats: self.stats
2068
+ , tests: tests.map(clean)
2069
+ , failures: failures.map(clean)
2070
+ , passes: passes.map(clean)
2071
+ };
2072
+
2073
+ process.stdout.write(JSON.stringify(obj, null, 2));
2074
+ });
2075
+ }
2076
+
2077
+ /**
2078
+ * Return a plain-object representation of `test`
2079
+ * free of cyclic properties etc.
2080
+ *
2081
+ * @param {Object} test
2082
+ * @return {Object}
2083
+ * @api private
2084
+ */
2085
+
2086
+ function clean(test) {
2087
+ return {
2088
+ title: test.title
2089
+ , fullTitle: test.fullTitle()
2090
+ , duration: test.duration
2091
+ }
2092
+ }
2093
+ }); // module: reporters/json.js
2094
+
2095
+ require.register("reporters/landing.js", function(module, exports, require){
2096
+
2097
+ /**
2098
+ * Module dependencies.
2099
+ */
2100
+
2101
+ var Base = require('./base')
2102
+ , cursor = Base.cursor
2103
+ , color = Base.color;
2104
+
2105
+ /**
2106
+ * Expose `Landing`.
2107
+ */
2108
+
2109
+ exports = module.exports = Landing;
2110
+
2111
+ /**
2112
+ * Airplane color.
2113
+ */
2114
+
2115
+ Base.colors.plane = 0;
2116
+
2117
+ /**
2118
+ * Airplane crash color.
2119
+ */
2120
+
2121
+ Base.colors['plane crash'] = 31;
2122
+
2123
+ /**
2124
+ * Runway color.
2125
+ */
2126
+
2127
+ Base.colors.runway = 90;
2128
+
2129
+ /**
2130
+ * Initialize a new `Landing` reporter.
2131
+ *
2132
+ * @param {Runner} runner
2133
+ * @api public
2134
+ */
2135
+
2136
+ function Landing(runner) {
2137
+ Base.call(this, runner);
2138
+
2139
+ var self = this
2140
+ , stats = this.stats
2141
+ , width = Base.window.width * .75 | 0
2142
+ , total = runner.total
2143
+ , stream = process.stdout
2144
+ , plane = color('plane', '✈')
2145
+ , crashed = -1
2146
+ , n = 0;
2147
+
2148
+ function runway() {
2149
+ var buf = Array(width).join('-');
2150
+ return ' ' + color('runway', buf);
2151
+ }
2152
+
2153
+ runner.on('start', function(){
2154
+ stream.write('\n ');
2155
+ cursor.hide();
2156
+ });
2157
+
2158
+ runner.on('test end', function(test){
2159
+ // check if the plane crashed
2160
+ var col = -1 == crashed
2161
+ ? width * ++n / total | 0
2162
+ : crashed;
2163
+
2164
+ // show the crash
2165
+ if ('failed' == test.state) {
2166
+ plane = color('plane crash', '✈');
2167
+ crashed = col;
2168
+ }
2169
+
2170
+ // render landing strip
2171
+ stream.write('\033[4F\n\n');
2172
+ stream.write(runway());
2173
+ stream.write('\n ');
2174
+ stream.write(color('runway', Array(col).join('⋅')));
2175
+ stream.write(plane)
2176
+ stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
2177
+ stream.write(runway());
2178
+ stream.write('\033[0m');
2179
+ });
2180
+
2181
+ runner.on('end', function(){
2182
+ cursor.show();
2183
+ console.log();
2184
+ self.epilogue();
2185
+ });
2186
+ }
2187
+
2188
+ /**
2189
+ * Inherit from `Base.prototype`.
2190
+ */
2191
+
2192
+ Landing.prototype = new Base;
2193
+ Landing.prototype.constructor = Landing;
2194
+
2195
+ }); // module: reporters/landing.js
2196
+
2197
+ require.register("reporters/list.js", function(module, exports, require){
2198
+
2199
+ /**
2200
+ * Module dependencies.
2201
+ */
2202
+
2203
+ var Base = require('./base')
2204
+ , cursor = Base.cursor
2205
+ , color = Base.color;
2206
+
2207
+ /**
2208
+ * Expose `List`.
2209
+ */
2210
+
2211
+ exports = module.exports = List;
2212
+
2213
+ /**
2214
+ * Initialize a new `List` test reporter.
2215
+ *
2216
+ * @param {Runner} runner
2217
+ * @api public
2218
+ */
2219
+
2220
+ function List(runner) {
2221
+ Base.call(this, runner);
2222
+
2223
+ var self = this
2224
+ , stats = this.stats
2225
+ , n = 0;
2226
+
2227
+ runner.on('start', function(){
2228
+ console.log();
2229
+ });
2230
+
2231
+ runner.on('test', function(test){
2232
+ process.stdout.write(color('pass', ' ' + test.fullTitle() + ': '));
2233
+ });
2234
+
2235
+ runner.on('pending', function(test){
2236
+ var fmt = color('checkmark', ' -')
2237
+ + color('pending', ' %s');
2238
+ console.log(fmt, test.fullTitle());
2239
+ });
2240
+
2241
+ runner.on('pass', function(test){
2242
+ var fmt = color('checkmark', ' ✓')
2243
+ + color('pass', ' %s: ')
2244
+ + color(test.speed, '%dms');
2245
+ cursor.CR();
2246
+ console.log(fmt, test.fullTitle(), test.duration);
2247
+ });
2248
+
2249
+ runner.on('fail', function(test, err){
2250
+ cursor.CR();
2251
+ console.log(color('fail', ' %d) %s'), ++n, test.fullTitle());
2252
+ });
2253
+
2254
+ runner.on('end', self.epilogue.bind(self));
2255
+ }
2256
+
2257
+ /**
2258
+ * Inherit from `Base.prototype`.
2259
+ */
2260
+
2261
+ List.prototype = new Base;
2262
+ List.prototype.constructor = List;
2263
+
2264
+
2265
+ }); // module: reporters/list.js
2266
+
2267
+ require.register("reporters/markdown.js", function(module, exports, require){
2268
+
2269
+ /**
2270
+ * Module dependencies.
2271
+ */
2272
+
2273
+ var Base = require('./base')
2274
+ , utils = require('../utils');
2275
+
2276
+ /**
2277
+ * Expose `Markdown`.
2278
+ */
2279
+
2280
+ exports = module.exports = Markdown;
2281
+
2282
+ /**
2283
+ * Initialize a new `Markdown` reporter.
2284
+ *
2285
+ * @param {Runner} runner
2286
+ * @api public
2287
+ */
2288
+
2289
+ function Markdown(runner) {
2290
+ Base.call(this, runner);
2291
+
2292
+ var self = this
2293
+ , stats = this.stats
2294
+ , total = runner.total
2295
+ , level = 0
2296
+ , buf = '';
2297
+
2298
+ function title(str) {
2299
+ return Array(level).join('#') + ' ' + str;
2300
+ }
2301
+
2302
+ function indent() {
2303
+ return Array(level).join(' ');
2304
+ }
2305
+
2306
+ function mapTOC(suite, obj) {
2307
+ var ret = obj;
2308
+ obj = obj[suite.title] = obj[suite.title] || { suite: suite };
2309
+ suite.suites.forEach(function(suite){
2310
+ mapTOC(suite, obj);
2311
+ });
2312
+ return ret;
2313
+ }
2314
+
2315
+ function stringifyTOC(obj, level) {
2316
+ ++level;
2317
+ var buf = '';
2318
+ var link;
2319
+ for (var key in obj) {
2320
+ if ('suite' == key) continue;
2321
+ if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
2322
+ if (key) buf += Array(level).join(' ') + link;
2323
+ buf += stringifyTOC(obj[key], level);
2324
+ }
2325
+ --level;
2326
+ return buf;
2327
+ }
2328
+
2329
+ function generateTOC(suite) {
2330
+ var obj = mapTOC(suite, {});
2331
+ return stringifyTOC(obj, 0);
2332
+ }
2333
+
2334
+ generateTOC(runner.suite);
2335
+
2336
+ runner.on('suite', function(suite){
2337
+ ++level;
2338
+ var slug = utils.slug(suite.fullTitle());
2339
+ buf += '<a name="' + slug + '" />' + '\n';
2340
+ buf += title(suite.title) + '\n';
2341
+ });
2342
+
2343
+ runner.on('suite end', function(suite){
2344
+ --level;
2345
+ });
2346
+
2347
+ runner.on('pass', function(test){
2348
+ var code = clean(test.fn.toString());
2349
+ buf += test.title + '.\n';
2350
+ buf += '\n```js';
2351
+ buf += code + '\n';
2352
+ buf += '```\n\n';
2353
+ });
2354
+
2355
+ runner.on('end', function(){
2356
+ process.stdout.write('# TOC\n');
2357
+ process.stdout.write(generateTOC(runner.suite));
2358
+ process.stdout.write(buf);
2359
+ });
2360
+ }
2361
+
2362
+ /**
2363
+ * Strip the function definition from `str`,
2364
+ * and re-indent for pre whitespace.
2365
+ */
2366
+
2367
+ function clean(str) {
2368
+ str = str
2369
+ .replace(/^function *\(.*\) *{/, '')
2370
+ .replace(/\s+\}$/, '');
2371
+
2372
+ var spaces = str.match(/^\n?( *)/)[1].length
2373
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
2374
+
2375
+ str = str.replace(re, '');
2376
+
2377
+ return str;
2378
+ }
2379
+ }); // module: reporters/markdown.js
2380
+
2381
+ require.register("reporters/min.js", function(module, exports, require){
2382
+ /**
2383
+ * Module dependencies.
2384
+ */
2385
+
2386
+ var Base = require('./base');
2387
+
2388
+ /**
2389
+ * Expose `Min`.
2390
+ */
2391
+
2392
+ exports = module.exports = Min;
2393
+
2394
+ /**
2395
+ * Initialize a new `Min` minimal test reporter (best used with --watch).
2396
+ *
2397
+ * @param {Runner} runner
2398
+ * @api public
2399
+ */
2400
+
2401
+ function Min(runner) {
2402
+ Base.call(this, runner);
2403
+
2404
+ runner.on('start', function(){
2405
+ // clear screen
2406
+ process.stdout.write('\033[2J');
2407
+ // set cursor position
2408
+ process.stdout.write('\033[1;3H');
2409
+ });
2410
+
2411
+ runner.on('end', this.epilogue.bind(this));
2412
+ }
2413
+
2414
+ /**
2415
+ * Inherit from `Base.prototype`.
2416
+ */
2417
+
2418
+ Min.prototype = new Base;
2419
+ Min.prototype.constructor = Min;
2420
+
2421
+ }); // module: reporters/min.js
2422
+
2423
+ require.register("reporters/progress.js", function(module, exports, require){
2424
+
2425
+ /**
2426
+ * Module dependencies.
2427
+ */
2428
+
2429
+ var Base = require('./base')
2430
+ , cursor = Base.cursor
2431
+ , color = Base.color;
2432
+
2433
+ /**
2434
+ * Expose `Progress`.
2435
+ */
2436
+
2437
+ exports = module.exports = Progress;
2438
+
2439
+ /**
2440
+ * General progress bar color.
2441
+ */
2442
+
2443
+ Base.colors.progress = 90;
2444
+
2445
+ /**
2446
+ * Initialize a new `Progress` bar test reporter.
2447
+ *
2448
+ * @param {Runner} runner
2449
+ * @param {Object} options
2450
+ * @api public
2451
+ */
2452
+
2453
+ function Progress(runner, options) {
2454
+ Base.call(this, runner);
2455
+
2456
+ var self = this
2457
+ , options = options || {}
2458
+ , stats = this.stats
2459
+ , width = Base.window.width * .50 | 0
2460
+ , total = runner.total
2461
+ , complete = 0
2462
+ , max = Math.max;
2463
+
2464
+ // default chars
2465
+ options.open = options.open || '[';
2466
+ options.complete = options.complete || '▬';
2467
+ options.incomplete = options.incomplete || '⋅';
2468
+ options.close = options.close || ']';
2469
+ options.verbose = false;
2470
+
2471
+ // tests started
2472
+ runner.on('start', function(){
2473
+ console.log();
2474
+ cursor.hide();
2475
+ });
2476
+
2477
+ // tests complete
2478
+ runner.on('test end', function(){
2479
+ complete++;
2480
+ var incomplete = total - complete
2481
+ , percent = complete / total
2482
+ , n = width * percent | 0
2483
+ , i = width - n;
2484
+
2485
+ cursor.CR();
2486
+ process.stdout.write('\033[J');
2487
+ process.stdout.write(color('progress', ' ' + options.open));
2488
+ process.stdout.write(Array(n).join(options.complete));
2489
+ process.stdout.write(Array(i).join(options.incomplete));
2490
+ process.stdout.write(color('progress', options.close));
2491
+ if (options.verbose) {
2492
+ process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
2493
+ }
2494
+ });
2495
+
2496
+ // tests are complete, output some stats
2497
+ // and the failures if any
2498
+ runner.on('end', function(){
2499
+ cursor.show();
2500
+ console.log();
2501
+ self.epilogue();
2502
+ });
2503
+ }
2504
+
2505
+ /**
2506
+ * Inherit from `Base.prototype`.
2507
+ */
2508
+
2509
+ Progress.prototype = new Base;
2510
+ Progress.prototype.constructor = Progress;
2511
+
2512
+
2513
+ }); // module: reporters/progress.js
2514
+
2515
+ require.register("reporters/spec.js", function(module, exports, require){
2516
+
2517
+ /**
2518
+ * Module dependencies.
2519
+ */
2520
+
2521
+ var Base = require('./base')
2522
+ , cursor = Base.cursor
2523
+ , color = Base.color;
2524
+
2525
+ /**
2526
+ * Expose `Spec`.
2527
+ */
2528
+
2529
+ exports = module.exports = Spec;
2530
+
2531
+ /**
2532
+ * Initialize a new `Spec` test reporter.
2533
+ *
2534
+ * @param {Runner} runner
2535
+ * @api public
2536
+ */
2537
+
2538
+ function Spec(runner) {
2539
+ Base.call(this, runner);
2540
+
2541
+ var self = this
2542
+ , stats = this.stats
2543
+ , indents = 0
2544
+ , n = 0;
2545
+
2546
+ function indent() {
2547
+ return Array(indents).join(' ')
2548
+ }
2549
+
2550
+ runner.on('start', function(){
2551
+ console.log();
2552
+ });
2553
+
2554
+ runner.on('suite', function(suite){
2555
+ ++indents;
2556
+ console.log(color('suite', '%s%s'), indent(), suite.title);
2557
+ });
2558
+
2559
+ runner.on('suite end', function(suite){
2560
+ --indents;
2561
+ if (1 == indents) console.log();
2562
+ });
2563
+
2564
+ runner.on('test', function(test){
2565
+ process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': '));
2566
+ });
2567
+
2568
+ runner.on('pending', function(test){
2569
+ var fmt = indent() + color('pending', ' - %s');
2570
+ console.log(fmt, test.title);
2571
+ });
2572
+
2573
+ runner.on('pass', function(test){
2574
+ if ('fast' == test.speed) {
2575
+ var fmt = indent()
2576
+ + color('checkmark', ' ✓')
2577
+ + color('pass', ' %s ');
2578
+ cursor.CR();
2579
+ console.log(fmt, test.title);
2580
+ } else {
2581
+ var fmt = indent()
2582
+ + color('checkmark', ' ✓')
2583
+ + color('pass', ' %s ')
2584
+ + color(test.speed, '(%dms)');
2585
+ cursor.CR();
2586
+ console.log(fmt, test.title, test.duration);
2587
+ }
2588
+ });
2589
+
2590
+ runner.on('fail', function(test, err){
2591
+ cursor.CR();
2592
+ console.log(indent() + color('fail', ' %d) %s'), ++n, test.title);
2593
+ });
2594
+
2595
+ runner.on('end', self.epilogue.bind(self));
2596
+ }
2597
+
2598
+ /**
2599
+ * Inherit from `Base.prototype`.
2600
+ */
2601
+
2602
+ Spec.prototype = new Base;
2603
+ Spec.prototype.constructor = Spec;
2604
+
2605
+
2606
+ }); // module: reporters/spec.js
2607
+
2608
+ require.register("reporters/tap.js", function(module, exports, require){
2609
+
2610
+ /**
2611
+ * Module dependencies.
2612
+ */
2613
+
2614
+ var Base = require('./base')
2615
+ , cursor = Base.cursor
2616
+ , color = Base.color;
2617
+
2618
+ /**
2619
+ * Expose `TAP`.
2620
+ */
2621
+
2622
+ exports = module.exports = TAP;
2623
+
2624
+ /**
2625
+ * Initialize a new `TAP` reporter.
2626
+ *
2627
+ * @param {Runner} runner
2628
+ * @api public
2629
+ */
2630
+
2631
+ function TAP(runner) {
2632
+ Base.call(this, runner);
2633
+
2634
+ var self = this
2635
+ , stats = this.stats
2636
+ , total = runner.total
2637
+ , n = 1;
2638
+
2639
+ runner.on('start', function(){
2640
+ console.log('%d..%d', 1, total);
2641
+ });
2642
+
2643
+ runner.on('test end', function(){
2644
+ ++n;
2645
+ });
2646
+
2647
+ runner.on('pending', function(test){
2648
+ console.log('ok %d %s # SKIP -', n, title(test));
2649
+ });
2650
+
2651
+ runner.on('pass', function(test){
2652
+ console.log('ok %d %s', n, title(test));
2653
+ });
2654
+
2655
+ runner.on('fail', function(test, err){
2656
+ console.log('not ok %d %s', n, title(test));
2657
+ console.log(err.stack.replace(/^/gm, ' '));
2658
+ });
2659
+ }
2660
+
2661
+ /**
2662
+ * Return a TAP-safe title of `test`
2663
+ *
2664
+ * @param {Object} test
2665
+ * @return {String}
2666
+ * @api private
2667
+ */
2668
+
2669
+ function title(test) {
2670
+ return test.fullTitle().replace(/#/g, '');
2671
+ }
2672
+
2673
+ }); // module: reporters/tap.js
2674
+
2675
+ require.register("reporters/teamcity.js", function(module, exports, require){
2676
+
2677
+ /**
2678
+ * Module dependencies.
2679
+ */
2680
+
2681
+ var Base = require('./base');
2682
+
2683
+ /**
2684
+ * Expose `Teamcity`.
2685
+ */
2686
+
2687
+ exports = module.exports = Teamcity;
2688
+
2689
+ /**
2690
+ * Initialize a new `Teamcity` reporter.
2691
+ *
2692
+ * @param {Runner} runner
2693
+ * @api public
2694
+ */
2695
+
2696
+ function Teamcity(runner) {
2697
+ Base.call(this, runner);
2698
+ var stats = this.stats;
2699
+
2700
+ runner.on('start', function() {
2701
+ console.log("##teamcity[testSuiteStarted name='mocha.suite']");
2702
+ });
2703
+
2704
+ runner.on('test', function(test) {
2705
+ console.log("##teamcity[testStarted name='%s']", escape(test.fullTitle()));
2706
+ });
2707
+
2708
+ runner.on('fail', function(test, err) {
2709
+ console.log("##teamcity[testFailed name='%s' message='%s']", escape(test.fullTitle()), escape(err.message));
2710
+ });
2711
+
2712
+ runner.on('pending', function(test) {
2713
+ console.log("##teamcity[testIgnored name='%s' message='pending']", escape(test.fullTitle()));
2714
+ });
2715
+
2716
+ runner.on('test end', function(test) {
2717
+ console.log("##teamcity[testFinished name='%s' duration='%s']", escape(test.fullTitle()), test.duration);
2718
+ });
2719
+
2720
+ runner.on('end', function() {
2721
+ console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='%s']", stats.duration);
2722
+ });
2723
+ }
2724
+
2725
+ /**
2726
+ * Escape the given `str`.
2727
+ */
2728
+
2729
+ function escape(str) {
2730
+ return str.replace(/'/g, "|'");
2731
+ }
2732
+ }); // module: reporters/teamcity.js
2733
+
2734
+ require.register("reporters/xunit.js", function(module, exports, require){
2735
+
2736
+ /**
2737
+ * Module dependencies.
2738
+ */
2739
+
2740
+ var Base = require('./base')
2741
+ , utils = require('../utils')
2742
+ , escape = utils.escape;
2743
+
2744
+ /**
2745
+ * Expose `XUnit`.
2746
+ */
2747
+
2748
+ exports = module.exports = XUnit;
2749
+
2750
+ /**
2751
+ * Initialize a new `XUnit` reporter.
2752
+ *
2753
+ * @param {Runner} runner
2754
+ * @api public
2755
+ */
2756
+
2757
+ function XUnit(runner) {
2758
+ Base.call(this, runner);
2759
+ var stats = this.stats
2760
+ , tests = []
2761
+ , self = this;
2762
+
2763
+ runner.on('test end', function(test){
2764
+ tests.push(test);
2765
+ });
2766
+
2767
+ runner.on('end', function(){
2768
+ console.log(tag('testsuite', {
2769
+ name: 'Mocha Tests'
2770
+ , tests: stats.tests
2771
+ , failures: stats.failures
2772
+ , errors: stats.failures
2773
+ , skip: stats.tests - stats.failures - stats.passes
2774
+ , timestamp: (new Date).toUTCString()
2775
+ , time: stats.duration / 1000
2776
+ }, false));
2777
+
2778
+ tests.forEach(test);
2779
+ console.log('</testsuite>');
2780
+ });
2781
+ }
2782
+
2783
+ /**
2784
+ * Inherit from `Base.prototype`.
2785
+ */
2786
+
2787
+ XUnit.prototype = new Base;
2788
+ XUnit.prototype.constructor = XUnit;
2789
+
2790
+
2791
+ /**
2792
+ * Output tag for the given `test.`
2793
+ */
2794
+
2795
+ function test(test) {
2796
+ var attrs = {
2797
+ classname: test.parent.fullTitle()
2798
+ , name: test.title
2799
+ , time: test.duration / 1000
2800
+ };
2801
+
2802
+ if ('failed' == test.state) {
2803
+ var err = test.err;
2804
+ attrs.message = escape(err.message);
2805
+ console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
2806
+ } else if (test.pending) {
2807
+ console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
2808
+ } else {
2809
+ console.log(tag('testcase', attrs, true) );
2810
+ }
2811
+ }
2812
+
2813
+ /**
2814
+ * HTML tag helper.
2815
+ */
2816
+
2817
+ function tag(name, attrs, close, content) {
2818
+ var end = close ? '/>' : '>'
2819
+ , pairs = []
2820
+ , tag;
2821
+
2822
+ for (var key in attrs) {
2823
+ pairs.push(key + '="' + escape(attrs[key]) + '"');
2824
+ }
2825
+
2826
+ tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
2827
+ if (content) tag += content + '</' + name + end;
2828
+ return tag;
2829
+ }
2830
+
2831
+ /**
2832
+ * Return cdata escaped CDATA `str`.
2833
+ */
2834
+
2835
+ function cdata(str) {
2836
+ return '<![CDATA[' + escape(str) + ']]>';
2837
+ }
2838
+
2839
+ }); // module: reporters/xunit.js
2840
+
2841
+ require.register("runnable.js", function(module, exports, require){
2842
+
2843
+ /**
2844
+ * Module dependencies.
2845
+ */
2846
+
2847
+ var EventEmitter = require('browser/events').EventEmitter
2848
+ , debug = require('browser/debug')('runnable');
2849
+
2850
+ /**
2851
+ * Expose `Runnable`.
2852
+ */
2853
+
2854
+ module.exports = Runnable;
2855
+
2856
+ /**
2857
+ * Initialize a new `Runnable` with the given `title` and callback `fn`.
2858
+ *
2859
+ * @param {String} title
2860
+ * @param {Function} fn
2861
+ * @api private
2862
+ */
2863
+
2864
+ function Runnable(title, fn) {
2865
+ this.title = title;
2866
+ this.fn = fn;
2867
+ this.async = fn && fn.length;
2868
+ this.sync = ! this.async;
2869
+ this._timeout = 2000;
2870
+ this.timedOut = false;
2871
+ }
2872
+
2873
+ /**
2874
+ * Inherit from `EventEmitter.prototype`.
2875
+ */
2876
+
2877
+ Runnable.prototype = new EventEmitter;
2878
+ Runnable.prototype.constructor = Runnable;
2879
+
2880
+
2881
+ /**
2882
+ * Set & get timeout `ms`.
2883
+ *
2884
+ * @param {Number} ms
2885
+ * @return {Runnable|Number} ms or self
2886
+ * @api private
2887
+ */
2888
+
2889
+ Runnable.prototype.timeout = function(ms){
2890
+ if (0 == arguments.length) return this._timeout;
2891
+ debug('timeout %d', ms);
2892
+ this._timeout = ms;
2893
+ if (this.timer) this.resetTimeout();
2894
+ return this;
2895
+ };
2896
+
2897
+ /**
2898
+ * Return the full title generated by recursively
2899
+ * concatenating the parent's full title.
2900
+ *
2901
+ * @return {String}
2902
+ * @api public
2903
+ */
2904
+
2905
+ Runnable.prototype.fullTitle = function(){
2906
+ return this.parent.fullTitle() + ' ' + this.title;
2907
+ };
2908
+
2909
+ /**
2910
+ * Clear the timeout.
2911
+ *
2912
+ * @api private
2913
+ */
2914
+
2915
+ Runnable.prototype.clearTimeout = function(){
2916
+ clearTimeout(this.timer);
2917
+ };
2918
+
2919
+ /**
2920
+ * Reset the timeout.
2921
+ *
2922
+ * @api private
2923
+ */
2924
+
2925
+ Runnable.prototype.resetTimeout = function(){
2926
+ var self = this
2927
+ , ms = this.timeout();
2928
+
2929
+ this.clearTimeout();
2930
+ if (ms) {
2931
+ this.timer = setTimeout(function(){
2932
+ self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
2933
+ self.timedOut = true;
2934
+ }, ms);
2935
+ }
2936
+ };
2937
+
2938
+ /**
2939
+ * Run the test and invoke `fn(err)`.
2940
+ *
2941
+ * @param {Function} fn
2942
+ * @api private
2943
+ */
2944
+
2945
+ Runnable.prototype.run = function(fn){
2946
+ var self = this
2947
+ , ms = this.timeout()
2948
+ , start = new Date
2949
+ , ctx = this.ctx
2950
+ , finished
2951
+ , emitted;
2952
+
2953
+ if (ctx) ctx.runnable(this);
2954
+
2955
+ // timeout
2956
+ if (this.async) {
2957
+ if (ms) {
2958
+ this.timer = setTimeout(function(){
2959
+ done(new Error('timeout of ' + ms + 'ms exceeded'));
2960
+ self.timedOut = true;
2961
+ }, ms);
2962
+ }
2963
+ }
2964
+
2965
+ // called multiple times
2966
+ function multiple() {
2967
+ if (emitted) return;
2968
+ emitted = true;
2969
+ self.emit('error', new Error('done() called multiple times'));
2970
+ }
2971
+
2972
+ // finished
2973
+ function done(err) {
2974
+ if (self.timedOut) return;
2975
+ if (finished) return multiple();
2976
+ self.clearTimeout();
2977
+ self.duration = new Date - start;
2978
+ finished = true;
2979
+ fn(err);
2980
+ }
2981
+
2982
+ // for .resetTimeout()
2983
+ this.callback = done;
2984
+
2985
+ // async
2986
+ if (this.async) {
2987
+ try {
2988
+ this.fn.call(ctx, function(err){
2989
+ if (err instanceof Error) return done(err);
2990
+ if (null != err) return done(new Error('done() invoked with non-Error: ' + err));
2991
+ done();
2992
+ });
2993
+ } catch (err) {
2994
+ done(err);
2995
+ }
2996
+ return;
2997
+ }
2998
+
2999
+ // sync
3000
+ try {
3001
+ if (!this.pending) this.fn.call(ctx);
3002
+ this.duration = new Date - start;
3003
+ fn();
3004
+ } catch (err) {
3005
+ fn(err);
3006
+ }
3007
+ };
3008
+
3009
+ }); // module: runnable.js
3010
+
3011
+ require.register("runner.js", function(module, exports, require){
3012
+
3013
+ /**
3014
+ * Module dependencies.
3015
+ */
3016
+
3017
+ var EventEmitter = require('browser/events').EventEmitter
3018
+ , debug = require('browser/debug')('runner')
3019
+ , Test = require('./test')
3020
+ , utils = require('./utils')
3021
+ , noop = function(){};
3022
+
3023
+ /**
3024
+ * Expose `Runner`.
3025
+ */
3026
+
3027
+ module.exports = Runner;
3028
+
3029
+ /**
3030
+ * Initialize a `Runner` for the given `suite`.
3031
+ *
3032
+ * Events:
3033
+ *
3034
+ * - `start` execution started
3035
+ * - `end` execution complete
3036
+ * - `suite` (suite) test suite execution started
3037
+ * - `suite end` (suite) all tests (and sub-suites) have finished
3038
+ * - `test` (test) test execution started
3039
+ * - `test end` (test) test completed
3040
+ * - `hook` (hook) hook execution started
3041
+ * - `hook end` (hook) hook complete
3042
+ * - `pass` (test) test passed
3043
+ * - `fail` (test, err) test failed
3044
+ *
3045
+ * @api public
3046
+ */
3047
+
3048
+ function Runner(suite) {
3049
+ var self = this;
3050
+ this._globals = [];
3051
+ this.suite = suite;
3052
+ this.total = suite.total();
3053
+ this.failures = 0;
3054
+ this.on('test end', function(test){ self.checkGlobals(test); });
3055
+ this.on('hook end', function(hook){ self.checkGlobals(hook); });
3056
+ this.grep(/.*/);
3057
+ this.globals(utils.keys(global).concat(['errno']));
3058
+ }
3059
+
3060
+ /**
3061
+ * Inherit from `EventEmitter.prototype`.
3062
+ */
3063
+
3064
+ Runner.prototype = new EventEmitter;
3065
+ Runner.prototype.constructor = Runner;
3066
+
3067
+
3068
+ /**
3069
+ * Run tests with full titles matching `re`. Updates runner.total
3070
+ * with number of tests matched.
3071
+ *
3072
+ * @param {RegExp} re
3073
+ * @return {Runner} for chaining
3074
+ * @api public
3075
+ */
3076
+
3077
+ Runner.prototype.grep = function(re){
3078
+ debug('grep %s', re);
3079
+ this._grep = re;
3080
+ this.total = this.grepTotal(this.suite);
3081
+ return this;
3082
+ };
3083
+
3084
+ /**
3085
+ * Returns the number of tests matching the grep search for the
3086
+ * given suite.
3087
+ *
3088
+ * @param {Suite} suite
3089
+ * @return {Number}
3090
+ * @api public
3091
+ */
3092
+
3093
+ Runner.prototype.grepTotal = function(suite) {
3094
+ var self = this;
3095
+ var total = 0;
3096
+
3097
+ suite.eachTest(function(test){
3098
+ if (self._grep.test(test.fullTitle())) total++;
3099
+ });
3100
+
3101
+ return total;
3102
+ };
3103
+
3104
+ /**
3105
+ * Allow the given `arr` of globals.
3106
+ *
3107
+ * @param {Array} arr
3108
+ * @return {Runner} for chaining
3109
+ * @api public
3110
+ */
3111
+
3112
+ Runner.prototype.globals = function(arr){
3113
+ if (0 == arguments.length) return this._globals;
3114
+ debug('globals %j', arr);
3115
+ utils.forEach(arr, function(arr){
3116
+ this._globals.push(arr);
3117
+ }, this);
3118
+ return this;
3119
+ };
3120
+
3121
+ /**
3122
+ * Check for global variable leaks.
3123
+ *
3124
+ * @api private
3125
+ */
3126
+
3127
+ Runner.prototype.checkGlobals = function(test){
3128
+ if (this.ignoreLeaks) return;
3129
+
3130
+ var leaks = utils.filter(utils.keys(global), function(key){
3131
+ return !~utils.indexOf(this._globals, key) && (!global.navigator || 'onerror' !== key);
3132
+ }, this);
3133
+
3134
+ this._globals = this._globals.concat(leaks);
3135
+
3136
+ if (leaks.length > 1) {
3137
+ this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
3138
+ } else if (leaks.length) {
3139
+ this.fail(test, new Error('global leak detected: ' + leaks[0]));
3140
+ }
3141
+ };
3142
+
3143
+ /**
3144
+ * Fail the given `test`.
3145
+ *
3146
+ * @param {Test} test
3147
+ * @param {Error} err
3148
+ * @api private
3149
+ */
3150
+
3151
+ Runner.prototype.fail = function(test, err){
3152
+ ++this.failures;
3153
+ test.state = 'failed';
3154
+ this.emit('fail', test, err);
3155
+ };
3156
+
3157
+ /**
3158
+ * Fail the given `hook` with `err`.
3159
+ *
3160
+ * Hook failures (currently) hard-end due
3161
+ * to that fact that a failing hook will
3162
+ * surely cause subsequent tests to fail,
3163
+ * causing jumbled reporting.
3164
+ *
3165
+ * @param {Hook} hook
3166
+ * @param {Error} err
3167
+ * @api private
3168
+ */
3169
+
3170
+ Runner.prototype.failHook = function(hook, err){
3171
+ this.fail(hook, err);
3172
+ this.emit('end');
3173
+ };
3174
+
3175
+ /**
3176
+ * Run hook `name` callbacks and then invoke `fn()`.
3177
+ *
3178
+ * @param {String} name
3179
+ * @param {Function} function
3180
+ * @api private
3181
+ */
3182
+
3183
+ Runner.prototype.hook = function(name, fn){
3184
+ var suite = this.suite
3185
+ , hooks = suite['_' + name]
3186
+ , ms = suite._timeout
3187
+ , self = this
3188
+ , timer;
3189
+
3190
+ function next(i) {
3191
+ var hook = hooks[i];
3192
+ if (!hook) return fn();
3193
+ self.currentRunnable = hook;
3194
+
3195
+ self.emit('hook', hook);
3196
+
3197
+ hook.on('error', function(err){
3198
+ self.failHook(hook, err);
3199
+ });
3200
+
3201
+ hook.run(function(err){
3202
+ hook.removeAllListeners('error');
3203
+ if (err) return self.failHook(hook, err);
3204
+ self.emit('hook end', hook);
3205
+ next(++i);
3206
+ });
3207
+ }
3208
+
3209
+ process.nextTick(function(){
3210
+ next(0);
3211
+ });
3212
+ };
3213
+
3214
+ /**
3215
+ * Run hook `name` for the given array of `suites`
3216
+ * in order, and callback `fn(err)`.
3217
+ *
3218
+ * @param {String} name
3219
+ * @param {Array} suites
3220
+ * @param {Function} fn
3221
+ * @api private
3222
+ */
3223
+
3224
+ Runner.prototype.hooks = function(name, suites, fn){
3225
+ var self = this
3226
+ , orig = this.suite;
3227
+
3228
+ function next(suite) {
3229
+ self.suite = suite;
3230
+
3231
+ if (!suite) {
3232
+ self.suite = orig;
3233
+ return fn();
3234
+ }
3235
+
3236
+ self.hook(name, function(err){
3237
+ if (err) {
3238
+ self.suite = orig;
3239
+ return fn(err);
3240
+ }
3241
+
3242
+ next(suites.pop());
3243
+ });
3244
+ }
3245
+
3246
+ next(suites.pop());
3247
+ };
3248
+
3249
+ /**
3250
+ * Run hooks from the top level down.
3251
+ *
3252
+ * @param {String} name
3253
+ * @param {Function} fn
3254
+ * @api private
3255
+ */
3256
+
3257
+ Runner.prototype.hookUp = function(name, fn){
3258
+ var suites = [this.suite].concat(this.parents()).reverse();
3259
+ this.hooks(name, suites, fn);
3260
+ };
3261
+
3262
+ /**
3263
+ * Run hooks from the bottom up.
3264
+ *
3265
+ * @param {String} name
3266
+ * @param {Function} fn
3267
+ * @api private
3268
+ */
3269
+
3270
+ Runner.prototype.hookDown = function(name, fn){
3271
+ var suites = [this.suite].concat(this.parents());
3272
+ this.hooks(name, suites, fn);
3273
+ };
3274
+
3275
+ /**
3276
+ * Return an array of parent Suites from
3277
+ * closest to furthest.
3278
+ *
3279
+ * @return {Array}
3280
+ * @api private
3281
+ */
3282
+
3283
+ Runner.prototype.parents = function(){
3284
+ var suite = this.suite
3285
+ , suites = [];
3286
+ while (suite = suite.parent) suites.push(suite);
3287
+ return suites;
3288
+ };
3289
+
3290
+ /**
3291
+ * Run the current test and callback `fn(err)`.
3292
+ *
3293
+ * @param {Function} fn
3294
+ * @api private
3295
+ */
3296
+
3297
+ Runner.prototype.runTest = function(fn){
3298
+ var test = this.test
3299
+ , self = this;
3300
+
3301
+ try {
3302
+ test.on('error', function(err){
3303
+ self.fail(test, err);
3304
+ });
3305
+ test.run(fn);
3306
+ } catch (err) {
3307
+ fn(err);
3308
+ }
3309
+ };
3310
+
3311
+ /**
3312
+ * Run tests in the given `suite` and invoke
3313
+ * the callback `fn()` when complete.
3314
+ *
3315
+ * @param {Suite} suite
3316
+ * @param {Function} fn
3317
+ * @api private
3318
+ */
3319
+
3320
+ Runner.prototype.runTests = function(suite, fn){
3321
+ var self = this
3322
+ , tests = suite.tests
3323
+ , test;
3324
+
3325
+ function next(err) {
3326
+ // if we bail after first err
3327
+ if (self.failures && suite._bail) return fn();
3328
+
3329
+ // next test
3330
+ test = tests.shift();
3331
+
3332
+ // all done
3333
+ if (!test) return fn();
3334
+
3335
+ // grep
3336
+ if (!self._grep.test(test.fullTitle())) return next();
3337
+
3338
+ // pending
3339
+ if (test.pending) {
3340
+ self.emit('pending', test);
3341
+ self.emit('test end', test);
3342
+ return next();
3343
+ }
3344
+
3345
+ // execute test and hook(s)
3346
+ self.emit('test', self.test = test);
3347
+ self.hookDown('beforeEach', function(){
3348
+ self.currentRunnable = self.test;
3349
+ self.runTest(function(err){
3350
+ test = self.test;
3351
+
3352
+ if (err) {
3353
+ self.fail(test, err);
3354
+ self.emit('test end', test);
3355
+ return self.hookUp('afterEach', next);
3356
+ }
3357
+
3358
+ test.state = 'passed';
3359
+ self.emit('pass', test);
3360
+ self.emit('test end', test);
3361
+ self.hookUp('afterEach', next);
3362
+ });
3363
+ });
3364
+ }
3365
+
3366
+ this.next = next;
3367
+ next();
3368
+ };
3369
+
3370
+ /**
3371
+ * Run the given `suite` and invoke the
3372
+ * callback `fn()` when complete.
3373
+ *
3374
+ * @param {Suite} suite
3375
+ * @param {Function} fn
3376
+ * @api private
3377
+ */
3378
+
3379
+ Runner.prototype.runSuite = function(suite, fn){
3380
+ var total = this.grepTotal(suite)
3381
+ , self = this
3382
+ , i = 0;
3383
+
3384
+ debug('run suite %s', suite.fullTitle());
3385
+
3386
+ if (!total) return fn();
3387
+
3388
+ this.emit('suite', this.suite = suite);
3389
+
3390
+ function next() {
3391
+ var curr = suite.suites[i++];
3392
+ if (!curr) return done();
3393
+ self.runSuite(curr, next);
3394
+ }
3395
+
3396
+ function done() {
3397
+ self.suite = suite;
3398
+ self.hook('afterAll', function(){
3399
+ self.emit('suite end', suite);
3400
+ fn();
3401
+ });
3402
+ }
3403
+
3404
+ this.hook('beforeAll', function(){
3405
+ self.runTests(suite, next);
3406
+ });
3407
+ };
3408
+
3409
+ /**
3410
+ * Handle uncaught exceptions.
3411
+ *
3412
+ * @param {Error} err
3413
+ * @api private
3414
+ */
3415
+
3416
+ Runner.prototype.uncaught = function(err){
3417
+ debug('uncaught exception');
3418
+ var runnable = this.currentRunnable;
3419
+ if ('failed' == runnable.state) return;
3420
+ runnable.clearTimeout();
3421
+ err.uncaught = true;
3422
+ this.fail(runnable, err);
3423
+
3424
+ // recover from test
3425
+ if ('test' == runnable.type) {
3426
+ this.emit('test end', runnable);
3427
+ this.hookUp('afterEach', this.next);
3428
+ return;
3429
+ }
3430
+
3431
+ // bail on hooks
3432
+ this.emit('end');
3433
+ };
3434
+
3435
+ /**
3436
+ * Run the root suite and invoke `fn(failures)`
3437
+ * on completion.
3438
+ *
3439
+ * @param {Function} fn
3440
+ * @return {Runner} for chaining
3441
+ * @api public
3442
+ */
3443
+
3444
+ Runner.prototype.run = function(fn){
3445
+ var self = this
3446
+ , fn = fn || function(){};
3447
+
3448
+ debug('start');
3449
+
3450
+ // callback
3451
+ this.on('end', function(){
3452
+ debug('end');
3453
+ process.removeListener('uncaughtException', this.uncaught);
3454
+ fn(self.failures);
3455
+ });
3456
+
3457
+ // run suites
3458
+ this.emit('start');
3459
+ this.runSuite(this.suite, function(){
3460
+ debug('finished running');
3461
+ self.emit('end');
3462
+ });
3463
+
3464
+ // uncaught exception
3465
+ process.on('uncaughtException', function(err){
3466
+ self.uncaught(err);
3467
+ });
3468
+
3469
+ return this;
3470
+ };
3471
+
3472
+ }); // module: runner.js
3473
+
3474
+ require.register("suite.js", function(module, exports, require){
3475
+
3476
+ /**
3477
+ * Module dependencies.
3478
+ */
3479
+
3480
+ var EventEmitter = require('browser/events').EventEmitter
3481
+ , debug = require('browser/debug')('suite')
3482
+ , utils = require('./utils')
3483
+ , Hook = require('./hook');
3484
+
3485
+ /**
3486
+ * Expose `Suite`.
3487
+ */
3488
+
3489
+ exports = module.exports = Suite;
3490
+
3491
+ /**
3492
+ * Create a new `Suite` with the given `title`
3493
+ * and parent `Suite`. When a suite with the
3494
+ * same title is already present, that suite
3495
+ * is returned to provide nicer reporter
3496
+ * and more flexible meta-testing.
3497
+ *
3498
+ * @param {Suite} parent
3499
+ * @param {String} title
3500
+ * @return {Suite}
3501
+ * @api public
3502
+ */
3503
+
3504
+ exports.create = function(parent, title){
3505
+ var suite = new Suite(title, parent.ctx);
3506
+ suite.parent = parent;
3507
+ title = suite.fullTitle();
3508
+ parent.addSuite(suite);
3509
+ return suite;
3510
+ };
3511
+
3512
+ /**
3513
+ * Initialize a new `Suite` with the given
3514
+ * `title` and `ctx`.
3515
+ *
3516
+ * @param {String} title
3517
+ * @param {Context} ctx
3518
+ * @api private
3519
+ */
3520
+
3521
+ function Suite(title, ctx) {
3522
+ this.title = title;
3523
+ this.ctx = ctx;
3524
+ this.suites = [];
3525
+ this.tests = [];
3526
+ this._beforeEach = [];
3527
+ this._beforeAll = [];
3528
+ this._afterEach = [];
3529
+ this._afterAll = [];
3530
+ this.root = !title;
3531
+ this._timeout = 2000;
3532
+ this._bail = false;
3533
+ }
3534
+
3535
+ /**
3536
+ * Inherit from `EventEmitter.prototype`.
3537
+ */
3538
+
3539
+ Suite.prototype = new EventEmitter;
3540
+ Suite.prototype.constructor = Suite;
3541
+
3542
+
3543
+ /**
3544
+ * Return a clone of this `Suite`.
3545
+ *
3546
+ * @return {Suite}
3547
+ * @api private
3548
+ */
3549
+
3550
+ Suite.prototype.clone = function(){
3551
+ var suite = new Suite(this.title);
3552
+ debug('clone');
3553
+ suite.ctx = this.ctx;
3554
+ suite.timeout(this.timeout());
3555
+ suite.bail(this.bail());
3556
+ return suite;
3557
+ };
3558
+
3559
+ /**
3560
+ * Set timeout `ms` or short-hand such as "2s".
3561
+ *
3562
+ * @param {Number|String} ms
3563
+ * @return {Suite|Number} for chaining
3564
+ * @api private
3565
+ */
3566
+
3567
+ Suite.prototype.timeout = function(ms){
3568
+ if (0 == arguments.length) return this._timeout;
3569
+ if (String(ms).match(/s$/)) ms = parseFloat(ms) * 1000;
3570
+ debug('timeout %d', ms);
3571
+ this._timeout = parseInt(ms, 10);
3572
+ return this;
3573
+ };
3574
+
3575
+ /**
3576
+ * Sets whether to bail after first error.
3577
+ *
3578
+ * @parma {Boolean} bail
3579
+ * @return {Suite|Number} for chaining
3580
+ * @api private
3581
+ */
3582
+
3583
+ Suite.prototype.bail = function(bail){
3584
+ if (0 == arguments.length) return this._bail;
3585
+ debug('bail %s', bail);
3586
+ this._bail = bail;
3587
+ return this;
3588
+ };
3589
+
3590
+ /**
3591
+ * Run `fn(test[, done])` before running tests.
3592
+ *
3593
+ * @param {Function} fn
3594
+ * @return {Suite} for chaining
3595
+ * @api private
3596
+ */
3597
+
3598
+ Suite.prototype.beforeAll = function(fn){
3599
+ var hook = new Hook('"before all" hook', fn);
3600
+ hook.parent = this;
3601
+ hook.timeout(this.timeout());
3602
+ hook.ctx = this.ctx;
3603
+ this._beforeAll.push(hook);
3604
+ this.emit('beforeAll', hook);
3605
+ return this;
3606
+ };
3607
+
3608
+ /**
3609
+ * Run `fn(test[, done])` after running tests.
3610
+ *
3611
+ * @param {Function} fn
3612
+ * @return {Suite} for chaining
3613
+ * @api private
3614
+ */
3615
+
3616
+ Suite.prototype.afterAll = function(fn){
3617
+ var hook = new Hook('"after all" hook', fn);
3618
+ hook.parent = this;
3619
+ hook.timeout(this.timeout());
3620
+ hook.ctx = this.ctx;
3621
+ this._afterAll.push(hook);
3622
+ this.emit('afterAll', hook);
3623
+ return this;
3624
+ };
3625
+
3626
+ /**
3627
+ * Run `fn(test[, done])` before each test case.
3628
+ *
3629
+ * @param {Function} fn
3630
+ * @return {Suite} for chaining
3631
+ * @api private
3632
+ */
3633
+
3634
+ Suite.prototype.beforeEach = function(fn){
3635
+ var hook = new Hook('"before each" hook', fn);
3636
+ hook.parent = this;
3637
+ hook.timeout(this.timeout());
3638
+ hook.ctx = this.ctx;
3639
+ this._beforeEach.push(hook);
3640
+ this.emit('beforeEach', hook);
3641
+ return this;
3642
+ };
3643
+
3644
+ /**
3645
+ * Run `fn(test[, done])` after each test case.
3646
+ *
3647
+ * @param {Function} fn
3648
+ * @return {Suite} for chaining
3649
+ * @api private
3650
+ */
3651
+
3652
+ Suite.prototype.afterEach = function(fn){
3653
+ var hook = new Hook('"after each" hook', fn);
3654
+ hook.parent = this;
3655
+ hook.timeout(this.timeout());
3656
+ hook.ctx = this.ctx;
3657
+ this._afterEach.push(hook);
3658
+ this.emit('afterEach', hook);
3659
+ return this;
3660
+ };
3661
+
3662
+ /**
3663
+ * Add a test `suite`.
3664
+ *
3665
+ * @param {Suite} suite
3666
+ * @return {Suite} for chaining
3667
+ * @api private
3668
+ */
3669
+
3670
+ Suite.prototype.addSuite = function(suite){
3671
+ suite.parent = this;
3672
+ suite.timeout(this.timeout());
3673
+ suite.bail(this.bail());
3674
+ this.suites.push(suite);
3675
+ this.emit('suite', suite);
3676
+ return this;
3677
+ };
3678
+
3679
+ /**
3680
+ * Add a `test` to this suite.
3681
+ *
3682
+ * @param {Test} test
3683
+ * @return {Suite} for chaining
3684
+ * @api private
3685
+ */
3686
+
3687
+ Suite.prototype.addTest = function(test){
3688
+ test.parent = this;
3689
+ test.timeout(this.timeout());
3690
+ test.ctx = this.ctx;
3691
+ this.tests.push(test);
3692
+ this.emit('test', test);
3693
+ return this;
3694
+ };
3695
+
3696
+ /**
3697
+ * Return the full title generated by recursively
3698
+ * concatenating the parent's full title.
3699
+ *
3700
+ * @return {String}
3701
+ * @api public
3702
+ */
3703
+
3704
+ Suite.prototype.fullTitle = function(){
3705
+ if (this.parent) {
3706
+ var full = this.parent.fullTitle();
3707
+ if (full) return full + ' ' + this.title;
3708
+ }
3709
+ return this.title;
3710
+ };
3711
+
3712
+ /**
3713
+ * Return the total number of tests.
3714
+ *
3715
+ * @return {Number}
3716
+ * @api public
3717
+ */
3718
+
3719
+ Suite.prototype.total = function(){
3720
+ return utils.reduce(this.suites, function(sum, suite){
3721
+ return sum + suite.total();
3722
+ }, 0) + this.tests.length;
3723
+ };
3724
+
3725
+ /**
3726
+ * Iterates through each suite recursively to find
3727
+ * all tests. Applies a function in the format
3728
+ * `fn(test)`.
3729
+ *
3730
+ * @param {Function} fn
3731
+ * @return {Suite}
3732
+ * @api private
3733
+ */
3734
+
3735
+ Suite.prototype.eachTest = function(fn){
3736
+ utils.forEach(this.tests, fn);
3737
+ utils.forEach(this.suites, function(suite){
3738
+ suite.eachTest(fn);
3739
+ });
3740
+ return this;
3741
+ };
3742
+
3743
+ }); // module: suite.js
3744
+
3745
+ require.register("test.js", function(module, exports, require){
3746
+
3747
+ /**
3748
+ * Module dependencies.
3749
+ */
3750
+
3751
+ var Runnable = require('./runnable');
3752
+
3753
+ /**
3754
+ * Expose `Test`.
3755
+ */
3756
+
3757
+ module.exports = Test;
3758
+
3759
+ /**
3760
+ * Initialize a new `Test` with the given `title` and callback `fn`.
3761
+ *
3762
+ * @param {String} title
3763
+ * @param {Function} fn
3764
+ * @api private
3765
+ */
3766
+
3767
+ function Test(title, fn) {
3768
+ Runnable.call(this, title, fn);
3769
+ this.pending = !fn;
3770
+ this.type = 'test';
3771
+ }
3772
+
3773
+ /**
3774
+ * Inherit from `Runnable.prototype`.
3775
+ */
3776
+
3777
+ Test.prototype = new Runnable;
3778
+ Test.prototype.constructor = Test;
3779
+
3780
+
3781
+ /**
3782
+ * Inspect the context void of private properties.
3783
+ *
3784
+ * @return {String}
3785
+ * @api private
3786
+ */
3787
+
3788
+ Test.prototype.inspect = function(){
3789
+ return JSON.stringify(this, function(key, val){
3790
+ return '_' == key[0]
3791
+ ? undefined
3792
+ : 'parent' == key
3793
+ ? '#<Suite>'
3794
+ : val;
3795
+ }, 2);
3796
+ };
3797
+ }); // module: test.js
3798
+
3799
+ require.register("utils.js", function(module, exports, require){
3800
+
3801
+ /**
3802
+ * Module dependencies.
3803
+ */
3804
+
3805
+ var fs = require('browser/fs')
3806
+ , path = require('browser/path')
3807
+ , join = path.join
3808
+ , debug = require('browser/debug')('watch');
3809
+
3810
+ /**
3811
+ * Ignored directories.
3812
+ */
3813
+
3814
+ var ignore = ['node_modules', '.git'];
3815
+
3816
+ /**
3817
+ * Escape special characters in the given string of html.
3818
+ *
3819
+ * @param {String} html
3820
+ * @return {String}
3821
+ * @api private
3822
+ */
3823
+
3824
+ exports.escape = function(html) {
3825
+ return String(html)
3826
+ .replace(/&/g, '&amp;')
3827
+ .replace(/"/g, '&quot;')
3828
+ .replace(/</g, '&lt;')
3829
+ .replace(/>/g, '&gt;');
3830
+ };
3831
+
3832
+ /**
3833
+ * Array#forEach (<=IE8)
3834
+ *
3835
+ * @param {Array} array
3836
+ * @param {Function} fn
3837
+ * @param {Object} scope
3838
+ * @api private
3839
+ */
3840
+
3841
+ exports.forEach = function(arr, fn, scope) {
3842
+ for (var i = 0, l = arr.length; i < l; i++)
3843
+ fn.call(scope, arr[i], i);
3844
+ };
3845
+
3846
+ /**
3847
+ * Array#indexOf (<=IE8)
3848
+ *
3849
+ * @parma {Array} arr
3850
+ * @param {Object} obj to find index of
3851
+ * @param {Number} start
3852
+ * @api private
3853
+ */
3854
+
3855
+ exports.indexOf = function (arr, obj, start) {
3856
+ for (var i = start || 0, l = arr.length; i < l; i++) {
3857
+ if (arr[i] === obj)
3858
+ return i;
3859
+ }
3860
+ return -1;
3861
+ };
3862
+
3863
+ /**
3864
+ * Array#reduce (<=IE8)
3865
+ *
3866
+ * @param {Array} array
3867
+ * @param {Function} fn
3868
+ * @param {Object} initial value
3869
+ * @param {Object} scope
3870
+ * @api private
3871
+ */
3872
+
3873
+ exports.reduce = function(arr, fn, val, scope) {
3874
+ var rval = val;
3875
+
3876
+ for (var i = 0, l = arr.length; i < l; i++) {
3877
+ rval = fn.call(scope, rval, arr[i], i, arr);
3878
+ }
3879
+
3880
+ return rval;
3881
+ };
3882
+
3883
+ /**
3884
+ * Array#filter (<=IE8)
3885
+ *
3886
+ * @param {Array} array
3887
+ * @param {Function} fn
3888
+ * @param {Object} scope
3889
+ * @api private
3890
+ */
3891
+
3892
+ exports.filter = function(arr, fn, scope) {
3893
+ var ret = [];
3894
+
3895
+ for (var i = 0, l = arr.length; i < l; i++) {
3896
+ var val = arr[i];
3897
+ if (fn.call(scope, val, i, arr))
3898
+ ret.push(val);
3899
+ }
3900
+
3901
+ return ret;
3902
+ };
3903
+
3904
+ /**
3905
+ * Object.keys (<=IE8)
3906
+ *
3907
+ * @param {Object} obj
3908
+ * @return {Array} keys
3909
+ * @api private
3910
+ */
3911
+
3912
+ exports.keys = Object.keys || function(obj) {
3913
+ var keys = []
3914
+ , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
3915
+
3916
+ for (var key in obj) {
3917
+ if (has.call(obj, key)) {
3918
+ keys.push(key);
3919
+ }
3920
+ }
3921
+
3922
+ return keys;
3923
+ };
3924
+
3925
+ /**
3926
+ * Watch the given `files` for changes
3927
+ * and invoke `fn(file)` on modification.
3928
+ *
3929
+ * @param {Array} files
3930
+ * @param {Function} fn
3931
+ * @api private
3932
+ */
3933
+
3934
+ exports.watch = function(files, fn){
3935
+ var options = { interval: 100 };
3936
+ files.forEach(function(file){
3937
+ debug('file %s', file);
3938
+ fs.watchFile(file, options, function(curr, prev){
3939
+ if (prev.mtime < curr.mtime) fn(file);
3940
+ });
3941
+ });
3942
+ };
3943
+
3944
+ /**
3945
+ * Ignored files.
3946
+ */
3947
+
3948
+ function ignored(path){
3949
+ return !~ignore.indexOf(path);
3950
+ }
3951
+
3952
+ /**
3953
+ * Lookup files in the given `dir`.
3954
+ *
3955
+ * @return {Array}
3956
+ * @api private
3957
+ */
3958
+
3959
+ exports.files = function(dir, ret){
3960
+ ret = ret || [];
3961
+
3962
+ fs.readdirSync(dir)
3963
+ .filter(ignored)
3964
+ .forEach(function(path){
3965
+ path = join(dir, path);
3966
+ if (fs.statSync(path).isDirectory()) {
3967
+ exports.files(path, ret);
3968
+ } else if (path.match(/\.(js|coffee)$/)) {
3969
+ ret.push(path);
3970
+ }
3971
+ });
3972
+
3973
+ return ret;
3974
+ };
3975
+
3976
+ /**
3977
+ * Compute a slug from the given `str`.
3978
+ *
3979
+ * @param {String} str
3980
+ * @return {String}
3981
+ */
3982
+
3983
+ exports.slug = function(str){
3984
+ return str
3985
+ .toLowerCase()
3986
+ .replace(/ +/g, '-')
3987
+ .replace(/[^-\w]/g, '');
3988
+ };
3989
+ }); // module: utils.js
3990
+ /**
3991
+ * Node shims.
3992
+ *
3993
+ * These are meant only to allow
3994
+ * mocha.js to run untouched, not
3995
+ * to allow running node code in
3996
+ * the browser.
3997
+ */
3998
+
3999
+ process = {};
4000
+ process.exit = function(status){};
4001
+ process.stdout = {};
4002
+ global = window;
4003
+
4004
+ /**
4005
+ * next tick implementation.
4006
+ */
4007
+
4008
+ process.nextTick = (function(){
4009
+ // postMessage behaves badly on IE8
4010
+ if (window.ActiveXObject || !window.postMessage) {
4011
+ return function(fn){ fn() };
4012
+ }
4013
+
4014
+ // based on setZeroTimeout by David Baron
4015
+ // - http://dbaron.org/log/20100309-faster-timeouts
4016
+ var timeouts = []
4017
+ , name = 'mocha-zero-timeout'
4018
+
4019
+ window.addEventListener('message', function(e){
4020
+ if (e.source == window && e.data == name) {
4021
+ if (e.stopPropagation) e.stopPropagation();
4022
+ if (timeouts.length) timeouts.shift()();
4023
+ }
4024
+ }, true);
4025
+
4026
+ return function(fn){
4027
+ timeouts.push(fn);
4028
+ window.postMessage(name, '*');
4029
+ }
4030
+ })();
4031
+
4032
+ /**
4033
+ * Remove uncaughtException listener.
4034
+ */
4035
+
4036
+ process.removeListener = function(e){
4037
+ if ('uncaughtException' == e) {
4038
+ window.onerror = null;
4039
+ }
4040
+ };
4041
+
4042
+ /**
4043
+ * Implements uncaughtException listener.
4044
+ */
4045
+
4046
+ process.on = function(e, fn){
4047
+ if ('uncaughtException' == e) {
4048
+ window.onerror = fn;
4049
+ }
4050
+ };
4051
+
4052
+ /**
4053
+ * Expose mocha.
4054
+ */
4055
+
4056
+ window.mocha = require('mocha');
4057
+
4058
+ // boot
4059
+ ;(function(){
4060
+ var suite = new mocha.Suite('', new mocha.Context)
4061
+ , utils = mocha.utils
4062
+ , options = {}
4063
+
4064
+ /**
4065
+ * Highlight the given string of `js`.
4066
+ */
4067
+
4068
+ function highlight(js) {
4069
+ return js
4070
+ .replace(/</g, '&lt;')
4071
+ .replace(/>/g, '&gt;')
4072
+ .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
4073
+ .replace(/('.*?')/gm, '<span class="string">$1</span>')
4074
+ .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
4075
+ .replace(/(\d+)/gm, '<span class="number">$1</span>')
4076
+ .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
4077
+ .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
4078
+ }
4079
+
4080
+ /**
4081
+ * Highlight code contents.
4082
+ */
4083
+
4084
+ function highlightCode() {
4085
+ var code = document.getElementsByTagName('code');
4086
+ for (var i = 0, len = code.length; i < len; ++i) {
4087
+ code[i].innerHTML = highlight(code[i].innerHTML);
4088
+ }
4089
+ }
4090
+
4091
+ /**
4092
+ * Parse the given `qs`.
4093
+ */
4094
+
4095
+ function parse(qs) {
4096
+ return utils.reduce(qs.replace('?', '').split('&'), function(obj, pair){
4097
+ var i = pair.indexOf('=')
4098
+ , key = pair.slice(0, i)
4099
+ , val = pair.slice(++i);
4100
+
4101
+ obj[key] = decodeURIComponent(val);
4102
+ return obj;
4103
+ }, {});
4104
+ }
4105
+
4106
+ /**
4107
+ * Setup mocha with the given setting options.
4108
+ */
4109
+
4110
+ mocha.setup = function(opts){
4111
+ if ('string' === typeof opts) options.ui = opts;
4112
+ else options = opts;
4113
+
4114
+ ui = mocha.interfaces[options.ui];
4115
+ if (!ui) throw new Error('invalid mocha interface "' + ui + '"');
4116
+ if (options.timeout) suite.timeout(options.timeout);
4117
+ ui(suite);
4118
+ suite.emit('pre-require', window);
4119
+ };
4120
+
4121
+ /**
4122
+ * Run mocha, returning the Runner.
4123
+ */
4124
+
4125
+ mocha.run = function(fn){
4126
+ suite.emit('run');
4127
+ var runner = new mocha.Runner(suite);
4128
+ var Reporter = options.reporter || mocha.reporters.HTML;
4129
+ var reporter = new Reporter(runner);
4130
+ var query = parse(window.location.search || "");
4131
+ if (query.grep) runner.grep(new RegExp(query.grep));
4132
+ if (options.ignoreLeaks) runner.ignoreLeaks = true;
4133
+ if (options.globals) runner.globals(options.globals);
4134
+ runner.globals(['location']);
4135
+ runner.on('end', highlightCode);
4136
+ return runner.run(fn);
4137
+ };
4138
+ })();
4139
+ })();