multi_mocha_rails 0.0.4

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.
Files changed (55) hide show
  1. data/MIT-LICENSE +22 -0
  2. data/Rakefile +38 -0
  3. data/Readme.md +7 -0
  4. data/app/assets/javascripts/mocha_rails/application.js +4 -0
  5. data/app/assets/javascripts/mocha_rails/mocha-rails.js +7 -0
  6. data/app/assets/stylesheets/mocha_rails/application.css +13 -0
  7. data/app/controllers/mocha_rails/application_controller.rb +4 -0
  8. data/app/controllers/mocha_rails/tests_controller.rb +52 -0
  9. data/app/helpers/mocha_rails/application_helper.rb +4 -0
  10. data/app/views/layouts/mocha.html.erb +14 -0
  11. data/app/views/mocha_rails/tests/index.html.erb +10 -0
  12. data/app/views/mocha_rails/tests/list.html.erb +11 -0
  13. data/config/initializers/mocha_rails.rb +4 -0
  14. data/config/routes.rb +8 -0
  15. data/lib/generators/mocha_rails/install_generator.rb +15 -0
  16. data/lib/generators/mocha_rails/templates/mocha-suite.js +12 -0
  17. data/lib/mocha_rails.rb +4 -0
  18. data/lib/mocha_rails/engine.rb +5 -0
  19. data/lib/mocha_rails/version.rb +3 -0
  20. data/lib/tasks/mocha_rails_tasks.rake +4 -0
  21. data/test/dummy/README.rdoc +261 -0
  22. data/test/dummy/Rakefile +7 -0
  23. data/test/dummy/app/assets/javascripts/application.js +15 -0
  24. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  25. data/test/dummy/app/controllers/application_controller.rb +3 -0
  26. data/test/dummy/app/helpers/application_helper.rb +2 -0
  27. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  28. data/test/dummy/config.ru +4 -0
  29. data/test/dummy/config/application.rb +62 -0
  30. data/test/dummy/config/boot.rb +10 -0
  31. data/test/dummy/config/environment.rb +5 -0
  32. data/test/dummy/config/environments/development.rb +31 -0
  33. data/test/dummy/config/environments/production.rb +64 -0
  34. data/test/dummy/config/environments/test.rb +35 -0
  35. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  36. data/test/dummy/config/initializers/inflections.rb +15 -0
  37. data/test/dummy/config/initializers/mime_types.rb +5 -0
  38. data/test/dummy/config/initializers/secret_token.rb +7 -0
  39. data/test/dummy/config/initializers/session_store.rb +8 -0
  40. data/test/dummy/config/initializers/wrap_parameters.rb +10 -0
  41. data/test/dummy/config/locales/en.yml +5 -0
  42. data/test/dummy/config/routes.rb +4 -0
  43. data/test/dummy/log/test.log +0 -0
  44. data/test/dummy/public/404.html +26 -0
  45. data/test/dummy/public/422.html +26 -0
  46. data/test/dummy/public/500.html +25 -0
  47. data/test/dummy/public/favicon.ico +0 -0
  48. data/test/dummy/script/rails +6 -0
  49. data/test/integration/navigation_test.rb +9 -0
  50. data/test/mocha_rails_test.rb +7 -0
  51. data/test/test_helper.rb +10 -0
  52. data/vendor/assets/javascripts/chai.js +2223 -0
  53. data/vendor/assets/javascripts/mocha.js +4068 -0
  54. data/vendor/assets/stylesheets/mocha.css +137 -0
  55. metadata +141 -0
@@ -0,0 +1,4068 @@
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 `Test` to `test`.
411
+ *
412
+ * @param {Test} test
413
+ * @return {Context}
414
+ * @api private
415
+ */
416
+
417
+ Context.prototype.test = function(test){
418
+ this._test = test;
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._test.timeout(ms);
432
+ return this;
433
+ };
434
+
435
+ /**
436
+ * Inspect the context void of `._test`.
437
+ *
438
+ * @return {String}
439
+ * @api private
440
+ */
441
+
442
+ Context.prototype.inspect = function(){
443
+ return JSON.stringify(this, function(key, val){
444
+ return '_test' == 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.0';
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, 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
+
1271
+ /**
1272
+ * Output common epilogue used by many of
1273
+ * the bundled reporters.
1274
+ *
1275
+ * @api public
1276
+ */
1277
+
1278
+ Base.prototype.epilogue = function(){
1279
+ var stats = this.stats
1280
+ , fmt;
1281
+
1282
+ console.log();
1283
+
1284
+ // failure
1285
+ if (stats.failures) {
1286
+ fmt = color('bright fail', ' ✖')
1287
+ + color('fail', ' %d of %d tests failed')
1288
+ + color('light', ':')
1289
+
1290
+ console.error(fmt, stats.failures, this.runner.total);
1291
+ Base.list(this.failures);
1292
+ console.error();
1293
+ return;
1294
+ }
1295
+
1296
+ // pass
1297
+ fmt = color('bright pass', ' ✔')
1298
+ + color('green', ' %d tests complete')
1299
+ + color('light', ' (%dms)');
1300
+
1301
+ console.log(fmt, stats.tests || 0, stats.duration);
1302
+ console.log();
1303
+ };
1304
+
1305
+ /**
1306
+ * Pad the given `str` to `len`.
1307
+ *
1308
+ * @param {String} str
1309
+ * @param {String} len
1310
+ * @return {String}
1311
+ * @api private
1312
+ */
1313
+
1314
+ function pad(str, len) {
1315
+ str = String(str);
1316
+ return Array(len - str.length + 1).join(' ') + str;
1317
+ }
1318
+
1319
+ /**
1320
+ * Return a character diff for `err`.
1321
+ *
1322
+ * @param {Error} err
1323
+ * @return {String}
1324
+ * @api private
1325
+ */
1326
+
1327
+ function errorDiff(err, type) {
1328
+ return diff['diff' + type](err.actual, err.expected).map(function(str){
1329
+ if (str.added) return colorLines('diff added', str.value);
1330
+ if (str.removed) return colorLines('diff removed', str.value);
1331
+ return str.value;
1332
+ }).join('');
1333
+ }
1334
+
1335
+ /**
1336
+ * Color lines for `str`, using the color `name`.
1337
+ *
1338
+ * @param {String} name
1339
+ * @param {String} str
1340
+ * @return {String}
1341
+ * @api private
1342
+ */
1343
+
1344
+ function colorLines(name, str) {
1345
+ return str.split('\n').map(function(str){
1346
+ return color(name, str);
1347
+ }).join('\n');
1348
+ }
1349
+
1350
+ }); // module: reporters/base.js
1351
+
1352
+ require.register("reporters/doc.js", function(module, exports, require){
1353
+
1354
+ /**
1355
+ * Module dependencies.
1356
+ */
1357
+
1358
+ var Base = require('./base')
1359
+ , utils = require('../utils');
1360
+
1361
+ /**
1362
+ * Expose `Doc`.
1363
+ */
1364
+
1365
+ exports = module.exports = Doc;
1366
+
1367
+ /**
1368
+ * Initialize a new `Doc` reporter.
1369
+ *
1370
+ * @param {Runner} runner
1371
+ * @api public
1372
+ */
1373
+
1374
+ function Doc(runner) {
1375
+ Base.call(this, runner);
1376
+
1377
+ var self = this
1378
+ , stats = this.stats
1379
+ , total = runner.total
1380
+ , indents = 2;
1381
+
1382
+ function indent() {
1383
+ return Array(indents).join(' ');
1384
+ }
1385
+
1386
+ runner.on('suite', function(suite){
1387
+ if (suite.root) return;
1388
+ ++indents;
1389
+ console.log('%s<section class="suite">', indent());
1390
+ ++indents;
1391
+ console.log('%s<h1>%s</h1>', indent(), suite.title);
1392
+ console.log('%s<dl>', indent());
1393
+ });
1394
+
1395
+ runner.on('suite end', function(suite){
1396
+ if (suite.root) return;
1397
+ console.log('%s</dl>', indent());
1398
+ --indents;
1399
+ console.log('%s</section>', indent());
1400
+ --indents;
1401
+ });
1402
+
1403
+ runner.on('pass', function(test){
1404
+ console.log('%s <dt>%s</dt>', indent(), test.title);
1405
+ var code = utils.escape(clean(test.fn.toString()));
1406
+ console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code);
1407
+ });
1408
+ }
1409
+
1410
+ /**
1411
+ * Strip the function definition from `str`,
1412
+ * and re-indent for pre whitespace.
1413
+ */
1414
+
1415
+ function clean(str) {
1416
+ str = str
1417
+ .replace(/^function *\(.*\) *{/, '')
1418
+ .replace(/\s+\}$/, '');
1419
+
1420
+ var spaces = str.match(/^\n?( *)/)[1].length
1421
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
1422
+
1423
+ str = str.replace(re, '');
1424
+
1425
+ return str;
1426
+ }
1427
+ }); // module: reporters/doc.js
1428
+
1429
+ require.register("reporters/dot.js", function(module, exports, require){
1430
+
1431
+ /**
1432
+ * Module dependencies.
1433
+ */
1434
+
1435
+ var Base = require('./base')
1436
+ , color = Base.color;
1437
+
1438
+ /**
1439
+ * Expose `Dot`.
1440
+ */
1441
+
1442
+ exports = module.exports = Dot;
1443
+
1444
+ /**
1445
+ * Initialize a new `Dot` matrix test reporter.
1446
+ *
1447
+ * @param {Runner} runner
1448
+ * @api public
1449
+ */
1450
+
1451
+ function Dot(runner) {
1452
+ Base.call(this, runner);
1453
+
1454
+ var self = this
1455
+ , stats = this.stats
1456
+ , width = Base.window.width * .75 | 0
1457
+ , n = 0;
1458
+
1459
+ runner.on('start', function(){
1460
+ process.stdout.write('\n ');
1461
+ });
1462
+
1463
+ runner.on('pending', function(test){
1464
+ process.stdout.write(color('pending', '.'));
1465
+ });
1466
+
1467
+ runner.on('pass', function(test){
1468
+ if (++n % width == 0) process.stdout.write('\n ');
1469
+ if ('slow' == test.speed) {
1470
+ process.stdout.write(color('bright yellow', '.'));
1471
+ } else {
1472
+ process.stdout.write(color(test.speed, '.'));
1473
+ }
1474
+ });
1475
+
1476
+ runner.on('fail', function(test, err){
1477
+ if (++n % width == 0) process.stdout.write('\n ');
1478
+ process.stdout.write(color('fail', '.'));
1479
+ });
1480
+
1481
+ runner.on('end', function(){
1482
+ console.log();
1483
+ self.epilogue();
1484
+ });
1485
+ }
1486
+
1487
+ /**
1488
+ * Inherit from `Base.prototype`.
1489
+ */
1490
+
1491
+ Dot.prototype = new Base;
1492
+ Dot.prototype.constructor = Dot;
1493
+
1494
+ }); // module: reporters/dot.js
1495
+
1496
+ require.register("reporters/html-cov.js", function(module, exports, require){
1497
+
1498
+ /**
1499
+ * Module dependencies.
1500
+ */
1501
+
1502
+ var JSONCov = require('./json-cov')
1503
+ , fs = require('browser/fs');
1504
+
1505
+ /**
1506
+ * Expose `HTMLCov`.
1507
+ */
1508
+
1509
+ exports = module.exports = HTMLCov;
1510
+
1511
+ /**
1512
+ * Initialize a new `JsCoverage` reporter.
1513
+ *
1514
+ * @param {Runner} runner
1515
+ * @api public
1516
+ */
1517
+
1518
+ function HTMLCov(runner) {
1519
+ var jade = require('jade')
1520
+ , file = __dirname + '/templates/coverage.jade'
1521
+ , str = fs.readFileSync(file, 'utf8')
1522
+ , fn = jade.compile(str, { filename: file })
1523
+ , self = this;
1524
+
1525
+ JSONCov.call(this, runner, false);
1526
+
1527
+ runner.on('end', function(){
1528
+ process.stdout.write(fn({
1529
+ cov: self.cov
1530
+ , coverageClass: coverageClass
1531
+ }));
1532
+ });
1533
+ }
1534
+
1535
+ function coverageClass(n) {
1536
+ if (n >= 75) return 'high';
1537
+ if (n >= 50) return 'medium';
1538
+ if (n >= 25) return 'low';
1539
+ return 'terrible';
1540
+ }
1541
+ }); // module: reporters/html-cov.js
1542
+
1543
+ require.register("reporters/html.js", function(module, exports, require){
1544
+
1545
+ /**
1546
+ * Module dependencies.
1547
+ */
1548
+
1549
+ var Base = require('./base')
1550
+ , utils = require('../utils')
1551
+ , Progress = require('../browser/progress')
1552
+ , escape = utils.escape;
1553
+
1554
+ /**
1555
+ * Expose `Doc`.
1556
+ */
1557
+
1558
+ exports = module.exports = HTML;
1559
+
1560
+ /**
1561
+ * Stats template.
1562
+ */
1563
+
1564
+ var statsTemplate = '<ul id="stats">'
1565
+ + '<li class="progress"><canvas width="40" height="40"></canvas></li>'
1566
+ + '<li class="passes">passes: <em>0</em></li>'
1567
+ + '<li class="failures">failures: <em>0</em></li>'
1568
+ + '<li class="duration">duration: <em>0</em>s</li>'
1569
+ + '</ul>';
1570
+
1571
+ /**
1572
+ * Initialize a new `Doc` reporter.
1573
+ *
1574
+ * @param {Runner} runner
1575
+ * @api public
1576
+ */
1577
+
1578
+ function HTML(runner) {
1579
+ Base.call(this, runner);
1580
+
1581
+ var self = this
1582
+ , stats = this.stats
1583
+ , total = runner.total
1584
+ , root = document.getElementById('mocha')
1585
+ , stat = fragment(statsTemplate)
1586
+ , items = stat.getElementsByTagName('li')
1587
+ , passes = items[1].getElementsByTagName('em')[0]
1588
+ , failures = items[2].getElementsByTagName('em')[0]
1589
+ , duration = items[3].getElementsByTagName('em')[0]
1590
+ , canvas = stat.getElementsByTagName('canvas')[0]
1591
+ , stack = [root]
1592
+ , progress
1593
+ , ctx
1594
+
1595
+ if (canvas.getContext) {
1596
+ ctx = canvas.getContext('2d');
1597
+ progress = new Progress;
1598
+ }
1599
+
1600
+ if (!root) return error('#mocha div missing, add it to your document');
1601
+
1602
+ root.appendChild(stat);
1603
+
1604
+ if (progress) progress.size(40);
1605
+
1606
+ runner.on('suite', function(suite){
1607
+ if (suite.root) return;
1608
+
1609
+ // suite
1610
+ var el = fragment('<div class="suite"><h1>%s</h1></div>', suite.title);
1611
+
1612
+ // container
1613
+ stack[0].appendChild(el);
1614
+ stack.unshift(document.createElement('div'));
1615
+ el.appendChild(stack[0]);
1616
+ });
1617
+
1618
+ runner.on('suite end', function(suite){
1619
+ if (suite.root) return;
1620
+ stack.shift();
1621
+ });
1622
+
1623
+ runner.on('fail', function(test, err){
1624
+ if (err.uncaught) runner.emit('test end', test);
1625
+ });
1626
+
1627
+ runner.on('test end', function(test){
1628
+ // TODO: add to stats
1629
+ var percent = stats.tests / total * 100 | 0;
1630
+ if (progress) progress.update(percent).draw(ctx);
1631
+
1632
+ // update stats
1633
+ var ms = new Date - stats.start;
1634
+ text(passes, stats.passes);
1635
+ text(failures, stats.failures);
1636
+ text(duration, (ms / 1000).toFixed(2));
1637
+
1638
+ // test
1639
+ if ('passed' == test.state) {
1640
+ var el = fragment('<div class="test pass"><h2>%e</h2></div>', test.title);
1641
+ } else if (test.pending) {
1642
+ var el = fragment('<div class="test pass pending"><h2>%e</h2></div>', test.title);
1643
+ } else {
1644
+ var el = fragment('<div class="test fail"><h2>%e</h2></div>', test.title);
1645
+ var str = test.err.stack || test.err.toString();
1646
+
1647
+ // FF / Opera do not add the message
1648
+ if (!~str.indexOf(test.err.message)) {
1649
+ str = test.err.message + '\n' + str;
1650
+ }
1651
+
1652
+ // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
1653
+ // check for the result of the stringifying.
1654
+ if ('[object Error]' == str) str = test.err.message;
1655
+
1656
+ // Safari doesn't give you a stack. Let's at least provide a source line.
1657
+ if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
1658
+ str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
1659
+ }
1660
+
1661
+ el.appendChild(fragment('<pre class="error">%e</pre>', str));
1662
+ }
1663
+
1664
+ // toggle code
1665
+ var h2 = el.getElementsByTagName('h2')[0];
1666
+
1667
+ on(h2, 'click', function(){
1668
+ pre.style.display = 'none' == pre.style.display
1669
+ ? 'block'
1670
+ : 'none';
1671
+ });
1672
+
1673
+ // code
1674
+ // TODO: defer
1675
+ if (!test.pending) {
1676
+ var pre = fragment('<pre><code>%e</code></pre>', clean(test.fn.toString()));
1677
+ el.appendChild(pre);
1678
+ pre.style.display = 'none';
1679
+ }
1680
+
1681
+ stack[0].appendChild(el);
1682
+ });
1683
+ }
1684
+
1685
+ /**
1686
+ * Display error `msg`.
1687
+ */
1688
+
1689
+ function error(msg) {
1690
+ document.body.appendChild(fragment('<div id="error">%s</div>', msg));
1691
+ }
1692
+
1693
+ /**
1694
+ * Return a DOM fragment from `html`.
1695
+ */
1696
+
1697
+ function fragment(html) {
1698
+ var args = arguments
1699
+ , div = document.createElement('div')
1700
+ , i = 1;
1701
+
1702
+ div.innerHTML = html.replace(/%([se])/g, function(_, type){
1703
+ switch (type) {
1704
+ case 's': return String(args[i++]);
1705
+ case 'e': return escape(args[i++]);
1706
+ }
1707
+ });
1708
+
1709
+ return div.firstChild;
1710
+ }
1711
+
1712
+ /**
1713
+ * Set `el` text to `str`.
1714
+ */
1715
+
1716
+ function text(el, str) {
1717
+ if (el.textContent) {
1718
+ el.textContent = str;
1719
+ } else {
1720
+ el.innerText = str;
1721
+ }
1722
+ }
1723
+
1724
+ /**
1725
+ * Listen on `event` with callback `fn`.
1726
+ */
1727
+
1728
+ function on(el, event, fn) {
1729
+ if (el.addEventListener) {
1730
+ el.addEventListener(event, fn, false);
1731
+ } else {
1732
+ el.attachEvent('on' + event, fn);
1733
+ }
1734
+ }
1735
+
1736
+ /**
1737
+ * Strip the function definition from `str`,
1738
+ * and re-indent for pre whitespace.
1739
+ */
1740
+
1741
+ function clean(str) {
1742
+ str = str
1743
+ .replace(/^function *\(.*\) *{/, '')
1744
+ .replace(/\s+\}$/, '');
1745
+
1746
+ var spaces = str.match(/^\n?( *)/)[1].length
1747
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
1748
+
1749
+ str = str
1750
+ .replace(re, '')
1751
+ .replace(/^\s+/, '');
1752
+
1753
+ return str;
1754
+ }
1755
+
1756
+ }); // module: reporters/html.js
1757
+
1758
+ require.register("reporters/index.js", function(module, exports, require){
1759
+
1760
+ exports.Base = require('./base');
1761
+ exports.Dot = require('./dot');
1762
+ exports.Doc = require('./doc');
1763
+ exports.TAP = require('./tap');
1764
+ exports.JSON = require('./json');
1765
+ exports.HTML = require('./html');
1766
+ exports.List = require('./list');
1767
+ exports.Min = require('./min');
1768
+ exports.Spec = require('./spec');
1769
+ exports.Progress = require('./progress');
1770
+ exports.Landing = require('./landing');
1771
+ exports.JSONCov = require('./json-cov');
1772
+ exports.HTMLCov = require('./html-cov');
1773
+ exports.JSONStream = require('./json-stream');
1774
+ exports.XUnit = require('./xunit')
1775
+ exports.Teamcity = require('./teamcity')
1776
+
1777
+ }); // module: reporters/index.js
1778
+
1779
+ require.register("reporters/json-cov.js", function(module, exports, require){
1780
+
1781
+ /**
1782
+ * Module dependencies.
1783
+ */
1784
+
1785
+ var Base = require('./base');
1786
+
1787
+ /**
1788
+ * Expose `JSONCov`.
1789
+ */
1790
+
1791
+ exports = module.exports = JSONCov;
1792
+
1793
+ /**
1794
+ * Initialize a new `JsCoverage` reporter.
1795
+ *
1796
+ * @param {Runner} runner
1797
+ * @param {Boolean} output
1798
+ * @api public
1799
+ */
1800
+
1801
+ function JSONCov(runner, output) {
1802
+ var self = this
1803
+ , output = 1 == arguments.length ? true : output;
1804
+
1805
+ Base.call(this, runner);
1806
+
1807
+ var tests = []
1808
+ , failures = []
1809
+ , passes = [];
1810
+
1811
+ runner.on('test end', function(test){
1812
+ tests.push(test);
1813
+ });
1814
+
1815
+ runner.on('pass', function(test){
1816
+ passes.push(test);
1817
+ });
1818
+
1819
+ runner.on('fail', function(test){
1820
+ failures.push(test);
1821
+ });
1822
+
1823
+ runner.on('end', function(){
1824
+ var cov = global._$jscoverage || {};
1825
+ var result = self.cov = map(cov);
1826
+ result.stats = self.stats;
1827
+ result.tests = tests.map(clean);
1828
+ result.failures = failures.map(clean);
1829
+ result.passes = passes.map(clean);
1830
+ if (!output) return;
1831
+ process.stdout.write(JSON.stringify(result, null, 2 ));
1832
+ });
1833
+ }
1834
+
1835
+ /**
1836
+ * Map jscoverage data to a JSON structure
1837
+ * suitable for reporting.
1838
+ *
1839
+ * @param {Object} cov
1840
+ * @return {Object}
1841
+ * @api private
1842
+ */
1843
+
1844
+ function map(cov) {
1845
+ var ret = {
1846
+ instrumentation: 'node-jscoverage'
1847
+ , sloc: 0
1848
+ , hits: 0
1849
+ , misses: 0
1850
+ , coverage: 0
1851
+ , files: []
1852
+ };
1853
+
1854
+ for (var filename in cov) {
1855
+ var data = coverage(filename, cov[filename]);
1856
+ ret.files.push(data);
1857
+ ret.hits += data.hits;
1858
+ ret.misses += data.misses;
1859
+ ret.sloc += data.sloc;
1860
+ }
1861
+
1862
+ if (ret.sloc > 0) {
1863
+ ret.coverage = (ret.hits / ret.sloc) * 100;
1864
+ }
1865
+
1866
+ return ret;
1867
+ };
1868
+
1869
+ /**
1870
+ * Map jscoverage data for a single source file
1871
+ * to a JSON structure suitable for reporting.
1872
+ *
1873
+ * @param {String} filename name of the source file
1874
+ * @param {Object} data jscoverage coverage data
1875
+ * @return {Object}
1876
+ * @api private
1877
+ */
1878
+
1879
+ function coverage(filename, data) {
1880
+ var ret = {
1881
+ filename: filename,
1882
+ coverage: 0,
1883
+ hits: 0,
1884
+ misses: 0,
1885
+ sloc: 0,
1886
+ source: {}
1887
+ };
1888
+
1889
+ data.source.forEach(function(line, num){
1890
+ num++;
1891
+
1892
+ if (data[num] === 0) {
1893
+ ret.misses++;
1894
+ ret.sloc++;
1895
+ } else if (data[num] !== undefined) {
1896
+ ret.hits++;
1897
+ ret.sloc++;
1898
+ }
1899
+
1900
+ ret.source[num] = {
1901
+ source: line
1902
+ , coverage: data[num] === undefined
1903
+ ? ''
1904
+ : data[num]
1905
+ };
1906
+ });
1907
+
1908
+ ret.coverage = ret.hits / ret.sloc * 100;
1909
+
1910
+ return ret;
1911
+ }
1912
+
1913
+ /**
1914
+ * Return a plain-object representation of `test`
1915
+ * free of cyclic properties etc.
1916
+ *
1917
+ * @param {Object} test
1918
+ * @return {Object}
1919
+ * @api private
1920
+ */
1921
+
1922
+ function clean(test) {
1923
+ return {
1924
+ title: test.title
1925
+ , fullTitle: test.fullTitle()
1926
+ , duration: test.duration
1927
+ }
1928
+ }
1929
+
1930
+ }); // module: reporters/json-cov.js
1931
+
1932
+ require.register("reporters/json-stream.js", function(module, exports, require){
1933
+
1934
+ /**
1935
+ * Module dependencies.
1936
+ */
1937
+
1938
+ var Base = require('./base')
1939
+ , color = Base.color;
1940
+
1941
+ /**
1942
+ * Expose `List`.
1943
+ */
1944
+
1945
+ exports = module.exports = List;
1946
+
1947
+ /**
1948
+ * Initialize a new `List` test reporter.
1949
+ *
1950
+ * @param {Runner} runner
1951
+ * @api public
1952
+ */
1953
+
1954
+ function List(runner) {
1955
+ Base.call(this, runner);
1956
+
1957
+ var self = this
1958
+ , stats = this.stats
1959
+ , total = runner.total;
1960
+
1961
+ runner.on('start', function(){
1962
+ console.log(JSON.stringify(['start', { total: total }]));
1963
+ });
1964
+
1965
+ runner.on('pass', function(test){
1966
+ console.log(JSON.stringify(['pass', clean(test)]));
1967
+ });
1968
+
1969
+ runner.on('fail', function(test, err){
1970
+ console.log(JSON.stringify(['fail', clean(test)]));
1971
+ });
1972
+
1973
+ runner.on('end', function(){
1974
+ process.stdout.write(JSON.stringify(['end', self.stats]));
1975
+ });
1976
+ }
1977
+
1978
+ /**
1979
+ * Return a plain-object representation of `test`
1980
+ * free of cyclic properties etc.
1981
+ *
1982
+ * @param {Object} test
1983
+ * @return {Object}
1984
+ * @api private
1985
+ */
1986
+
1987
+ function clean(test) {
1988
+ return {
1989
+ title: test.title
1990
+ , fullTitle: test.fullTitle()
1991
+ , duration: test.duration
1992
+ }
1993
+ }
1994
+ }); // module: reporters/json-stream.js
1995
+
1996
+ require.register("reporters/json.js", function(module, exports, require){
1997
+
1998
+ /**
1999
+ * Module dependencies.
2000
+ */
2001
+
2002
+ var Base = require('./base')
2003
+ , cursor = Base.cursor
2004
+ , color = Base.color;
2005
+
2006
+ /**
2007
+ * Expose `JSON`.
2008
+ */
2009
+
2010
+ exports = module.exports = JSONReporter;
2011
+
2012
+ /**
2013
+ * Initialize a new `JSON` reporter.
2014
+ *
2015
+ * @param {Runner} runner
2016
+ * @api public
2017
+ */
2018
+
2019
+ function JSONReporter(runner) {
2020
+ var self = this;
2021
+ Base.call(this, runner);
2022
+
2023
+ var tests = []
2024
+ , failures = []
2025
+ , passes = [];
2026
+
2027
+ runner.on('test end', function(test){
2028
+ tests.push(test);
2029
+ });
2030
+
2031
+ runner.on('pass', function(test){
2032
+ passes.push(test);
2033
+ });
2034
+
2035
+ runner.on('fail', function(test){
2036
+ failures.push(test);
2037
+ });
2038
+
2039
+ runner.on('end', function(){
2040
+ var obj = {
2041
+ stats: self.stats
2042
+ , tests: tests.map(clean)
2043
+ , failures: failures.map(clean)
2044
+ , passes: passes.map(clean)
2045
+ };
2046
+
2047
+ process.stdout.write(JSON.stringify(obj, null, 2));
2048
+ });
2049
+ }
2050
+
2051
+ /**
2052
+ * Return a plain-object representation of `test`
2053
+ * free of cyclic properties etc.
2054
+ *
2055
+ * @param {Object} test
2056
+ * @return {Object}
2057
+ * @api private
2058
+ */
2059
+
2060
+ function clean(test) {
2061
+ return {
2062
+ title: test.title
2063
+ , fullTitle: test.fullTitle()
2064
+ , duration: test.duration
2065
+ }
2066
+ }
2067
+ }); // module: reporters/json.js
2068
+
2069
+ require.register("reporters/landing.js", function(module, exports, require){
2070
+
2071
+ /**
2072
+ * Module dependencies.
2073
+ */
2074
+
2075
+ var Base = require('./base')
2076
+ , cursor = Base.cursor
2077
+ , color = Base.color;
2078
+
2079
+ /**
2080
+ * Expose `Landing`.
2081
+ */
2082
+
2083
+ exports = module.exports = Landing;
2084
+
2085
+ /**
2086
+ * Airplane color.
2087
+ */
2088
+
2089
+ Base.colors.plane = 0;
2090
+
2091
+ /**
2092
+ * Airplane crash color.
2093
+ */
2094
+
2095
+ Base.colors['plane crash'] = 31;
2096
+
2097
+ /**
2098
+ * Runway color.
2099
+ */
2100
+
2101
+ Base.colors.runway = 90;
2102
+
2103
+ /**
2104
+ * Initialize a new `Landing` reporter.
2105
+ *
2106
+ * @param {Runner} runner
2107
+ * @api public
2108
+ */
2109
+
2110
+ function Landing(runner) {
2111
+ Base.call(this, runner);
2112
+
2113
+ var self = this
2114
+ , stats = this.stats
2115
+ , width = Base.window.width * .75 | 0
2116
+ , total = runner.total
2117
+ , stream = process.stdout
2118
+ , plane = color('plane', '✈')
2119
+ , crashed = -1
2120
+ , n = 0;
2121
+
2122
+ function runway() {
2123
+ var buf = Array(width).join('-');
2124
+ return ' ' + color('runway', buf);
2125
+ }
2126
+
2127
+ runner.on('start', function(){
2128
+ stream.write('\n ');
2129
+ cursor.hide();
2130
+ });
2131
+
2132
+ runner.on('test end', function(test){
2133
+ // check if the plane crashed
2134
+ var col = -1 == crashed
2135
+ ? width * ++n / total | 0
2136
+ : crashed;
2137
+
2138
+ // show the crash
2139
+ if ('failed' == test.state) {
2140
+ plane = color('plane crash', '✈');
2141
+ crashed = col;
2142
+ }
2143
+
2144
+ // render landing strip
2145
+ stream.write('\033[4F\n\n');
2146
+ stream.write(runway());
2147
+ stream.write('\n ');
2148
+ stream.write(color('runway', Array(col).join('⋅')));
2149
+ stream.write(plane)
2150
+ stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
2151
+ stream.write(runway());
2152
+ stream.write('\033[0m');
2153
+ });
2154
+
2155
+ runner.on('end', function(){
2156
+ cursor.show();
2157
+ console.log();
2158
+ self.epilogue();
2159
+ });
2160
+ }
2161
+
2162
+ /**
2163
+ * Inherit from `Base.prototype`.
2164
+ */
2165
+
2166
+ Landing.prototype = new Base;
2167
+ Landing.prototype.constructor = Landing;
2168
+
2169
+ }); // module: reporters/landing.js
2170
+
2171
+ require.register("reporters/list.js", function(module, exports, require){
2172
+
2173
+ /**
2174
+ * Module dependencies.
2175
+ */
2176
+
2177
+ var Base = require('./base')
2178
+ , cursor = Base.cursor
2179
+ , color = Base.color;
2180
+
2181
+ /**
2182
+ * Expose `List`.
2183
+ */
2184
+
2185
+ exports = module.exports = List;
2186
+
2187
+ /**
2188
+ * Initialize a new `List` test reporter.
2189
+ *
2190
+ * @param {Runner} runner
2191
+ * @api public
2192
+ */
2193
+
2194
+ function List(runner) {
2195
+ Base.call(this, runner);
2196
+
2197
+ var self = this
2198
+ , stats = this.stats
2199
+ , n = 0;
2200
+
2201
+ runner.on('start', function(){
2202
+ console.log();
2203
+ });
2204
+
2205
+ runner.on('test', function(test){
2206
+ process.stdout.write(color('pass', ' ' + test.fullTitle() + ': '));
2207
+ });
2208
+
2209
+ runner.on('pending', function(test){
2210
+ var fmt = color('checkmark', ' -')
2211
+ + color('pending', ' %s');
2212
+ console.log(fmt, test.fullTitle());
2213
+ });
2214
+
2215
+ runner.on('pass', function(test){
2216
+ var fmt = color('checkmark', ' ✓')
2217
+ + color('pass', ' %s: ')
2218
+ + color(test.speed, '%dms');
2219
+ cursor.CR();
2220
+ console.log(fmt, test.fullTitle(), test.duration);
2221
+ });
2222
+
2223
+ runner.on('fail', function(test, err){
2224
+ cursor.CR();
2225
+ console.log(color('fail', ' %d) %s'), ++n, test.fullTitle());
2226
+ });
2227
+
2228
+ runner.on('end', self.epilogue.bind(self));
2229
+ }
2230
+
2231
+ /**
2232
+ * Inherit from `Base.prototype`.
2233
+ */
2234
+
2235
+ List.prototype = new Base;
2236
+ List.prototype.constructor = List;
2237
+
2238
+
2239
+ }); // module: reporters/list.js
2240
+
2241
+ require.register("reporters/markdown.js", function(module, exports, require){
2242
+
2243
+ /**
2244
+ * Module dependencies.
2245
+ */
2246
+
2247
+ var Base = require('./base')
2248
+ , utils = require('../utils');
2249
+
2250
+ /**
2251
+ * Expose `Markdown`.
2252
+ */
2253
+
2254
+ exports = module.exports = Markdown;
2255
+
2256
+ /**
2257
+ * Initialize a new `Markdown` reporter.
2258
+ *
2259
+ * @param {Runner} runner
2260
+ * @api public
2261
+ */
2262
+
2263
+ function Markdown(runner) {
2264
+ Base.call(this, runner);
2265
+
2266
+ var self = this
2267
+ , stats = this.stats
2268
+ , total = runner.total
2269
+ , level = 0
2270
+ , buf = '';
2271
+
2272
+ function title(str) {
2273
+ return Array(level).join('#') + ' ' + str;
2274
+ }
2275
+
2276
+ function indent() {
2277
+ return Array(level).join(' ');
2278
+ }
2279
+
2280
+ function mapTOC(suite, obj) {
2281
+ var ret = obj;
2282
+ obj = obj[suite.title] = obj[suite.title] || { suite: suite };
2283
+ suite.suites.forEach(function(suite){
2284
+ mapTOC(suite, obj);
2285
+ });
2286
+ return ret;
2287
+ }
2288
+
2289
+ function stringifyTOC(obj, level) {
2290
+ ++level;
2291
+ var buf = '';
2292
+ var link;
2293
+ for (var key in obj) {
2294
+ if ('suite' == key) continue;
2295
+ if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
2296
+ if (key) buf += Array(level).join(' ') + link;
2297
+ buf += stringifyTOC(obj[key], level);
2298
+ }
2299
+ --level;
2300
+ return buf;
2301
+ }
2302
+
2303
+ function generateTOC(suite) {
2304
+ var obj = mapTOC(suite, {});
2305
+ return stringifyTOC(obj, 0);
2306
+ }
2307
+
2308
+ generateTOC(runner.suite);
2309
+
2310
+ runner.on('suite', function(suite){
2311
+ ++level;
2312
+ var slug = utils.slug(suite.fullTitle());
2313
+ buf += '<a name="' + slug + '" />' + '\n';
2314
+ buf += title(suite.title) + '\n';
2315
+ });
2316
+
2317
+ runner.on('suite end', function(suite){
2318
+ --level;
2319
+ });
2320
+
2321
+ runner.on('pass', function(test){
2322
+ var code = clean(test.fn.toString());
2323
+ buf += test.title + '.\n';
2324
+ buf += '\n```js';
2325
+ buf += code + '\n';
2326
+ buf += '```\n\n';
2327
+ });
2328
+
2329
+ runner.on('end', function(){
2330
+ process.stdout.write('# TOC\n');
2331
+ process.stdout.write(generateTOC(runner.suite));
2332
+ process.stdout.write(buf);
2333
+ });
2334
+ }
2335
+
2336
+ /**
2337
+ * Strip the function definition from `str`,
2338
+ * and re-indent for pre whitespace.
2339
+ */
2340
+
2341
+ function clean(str) {
2342
+ str = str
2343
+ .replace(/^function *\(.*\) *{/, '')
2344
+ .replace(/\s+\}$/, '');
2345
+
2346
+ var spaces = str.match(/^\n?( *)/)[1].length
2347
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
2348
+
2349
+ str = str.replace(re, '');
2350
+
2351
+ return str;
2352
+ }
2353
+ }); // module: reporters/markdown.js
2354
+
2355
+ require.register("reporters/min.js", function(module, exports, require){
2356
+ /**
2357
+ * Module dependencies.
2358
+ */
2359
+
2360
+ var Base = require('./base');
2361
+
2362
+ /**
2363
+ * Expose `Min`.
2364
+ */
2365
+
2366
+ exports = module.exports = Min;
2367
+
2368
+ /**
2369
+ * Initialize a new `Min` minimal test reporter (best used with --watch).
2370
+ *
2371
+ * @param {Runner} runner
2372
+ * @api public
2373
+ */
2374
+
2375
+ function Min(runner) {
2376
+ Base.call(this, runner);
2377
+
2378
+ runner.on('start', function(){
2379
+ // clear screen
2380
+ process.stdout.write('\033[2J');
2381
+ // set cursor position
2382
+ process.stdout.write('\033[1;3H');
2383
+ });
2384
+
2385
+ runner.on('end', this.epilogue.bind(this));
2386
+ }
2387
+
2388
+ /**
2389
+ * Inherit from `Base.prototype`.
2390
+ */
2391
+
2392
+ Min.prototype = new Base;
2393
+ Min.prototype.constructor = Min;
2394
+
2395
+ }); // module: reporters/min.js
2396
+
2397
+ require.register("reporters/progress.js", function(module, exports, require){
2398
+
2399
+ /**
2400
+ * Module dependencies.
2401
+ */
2402
+
2403
+ var Base = require('./base')
2404
+ , cursor = Base.cursor
2405
+ , color = Base.color;
2406
+
2407
+ /**
2408
+ * Expose `Progress`.
2409
+ */
2410
+
2411
+ exports = module.exports = Progress;
2412
+
2413
+ /**
2414
+ * General progress bar color.
2415
+ */
2416
+
2417
+ Base.colors.progress = 90;
2418
+
2419
+ /**
2420
+ * Initialize a new `Progress` bar test reporter.
2421
+ *
2422
+ * @param {Runner} runner
2423
+ * @param {Object} options
2424
+ * @api public
2425
+ */
2426
+
2427
+ function Progress(runner, options) {
2428
+ Base.call(this, runner);
2429
+
2430
+ var self = this
2431
+ , options = options || {}
2432
+ , stats = this.stats
2433
+ , width = Base.window.width * .50 | 0
2434
+ , total = runner.total
2435
+ , complete = 0
2436
+ , max = Math.max;
2437
+
2438
+ // default chars
2439
+ options.open = options.open || '[';
2440
+ options.complete = options.complete || '▬';
2441
+ options.incomplete = options.incomplete || '⋅';
2442
+ options.close = options.close || ']';
2443
+ options.verbose = false;
2444
+
2445
+ // tests started
2446
+ runner.on('start', function(){
2447
+ console.log();
2448
+ cursor.hide();
2449
+ });
2450
+
2451
+ // tests complete
2452
+ runner.on('test end', function(){
2453
+ var incomplete = total - complete
2454
+ , percent = complete++ / total
2455
+ , n = width * percent | 0
2456
+ , i = width - n;
2457
+
2458
+ cursor.CR();
2459
+ process.stdout.write('\033[J');
2460
+ process.stdout.write(color('progress', ' ' + options.open));
2461
+ process.stdout.write(Array(n).join(options.complete));
2462
+ process.stdout.write(Array(i).join(options.incomplete));
2463
+ process.stdout.write(color('progress', options.close));
2464
+ if (options.verbose) {
2465
+ process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
2466
+ }
2467
+ });
2468
+
2469
+ // tests are complete, output some stats
2470
+ // and the failures if any
2471
+ runner.on('end', function(){
2472
+ cursor.show();
2473
+ console.log();
2474
+ self.epilogue();
2475
+ });
2476
+ }
2477
+
2478
+ /**
2479
+ * Inherit from `Base.prototype`.
2480
+ */
2481
+
2482
+ Progress.prototype = new Base;
2483
+ Progress.prototype.constructor = Progress;
2484
+
2485
+
2486
+ }); // module: reporters/progress.js
2487
+
2488
+ require.register("reporters/spec.js", function(module, exports, require){
2489
+
2490
+ /**
2491
+ * Module dependencies.
2492
+ */
2493
+
2494
+ var Base = require('./base')
2495
+ , cursor = Base.cursor
2496
+ , color = Base.color;
2497
+
2498
+ /**
2499
+ * Expose `Spec`.
2500
+ */
2501
+
2502
+ exports = module.exports = Spec;
2503
+
2504
+ /**
2505
+ * Initialize a new `Spec` test reporter.
2506
+ *
2507
+ * @param {Runner} runner
2508
+ * @api public
2509
+ */
2510
+
2511
+ function Spec(runner) {
2512
+ Base.call(this, runner);
2513
+
2514
+ var self = this
2515
+ , stats = this.stats
2516
+ , indents = 0
2517
+ , n = 0;
2518
+
2519
+ function indent() {
2520
+ return Array(indents).join(' ')
2521
+ }
2522
+
2523
+ runner.on('start', function(){
2524
+ console.log();
2525
+ });
2526
+
2527
+ runner.on('suite', function(suite){
2528
+ ++indents;
2529
+ console.log(color('suite', '%s%s'), indent(), suite.title);
2530
+ });
2531
+
2532
+ runner.on('suite end', function(suite){
2533
+ --indents;
2534
+ if (1 == indents) console.log();
2535
+ });
2536
+
2537
+ runner.on('test', function(test){
2538
+ process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': '));
2539
+ });
2540
+
2541
+ runner.on('pending', function(test){
2542
+ var fmt = indent() + color('pending', ' - %s');
2543
+ console.log(fmt, test.title);
2544
+ });
2545
+
2546
+ runner.on('pass', function(test){
2547
+ if ('fast' == test.speed) {
2548
+ var fmt = indent()
2549
+ + color('checkmark', ' ✓')
2550
+ + color('pass', ' %s ');
2551
+ cursor.CR();
2552
+ console.log(fmt, test.title);
2553
+ } else {
2554
+ var fmt = indent()
2555
+ + color('checkmark', ' ✓')
2556
+ + color('pass', ' %s ')
2557
+ + color(test.speed, '(%dms)');
2558
+ cursor.CR();
2559
+ console.log(fmt, test.title, test.duration);
2560
+ }
2561
+ });
2562
+
2563
+ runner.on('fail', function(test, err){
2564
+ cursor.CR();
2565
+ console.log(indent() + color('fail', ' %d) %s'), ++n, test.title);
2566
+ });
2567
+
2568
+ runner.on('end', self.epilogue.bind(self));
2569
+ }
2570
+
2571
+ /**
2572
+ * Inherit from `Base.prototype`.
2573
+ */
2574
+
2575
+ Spec.prototype = new Base;
2576
+ Spec.prototype.constructor = Spec;
2577
+
2578
+
2579
+ }); // module: reporters/spec.js
2580
+
2581
+ require.register("reporters/tap.js", function(module, exports, require){
2582
+
2583
+ /**
2584
+ * Module dependencies.
2585
+ */
2586
+
2587
+ var Base = require('./base')
2588
+ , cursor = Base.cursor
2589
+ , color = Base.color;
2590
+
2591
+ /**
2592
+ * Expose `TAP`.
2593
+ */
2594
+
2595
+ exports = module.exports = TAP;
2596
+
2597
+ /**
2598
+ * Initialize a new `TAP` reporter.
2599
+ *
2600
+ * @param {Runner} runner
2601
+ * @api public
2602
+ */
2603
+
2604
+ function TAP(runner) {
2605
+ Base.call(this, runner);
2606
+
2607
+ var self = this
2608
+ , stats = this.stats
2609
+ , total = runner.total
2610
+ , n = 1;
2611
+
2612
+ runner.on('start', function(){
2613
+ console.log('%d..%d', 1, total);
2614
+ });
2615
+
2616
+ runner.on('test end', function(){
2617
+ ++n;
2618
+ });
2619
+
2620
+ runner.on('pending', function(test){
2621
+ console.log('ok %d %s # SKIP -', n, title(test));
2622
+ });
2623
+
2624
+ runner.on('pass', function(test){
2625
+ console.log('ok %d %s', n, title(test));
2626
+ });
2627
+
2628
+ runner.on('fail', function(test, err){
2629
+ console.log('not ok %d %s', n, title(test));
2630
+ console.log(err.stack.replace(/^/gm, ' '));
2631
+ });
2632
+ }
2633
+
2634
+ /**
2635
+ * Return a TAP-safe title of `test`
2636
+ *
2637
+ * @param {Object} test
2638
+ * @return {String}
2639
+ * @api private
2640
+ */
2641
+
2642
+ function title(test) {
2643
+ return test.fullTitle().replace(/#/g, '');
2644
+ }
2645
+
2646
+ }); // module: reporters/tap.js
2647
+
2648
+ require.register("reporters/teamcity.js", function(module, exports, require){
2649
+
2650
+ /**
2651
+ * Module dependencies.
2652
+ */
2653
+
2654
+ var Base = require('./base');
2655
+
2656
+ /**
2657
+ * Expose `Teamcity`.
2658
+ */
2659
+
2660
+ exports = module.exports = Teamcity;
2661
+
2662
+ /**
2663
+ * Initialize a new `Teamcity` reporter.
2664
+ *
2665
+ * @param {Runner} runner
2666
+ * @api public
2667
+ */
2668
+
2669
+ function Teamcity(runner) {
2670
+ Base.call(this, runner);
2671
+ var stats = this.stats;
2672
+
2673
+ runner.on('start', function() {
2674
+ console.log("##teamcity[testSuiteStarted name='mocha.suite']");
2675
+ });
2676
+
2677
+ runner.on('test', function(test) {
2678
+ console.log("##teamcity[testStarted name='%s']", escape(test.fullTitle()));
2679
+ });
2680
+
2681
+ runner.on('fail', function(test, err) {
2682
+ console.log("##teamcity[testFailed name='%s' message='%s']", escape(test.fullTitle()), escape(err.message));
2683
+ });
2684
+
2685
+ runner.on('pending', function(test) {
2686
+ console.log("##teamcity[testIgnored name='%s' message='pending']", escape(test.fullTitle()));
2687
+ });
2688
+
2689
+ runner.on('test end', function(test) {
2690
+ console.log("##teamcity[testFinished name='%s' duration='%s']", escape(test.fullTitle()), test.duration);
2691
+ });
2692
+
2693
+ runner.on('end', function() {
2694
+ console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='%s']", stats.duration);
2695
+ });
2696
+ }
2697
+
2698
+ /**
2699
+ * Escape the given `str`.
2700
+ */
2701
+
2702
+ function escape(str) {
2703
+ return str.replace(/'/g, "|'");
2704
+ }
2705
+ }); // module: reporters/teamcity.js
2706
+
2707
+ require.register("reporters/xunit.js", function(module, exports, require){
2708
+
2709
+ /**
2710
+ * Module dependencies.
2711
+ */
2712
+
2713
+ var Base = require('./base')
2714
+ , utils = require('../utils')
2715
+ , escape = utils.escape;
2716
+
2717
+ /**
2718
+ * Expose `XUnit`.
2719
+ */
2720
+
2721
+ exports = module.exports = XUnit;
2722
+
2723
+ /**
2724
+ * Initialize a new `XUnit` reporter.
2725
+ *
2726
+ * @param {Runner} runner
2727
+ * @api public
2728
+ */
2729
+
2730
+ function XUnit(runner) {
2731
+ Base.call(this, runner);
2732
+ var stats = this.stats
2733
+ , tests = []
2734
+ , self = this;
2735
+
2736
+ runner.on('test end', function(test){
2737
+ tests.push(test);
2738
+ });
2739
+
2740
+ runner.on('end', function(){
2741
+ console.log(tag('testsuite', {
2742
+ name: 'Mocha Tests'
2743
+ , tests: stats.tests
2744
+ , failures: stats.failures
2745
+ , errors: stats.failures
2746
+ , skip: stats.tests - stats.failures - stats.passes
2747
+ , timestamp: (new Date).toUTCString()
2748
+ , time: stats.duration / 1000
2749
+ }, false));
2750
+
2751
+ tests.forEach(test);
2752
+ console.log('</testsuite>');
2753
+ });
2754
+ }
2755
+
2756
+ /**
2757
+ * Inherit from `Base.prototype`.
2758
+ */
2759
+
2760
+ XUnit.prototype = new Base;
2761
+ XUnit.prototype.constructor = XUnit;
2762
+
2763
+
2764
+ /**
2765
+ * Output tag for the given `test.`
2766
+ */
2767
+
2768
+ function test(test) {
2769
+ var attrs = {
2770
+ classname: test.parent.fullTitle()
2771
+ , name: test.title
2772
+ , time: test.duration / 1000
2773
+ };
2774
+
2775
+ if ('failed' == test.state) {
2776
+ var err = test.err;
2777
+ attrs.message = escape(err.message);
2778
+ console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
2779
+ } else if (test.pending) {
2780
+ console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
2781
+ } else {
2782
+ console.log(tag('testcase', attrs, true) );
2783
+ }
2784
+ }
2785
+
2786
+ /**
2787
+ * HTML tag helper.
2788
+ */
2789
+
2790
+ function tag(name, attrs, close, content) {
2791
+ var end = close ? '/>' : '>'
2792
+ , pairs = []
2793
+ , tag;
2794
+
2795
+ for (var key in attrs) {
2796
+ pairs.push(key + '="' + escape(attrs[key]) + '"');
2797
+ }
2798
+
2799
+ tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
2800
+ if (content) tag += content + '</' + name + end;
2801
+ return tag;
2802
+ }
2803
+
2804
+ /**
2805
+ * Return cdata escaped CDATA `str`.
2806
+ */
2807
+
2808
+ function cdata(str) {
2809
+ return '<![CDATA[' + escape(str) + ']]>';
2810
+ }
2811
+
2812
+ }); // module: reporters/xunit.js
2813
+
2814
+ require.register("runnable.js", function(module, exports, require){
2815
+
2816
+ /**
2817
+ * Module dependencies.
2818
+ */
2819
+
2820
+ var EventEmitter = require('browser/events').EventEmitter
2821
+ , debug = require('browser/debug')('runnable');
2822
+
2823
+ /**
2824
+ * Expose `Runnable`.
2825
+ */
2826
+
2827
+ module.exports = Runnable;
2828
+
2829
+ /**
2830
+ * Initialize a new `Runnable` with the given `title` and callback `fn`.
2831
+ *
2832
+ * @param {String} title
2833
+ * @param {Function} fn
2834
+ * @api private
2835
+ */
2836
+
2837
+ function Runnable(title, fn) {
2838
+ this.title = title;
2839
+ this.fn = fn;
2840
+ this.async = fn && fn.length;
2841
+ this.sync = ! this.async;
2842
+ this._timeout = 2000;
2843
+ this.timedOut = false;
2844
+ }
2845
+
2846
+ /**
2847
+ * Inherit from `EventEmitter.prototype`.
2848
+ */
2849
+
2850
+ Runnable.prototype = new EventEmitter;
2851
+ Runnable.prototype.constructor = Runnable;
2852
+
2853
+
2854
+ /**
2855
+ * Set & get timeout `ms`.
2856
+ *
2857
+ * @param {Number} ms
2858
+ * @return {Runnable|Number} ms or self
2859
+ * @api private
2860
+ */
2861
+
2862
+ Runnable.prototype.timeout = function(ms){
2863
+ if (0 == arguments.length) return this._timeout;
2864
+ debug('timeout %d', ms);
2865
+ this._timeout = ms;
2866
+ if (this.timer) this.resetTimeout();
2867
+ return this;
2868
+ };
2869
+
2870
+ /**
2871
+ * Return the full title generated by recursively
2872
+ * concatenating the parent's full title.
2873
+ *
2874
+ * @return {String}
2875
+ * @api public
2876
+ */
2877
+
2878
+ Runnable.prototype.fullTitle = function(){
2879
+ return this.parent.fullTitle() + ' ' + this.title;
2880
+ };
2881
+
2882
+ /**
2883
+ * Clear the timeout.
2884
+ *
2885
+ * @api private
2886
+ */
2887
+
2888
+ Runnable.prototype.clearTimeout = function(){
2889
+ clearTimeout(this.timer);
2890
+ };
2891
+
2892
+ /**
2893
+ * Reset the timeout.
2894
+ *
2895
+ * @api private
2896
+ */
2897
+
2898
+ Runnable.prototype.resetTimeout = function(){
2899
+ var self = this
2900
+ , ms = this.timeout();
2901
+
2902
+ this.clearTimeout();
2903
+ if (ms) {
2904
+ this.timer = setTimeout(function(){
2905
+ self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
2906
+ self.timedOut = true;
2907
+ }, ms);
2908
+ }
2909
+ };
2910
+
2911
+ /**
2912
+ * Run the test and invoke `fn(err)`.
2913
+ *
2914
+ * @param {Function} fn
2915
+ * @api private
2916
+ */
2917
+
2918
+ Runnable.prototype.run = function(fn){
2919
+ var self = this
2920
+ , ms = this.timeout()
2921
+ , start = new Date
2922
+ , ctx = this.ctx
2923
+ , finished
2924
+ , emitted;
2925
+
2926
+ // timeout
2927
+ if (this.async) {
2928
+ if (ms) {
2929
+ this.timer = setTimeout(function(){
2930
+ done(new Error('timeout of ' + ms + 'ms exceeded'));
2931
+ self.timedOut = true;
2932
+ }, ms);
2933
+ }
2934
+ }
2935
+
2936
+ // called multiple times
2937
+ function multiple() {
2938
+ if (emitted) return;
2939
+ emitted = true;
2940
+ self.emit('error', new Error('done() called multiple times'));
2941
+ }
2942
+
2943
+ // finished
2944
+ function done(err) {
2945
+ if (self.timedOut) return;
2946
+ if (finished) return multiple();
2947
+ self.clearTimeout();
2948
+ self.duration = new Date - start;
2949
+ finished = true;
2950
+ fn(err);
2951
+ }
2952
+
2953
+ // for .resetTimeout()
2954
+ this.callback = done;
2955
+
2956
+ // async
2957
+ if (this.async) {
2958
+ try {
2959
+ this.fn.call(ctx, function(err){
2960
+ if (err instanceof Error) return done(err);
2961
+ if (null != err) return done(new Error('done() invoked with non-Error: ' + err));
2962
+ done();
2963
+ });
2964
+ } catch (err) {
2965
+ done(err);
2966
+ }
2967
+ return;
2968
+ }
2969
+
2970
+ // sync
2971
+ try {
2972
+ if (!this.pending) this.fn.call(ctx);
2973
+ this.duration = new Date - start;
2974
+ fn();
2975
+ } catch (err) {
2976
+ fn(err);
2977
+ }
2978
+ };
2979
+
2980
+ }); // module: runnable.js
2981
+
2982
+ require.register("runner.js", function(module, exports, require){
2983
+
2984
+ /**
2985
+ * Module dependencies.
2986
+ */
2987
+
2988
+ var EventEmitter = require('browser/events').EventEmitter
2989
+ , debug = require('browser/debug')('runner')
2990
+ , Test = require('./test')
2991
+ , utils = require('./utils')
2992
+ , noop = function(){};
2993
+
2994
+ /**
2995
+ * Expose `Runner`.
2996
+ */
2997
+
2998
+ module.exports = Runner;
2999
+
3000
+ /**
3001
+ * Initialize a `Runner` for the given `suite`.
3002
+ *
3003
+ * Events:
3004
+ *
3005
+ * - `start` execution started
3006
+ * - `end` execution complete
3007
+ * - `suite` (suite) test suite execution started
3008
+ * - `suite end` (suite) all tests (and sub-suites) have finished
3009
+ * - `test` (test) test execution started
3010
+ * - `test end` (test) test completed
3011
+ * - `hook` (hook) hook execution started
3012
+ * - `hook end` (hook) hook complete
3013
+ * - `pass` (test) test passed
3014
+ * - `fail` (test, err) test failed
3015
+ *
3016
+ * @api public
3017
+ */
3018
+
3019
+ function Runner(suite) {
3020
+ var self = this;
3021
+ this._globals = [];
3022
+ this.suite = suite;
3023
+ this.total = suite.total();
3024
+ this.failures = 0;
3025
+ this.on('test end', function(test){ self.checkGlobals(test); });
3026
+ this.on('hook end', function(hook){ self.checkGlobals(hook); });
3027
+ this.grep(/.*/);
3028
+ this.globals(utils.keys(global).concat(['errno']));
3029
+ }
3030
+
3031
+ /**
3032
+ * Inherit from `EventEmitter.prototype`.
3033
+ */
3034
+
3035
+ Runner.prototype = new EventEmitter;
3036
+ Runner.prototype.constructor = Runner;
3037
+
3038
+
3039
+ /**
3040
+ * Run tests with full titles matching `re`.
3041
+ *
3042
+ * @param {RegExp} re
3043
+ * @return {Runner} for chaining
3044
+ * @api public
3045
+ */
3046
+
3047
+ Runner.prototype.grep = function(re){
3048
+ debug('grep %s', re);
3049
+ this._grep = re;
3050
+ return this;
3051
+ };
3052
+
3053
+ /**
3054
+ * Allow the given `arr` of globals.
3055
+ *
3056
+ * @param {Array} arr
3057
+ * @return {Runner} for chaining
3058
+ * @api public
3059
+ */
3060
+
3061
+ Runner.prototype.globals = function(arr){
3062
+ if (0 == arguments.length) return this._globals;
3063
+ debug('globals %j', arr);
3064
+ utils.forEach(arr, function(arr){
3065
+ this._globals.push(arr);
3066
+ }, this);
3067
+ return this;
3068
+ };
3069
+
3070
+ /**
3071
+ * Check for global variable leaks.
3072
+ *
3073
+ * @api private
3074
+ */
3075
+
3076
+ Runner.prototype.checkGlobals = function(test){
3077
+ if (this.ignoreLeaks) return;
3078
+
3079
+ var leaks = utils.filter(utils.keys(global), function(key){
3080
+ return !~utils.indexOf(this._globals, key) && (!global.navigator || 'onerror' !== key);
3081
+ }, this);
3082
+
3083
+ this._globals = this._globals.concat(leaks);
3084
+
3085
+ if (leaks.length > 1) {
3086
+ this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
3087
+ } else if (leaks.length) {
3088
+ this.fail(test, new Error('global leak detected: ' + leaks[0]));
3089
+ }
3090
+ };
3091
+
3092
+ /**
3093
+ * Fail the given `test`.
3094
+ *
3095
+ * @param {Test} test
3096
+ * @param {Error} err
3097
+ * @api private
3098
+ */
3099
+
3100
+ Runner.prototype.fail = function(test, err){
3101
+ ++this.failures;
3102
+ test.state = 'failed';
3103
+ this.emit('fail', test, err);
3104
+ };
3105
+
3106
+ /**
3107
+ * Fail the given `hook` with `err`.
3108
+ *
3109
+ * Hook failures (currently) hard-end due
3110
+ * to that fact that a failing hook will
3111
+ * surely cause subsequent tests to fail,
3112
+ * causing jumbled reporting.
3113
+ *
3114
+ * @param {Hook} hook
3115
+ * @param {Error} err
3116
+ * @api private
3117
+ */
3118
+
3119
+ Runner.prototype.failHook = function(hook, err){
3120
+ this.fail(hook, err);
3121
+ this.emit('end');
3122
+ };
3123
+
3124
+ /**
3125
+ * Run hook `name` callbacks and then invoke `fn()`.
3126
+ *
3127
+ * @param {String} name
3128
+ * @param {Function} function
3129
+ * @api private
3130
+ */
3131
+
3132
+ Runner.prototype.hook = function(name, fn){
3133
+ var suite = this.suite
3134
+ , hooks = suite['_' + name]
3135
+ , ms = suite._timeout
3136
+ , self = this
3137
+ , timer;
3138
+
3139
+ function next(i) {
3140
+ var hook = hooks[i];
3141
+ if (!hook) return fn();
3142
+ self.currentRunnable = hook;
3143
+ hook.ctx.test(self.test);
3144
+
3145
+ self.emit('hook', hook);
3146
+
3147
+ hook.on('error', function(err){
3148
+ self.failHook(hook, err);
3149
+ });
3150
+
3151
+ hook.run(function(err){
3152
+ hook.removeAllListeners('error');
3153
+ if (err) return self.failHook(hook, err);
3154
+ self.emit('hook end', hook);
3155
+ next(++i);
3156
+ });
3157
+ }
3158
+
3159
+ process.nextTick(function(){
3160
+ next(0);
3161
+ });
3162
+ };
3163
+
3164
+ /**
3165
+ * Run hook `name` for the given array of `suites`
3166
+ * in order, and callback `fn(err)`.
3167
+ *
3168
+ * @param {String} name
3169
+ * @param {Array} suites
3170
+ * @param {Function} fn
3171
+ * @api private
3172
+ */
3173
+
3174
+ Runner.prototype.hooks = function(name, suites, fn){
3175
+ var self = this
3176
+ , orig = this.suite;
3177
+
3178
+ function next(suite) {
3179
+ self.suite = suite;
3180
+
3181
+ if (!suite) {
3182
+ self.suite = orig;
3183
+ return fn();
3184
+ }
3185
+
3186
+ self.hook(name, function(err){
3187
+ if (err) {
3188
+ self.suite = orig;
3189
+ return fn(err);
3190
+ }
3191
+
3192
+ next(suites.pop());
3193
+ });
3194
+ }
3195
+
3196
+ next(suites.pop());
3197
+ };
3198
+
3199
+ /**
3200
+ * Run hooks from the top level down.
3201
+ *
3202
+ * @param {String} name
3203
+ * @param {Function} fn
3204
+ * @api private
3205
+ */
3206
+
3207
+ Runner.prototype.hookUp = function(name, fn){
3208
+ var suites = [this.suite].concat(this.parents()).reverse();
3209
+ this.hooks(name, suites, fn);
3210
+ };
3211
+
3212
+ /**
3213
+ * Run hooks from the bottom up.
3214
+ *
3215
+ * @param {String} name
3216
+ * @param {Function} fn
3217
+ * @api private
3218
+ */
3219
+
3220
+ Runner.prototype.hookDown = function(name, fn){
3221
+ var suites = [this.suite].concat(this.parents());
3222
+ this.hooks(name, suites, fn);
3223
+ };
3224
+
3225
+ /**
3226
+ * Return an array of parent Suites from
3227
+ * closest to furthest.
3228
+ *
3229
+ * @return {Array}
3230
+ * @api private
3231
+ */
3232
+
3233
+ Runner.prototype.parents = function(){
3234
+ var suite = this.suite
3235
+ , suites = [];
3236
+ while (suite = suite.parent) suites.push(suite);
3237
+ return suites;
3238
+ };
3239
+
3240
+ /**
3241
+ * Run the current test and callback `fn(err)`.
3242
+ *
3243
+ * @param {Function} fn
3244
+ * @api private
3245
+ */
3246
+
3247
+ Runner.prototype.runTest = function(fn){
3248
+ var test = this.test
3249
+ , self = this;
3250
+
3251
+ try {
3252
+ test.ctx.test(test);
3253
+ test.on('error', function(err){
3254
+ self.fail(test, err);
3255
+ });
3256
+ test.run(fn);
3257
+ } catch (err) {
3258
+ fn(err);
3259
+ }
3260
+ };
3261
+
3262
+ /**
3263
+ * Run tests in the given `suite` and invoke
3264
+ * the callback `fn()` when complete.
3265
+ *
3266
+ * @param {Suite} suite
3267
+ * @param {Function} fn
3268
+ * @api private
3269
+ */
3270
+
3271
+ Runner.prototype.runTests = function(suite, fn){
3272
+ var self = this
3273
+ , tests = suite.tests
3274
+ , test;
3275
+
3276
+ function next(err) {
3277
+ // if we bail after first err
3278
+ if (self.failures && suite._bail) return fn();
3279
+
3280
+ // next test
3281
+ test = tests.shift();
3282
+
3283
+ // all done
3284
+ if (!test) return fn();
3285
+
3286
+ // grep
3287
+ if (!self._grep.test(test.fullTitle())) return next();
3288
+
3289
+ // pending
3290
+ if (test.pending) {
3291
+ self.emit('pending', test);
3292
+ self.emit('test end', test);
3293
+ return next();
3294
+ }
3295
+
3296
+ // execute test and hook(s)
3297
+ self.emit('test', self.test = test);
3298
+ self.hookDown('beforeEach', function(){
3299
+ self.currentRunnable = self.test;
3300
+ self.runTest(function(err){
3301
+ test = self.test;
3302
+
3303
+ if (err) {
3304
+ self.fail(test, err);
3305
+ self.emit('test end', test);
3306
+ return self.hookUp('afterEach', next);
3307
+ }
3308
+
3309
+ test.state = 'passed';
3310
+ self.emit('pass', test);
3311
+ self.emit('test end', test);
3312
+ self.hookUp('afterEach', next);
3313
+ });
3314
+ });
3315
+ }
3316
+
3317
+ this.next = next;
3318
+ next();
3319
+ };
3320
+
3321
+ /**
3322
+ * Run the given `suite` and invoke the
3323
+ * callback `fn()` when complete.
3324
+ *
3325
+ * @param {Suite} suite
3326
+ * @param {Function} fn
3327
+ * @api private
3328
+ */
3329
+
3330
+ Runner.prototype.runSuite = function(suite, fn){
3331
+ var self = this
3332
+ , i = 0;
3333
+
3334
+ debug('run suite %s', suite.fullTitle());
3335
+ this.emit('suite', this.suite = suite);
3336
+
3337
+ function next() {
3338
+ var curr = suite.suites[i++];
3339
+ if (!curr) return done();
3340
+ self.runSuite(curr, next);
3341
+ }
3342
+
3343
+ function done() {
3344
+ self.suite = suite;
3345
+ self.hook('afterAll', function(){
3346
+ self.emit('suite end', suite);
3347
+ fn();
3348
+ });
3349
+ }
3350
+
3351
+ this.hook('beforeAll', function(){
3352
+ self.runTests(suite, next);
3353
+ });
3354
+ };
3355
+
3356
+ /**
3357
+ * Handle uncaught exceptions.
3358
+ *
3359
+ * @param {Error} err
3360
+ * @api private
3361
+ */
3362
+
3363
+ Runner.prototype.uncaught = function(err){
3364
+ debug('uncaught exception');
3365
+ var runnable = this.currentRunnable;
3366
+ if ('failed' == runnable.state) return;
3367
+ runnable.clearTimeout();
3368
+ err.uncaught = true;
3369
+ this.fail(runnable, err);
3370
+
3371
+ // recover from test
3372
+ if ('test' == runnable.type) {
3373
+ this.emit('test end', runnable);
3374
+ this.hookUp('afterEach', this.next);
3375
+ return;
3376
+ }
3377
+
3378
+ // bail on hooks
3379
+ this.emit('end');
3380
+ };
3381
+
3382
+ /**
3383
+ * Run the root suite and invoke `fn(failures)`
3384
+ * on completion.
3385
+ *
3386
+ * @param {Function} fn
3387
+ * @return {Runner} for chaining
3388
+ * @api public
3389
+ */
3390
+
3391
+ Runner.prototype.run = function(fn){
3392
+ var self = this
3393
+ , fn = fn || function(){};
3394
+
3395
+ debug('start');
3396
+
3397
+ // callback
3398
+ this.on('end', function(){
3399
+ debug('end');
3400
+ process.removeListener('uncaughtException', this.uncaught);
3401
+ fn(self.failures);
3402
+ });
3403
+
3404
+ // run suites
3405
+ this.emit('start');
3406
+ this.runSuite(this.suite, function(){
3407
+ debug('finished running');
3408
+ self.emit('end');
3409
+ });
3410
+
3411
+ // uncaught exception
3412
+ process.on('uncaughtException', function(err){
3413
+ self.uncaught(err);
3414
+ });
3415
+
3416
+ return this;
3417
+ };
3418
+
3419
+ }); // module: runner.js
3420
+
3421
+ require.register("suite.js", function(module, exports, require){
3422
+
3423
+ /**
3424
+ * Module dependencies.
3425
+ */
3426
+
3427
+ var EventEmitter = require('browser/events').EventEmitter
3428
+ , debug = require('browser/debug')('suite')
3429
+ , utils = require('./utils')
3430
+ , Hook = require('./hook');
3431
+
3432
+ /**
3433
+ * Expose `Suite`.
3434
+ */
3435
+
3436
+ exports = module.exports = Suite;
3437
+
3438
+ /**
3439
+ * Create a new `Suite` with the given `title`
3440
+ * and parent `Suite`. When a suite with the
3441
+ * same title is already present, that suite
3442
+ * is returned to provide nicer reporter
3443
+ * and more flexible meta-testing.
3444
+ *
3445
+ * @param {Suite} parent
3446
+ * @param {String} title
3447
+ * @return {Suite}
3448
+ * @api public
3449
+ */
3450
+
3451
+ exports.create = function(parent, title){
3452
+ var suite = new Suite(title, parent.ctx);
3453
+ suite.parent = parent;
3454
+ title = suite.fullTitle();
3455
+ parent.addSuite(suite);
3456
+ return suite;
3457
+ };
3458
+
3459
+ /**
3460
+ * Initialize a new `Suite` with the given
3461
+ * `title` and `ctx`.
3462
+ *
3463
+ * @param {String} title
3464
+ * @param {Context} ctx
3465
+ * @api private
3466
+ */
3467
+
3468
+ function Suite(title, ctx) {
3469
+ this.title = title;
3470
+ this.ctx = ctx;
3471
+ this.suites = [];
3472
+ this.tests = [];
3473
+ this._beforeEach = [];
3474
+ this._beforeAll = [];
3475
+ this._afterEach = [];
3476
+ this._afterAll = [];
3477
+ this.root = !title;
3478
+ this._timeout = 2000;
3479
+ this._bail = false;
3480
+ }
3481
+
3482
+ /**
3483
+ * Inherit from `EventEmitter.prototype`.
3484
+ */
3485
+
3486
+ Suite.prototype = new EventEmitter;
3487
+ Suite.prototype.constructor = Suite;
3488
+
3489
+
3490
+ /**
3491
+ * Return a clone of this `Suite`.
3492
+ *
3493
+ * @return {Suite}
3494
+ * @api private
3495
+ */
3496
+
3497
+ Suite.prototype.clone = function(){
3498
+ var suite = new Suite(this.title);
3499
+ debug('clone');
3500
+ suite.ctx = this.ctx;
3501
+ suite.timeout(this.timeout());
3502
+ suite.bail(this.bail());
3503
+ return suite;
3504
+ };
3505
+
3506
+ /**
3507
+ * Set timeout `ms` or short-hand such as "2s".
3508
+ *
3509
+ * @param {Number|String} ms
3510
+ * @return {Suite|Number} for chaining
3511
+ * @api private
3512
+ */
3513
+
3514
+ Suite.prototype.timeout = function(ms){
3515
+ if (0 == arguments.length) return this._timeout;
3516
+ if (String(ms).match(/s$/)) ms = parseFloat(ms) * 1000;
3517
+ debug('timeout %d', ms);
3518
+ this._timeout = parseInt(ms, 10);
3519
+ return this;
3520
+ };
3521
+
3522
+ /**
3523
+ * Sets whether to bail after first error.
3524
+ *
3525
+ * @parma {Boolean} bail
3526
+ * @return {Suite|Number} for chaining
3527
+ * @api private
3528
+ */
3529
+
3530
+ Suite.prototype.bail = function(bail){
3531
+ if (0 == arguments.length) return this._bail;
3532
+ debug('bail %s', bail);
3533
+ this._bail = bail;
3534
+ return this;
3535
+ };
3536
+
3537
+ /**
3538
+ * Run `fn(test[, done])` before running tests.
3539
+ *
3540
+ * @param {Function} fn
3541
+ * @return {Suite} for chaining
3542
+ * @api private
3543
+ */
3544
+
3545
+ Suite.prototype.beforeAll = function(fn){
3546
+ var hook = new Hook('"before all" hook', fn);
3547
+ hook.parent = this;
3548
+ hook.timeout(this.timeout());
3549
+ hook.ctx = this.ctx;
3550
+ this._beforeAll.push(hook);
3551
+ this.emit('beforeAll', hook);
3552
+ return this;
3553
+ };
3554
+
3555
+ /**
3556
+ * Run `fn(test[, done])` after running tests.
3557
+ *
3558
+ * @param {Function} fn
3559
+ * @return {Suite} for chaining
3560
+ * @api private
3561
+ */
3562
+
3563
+ Suite.prototype.afterAll = function(fn){
3564
+ var hook = new Hook('"after all" hook', fn);
3565
+ hook.parent = this;
3566
+ hook.timeout(this.timeout());
3567
+ hook.ctx = this.ctx;
3568
+ this._afterAll.push(hook);
3569
+ this.emit('afterAll', hook);
3570
+ return this;
3571
+ };
3572
+
3573
+ /**
3574
+ * Run `fn(test[, done])` before each test case.
3575
+ *
3576
+ * @param {Function} fn
3577
+ * @return {Suite} for chaining
3578
+ * @api private
3579
+ */
3580
+
3581
+ Suite.prototype.beforeEach = function(fn){
3582
+ var hook = new Hook('"before each" hook', fn);
3583
+ hook.parent = this;
3584
+ hook.timeout(this.timeout());
3585
+ hook.ctx = this.ctx;
3586
+ this._beforeEach.push(hook);
3587
+ this.emit('beforeEach', hook);
3588
+ return this;
3589
+ };
3590
+
3591
+ /**
3592
+ * Run `fn(test[, done])` after each test case.
3593
+ *
3594
+ * @param {Function} fn
3595
+ * @return {Suite} for chaining
3596
+ * @api private
3597
+ */
3598
+
3599
+ Suite.prototype.afterEach = function(fn){
3600
+ var hook = new Hook('"after each" hook', fn);
3601
+ hook.parent = this;
3602
+ hook.timeout(this.timeout());
3603
+ hook.ctx = this.ctx;
3604
+ this._afterEach.push(hook);
3605
+ this.emit('afterEach', hook);
3606
+ return this;
3607
+ };
3608
+
3609
+ /**
3610
+ * Add a test `suite`.
3611
+ *
3612
+ * @param {Suite} suite
3613
+ * @return {Suite} for chaining
3614
+ * @api private
3615
+ */
3616
+
3617
+ Suite.prototype.addSuite = function(suite){
3618
+ suite.parent = this;
3619
+ suite.timeout(this.timeout());
3620
+ suite.bail(this.bail());
3621
+ this.suites.push(suite);
3622
+ this.emit('suite', suite);
3623
+ return this;
3624
+ };
3625
+
3626
+ /**
3627
+ * Add a `test` to this suite.
3628
+ *
3629
+ * @param {Test} test
3630
+ * @return {Suite} for chaining
3631
+ * @api private
3632
+ */
3633
+
3634
+ Suite.prototype.addTest = function(test){
3635
+ test.parent = this;
3636
+ test.timeout(this.timeout());
3637
+ test.ctx = this.ctx;
3638
+ this.tests.push(test);
3639
+ this.emit('test', test);
3640
+ return this;
3641
+ };
3642
+
3643
+ /**
3644
+ * Return the full title generated by recursively
3645
+ * concatenating the parent's full title.
3646
+ *
3647
+ * @return {String}
3648
+ * @api public
3649
+ */
3650
+
3651
+ Suite.prototype.fullTitle = function(){
3652
+ if (this.parent) {
3653
+ var full = this.parent.fullTitle();
3654
+ if (full) return full + ' ' + this.title;
3655
+ }
3656
+ return this.title;
3657
+ };
3658
+
3659
+ /**
3660
+ * Return the total number of tests.
3661
+ *
3662
+ * @return {Number}
3663
+ * @api public
3664
+ */
3665
+
3666
+ Suite.prototype.total = function(){
3667
+ return utils.reduce(this.suites, function(sum, suite){
3668
+ return sum + suite.total();
3669
+ }, 0) + this.tests.length;
3670
+ };
3671
+
3672
+ }); // module: suite.js
3673
+
3674
+ require.register("test.js", function(module, exports, require){
3675
+
3676
+ /**
3677
+ * Module dependencies.
3678
+ */
3679
+
3680
+ var Runnable = require('./runnable');
3681
+
3682
+ /**
3683
+ * Expose `Test`.
3684
+ */
3685
+
3686
+ module.exports = Test;
3687
+
3688
+ /**
3689
+ * Initialize a new `Test` with the given `title` and callback `fn`.
3690
+ *
3691
+ * @param {String} title
3692
+ * @param {Function} fn
3693
+ * @api private
3694
+ */
3695
+
3696
+ function Test(title, fn) {
3697
+ Runnable.call(this, title, fn);
3698
+ this.pending = !fn;
3699
+ this.type = 'test';
3700
+ }
3701
+
3702
+ /**
3703
+ * Inherit from `Runnable.prototype`.
3704
+ */
3705
+
3706
+ Test.prototype = new Runnable;
3707
+ Test.prototype.constructor = Test;
3708
+
3709
+
3710
+ /**
3711
+ * Inspect the context void of private properties.
3712
+ *
3713
+ * @return {String}
3714
+ * @api private
3715
+ */
3716
+
3717
+ Test.prototype.inspect = function(){
3718
+ return JSON.stringify(this, function(key, val){
3719
+ return '_' == key[0]
3720
+ ? undefined
3721
+ : 'parent' == key
3722
+ ? '#<Suite>'
3723
+ : val;
3724
+ }, 2);
3725
+ };
3726
+ }); // module: test.js
3727
+
3728
+ require.register("utils.js", function(module, exports, require){
3729
+
3730
+ /**
3731
+ * Module dependencies.
3732
+ */
3733
+
3734
+ var fs = require('browser/fs')
3735
+ , path = require('browser/path')
3736
+ , join = path.join
3737
+ , debug = require('browser/debug')('watch');
3738
+
3739
+ /**
3740
+ * Ignored directories.
3741
+ */
3742
+
3743
+ var ignore = ['node_modules', '.git'];
3744
+
3745
+ /**
3746
+ * Escape special characters in the given string of html.
3747
+ *
3748
+ * @param {String} html
3749
+ * @return {String}
3750
+ * @api private
3751
+ */
3752
+
3753
+ exports.escape = function(html) {
3754
+ return String(html)
3755
+ .replace(/&/g, '&amp;')
3756
+ .replace(/"/g, '&quot;')
3757
+ .replace(/</g, '&lt;')
3758
+ .replace(/>/g, '&gt;');
3759
+ };
3760
+
3761
+ /**
3762
+ * Array#forEach (<=IE8)
3763
+ *
3764
+ * @param {Array} array
3765
+ * @param {Function} fn
3766
+ * @param {Object} scope
3767
+ * @api private
3768
+ */
3769
+
3770
+ exports.forEach = function(arr, fn, scope) {
3771
+ for (var i = 0, l = arr.length; i < l; i++)
3772
+ fn.call(scope, arr[i], i);
3773
+ };
3774
+
3775
+ /**
3776
+ * Array#indexOf (<=IE8)
3777
+ *
3778
+ * @parma {Array} arr
3779
+ * @param {Object} obj to find index of
3780
+ * @param {Number} start
3781
+ * @api private
3782
+ */
3783
+
3784
+ exports.indexOf = function (arr, obj, start) {
3785
+ for (var i = start || 0, l = arr.length; i < l; i++) {
3786
+ if (arr[i] === obj)
3787
+ return i;
3788
+ }
3789
+ return -1;
3790
+ };
3791
+
3792
+ /**
3793
+ * Array#reduce (<=IE8)
3794
+ *
3795
+ * @param {Array} array
3796
+ * @param {Function} fn
3797
+ * @param {Object} initial value
3798
+ * @param {Object} scope
3799
+ * @api private
3800
+ */
3801
+
3802
+ exports.reduce = function(arr, fn, val, scope) {
3803
+ var rval = val;
3804
+
3805
+ for (var i = 0, l = arr.length; i < l; i++) {
3806
+ rval = fn.call(scope, rval, arr[i], i, arr);
3807
+ }
3808
+
3809
+ return rval;
3810
+ };
3811
+
3812
+ /**
3813
+ * Array#filter (<=IE8)
3814
+ *
3815
+ * @param {Array} array
3816
+ * @param {Function} fn
3817
+ * @param {Object} scope
3818
+ * @api private
3819
+ */
3820
+
3821
+ exports.filter = function(arr, fn, scope) {
3822
+ var ret = [];
3823
+
3824
+ for (var i = 0, l = arr.length; i < l; i++) {
3825
+ var val = arr[i];
3826
+ if (fn.call(scope, val, i, arr))
3827
+ ret.push(val);
3828
+ }
3829
+
3830
+ return ret;
3831
+ };
3832
+
3833
+ /**
3834
+ * Object.keys (<=IE8)
3835
+ *
3836
+ * @param {Object} obj
3837
+ * @return {Array} keys
3838
+ * @api private
3839
+ */
3840
+
3841
+ exports.keys = Object.keys || function(obj) {
3842
+ var keys = []
3843
+ , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
3844
+
3845
+ for (var key in obj) {
3846
+ if (has.call(obj, key)) {
3847
+ keys.push(key);
3848
+ }
3849
+ }
3850
+
3851
+ return keys;
3852
+ };
3853
+
3854
+ /**
3855
+ * Watch the given `files` for changes
3856
+ * and invoke `fn(file)` on modification.
3857
+ *
3858
+ * @param {Array} files
3859
+ * @param {Function} fn
3860
+ * @api private
3861
+ */
3862
+
3863
+ exports.watch = function(files, fn){
3864
+ var options = { interval: 100 };
3865
+ files.forEach(function(file){
3866
+ debug('file %s', file);
3867
+ fs.watchFile(file, options, function(curr, prev){
3868
+ if (prev.mtime < curr.mtime) fn(file);
3869
+ });
3870
+ });
3871
+ };
3872
+
3873
+ /**
3874
+ * Ignored files.
3875
+ */
3876
+
3877
+ function ignored(path){
3878
+ return !~ignore.indexOf(path);
3879
+ }
3880
+
3881
+ /**
3882
+ * Lookup files in the given `dir`.
3883
+ *
3884
+ * @return {Array}
3885
+ * @api private
3886
+ */
3887
+
3888
+ exports.files = function(dir, ret){
3889
+ ret = ret || [];
3890
+
3891
+ fs.readdirSync(dir)
3892
+ .filter(ignored)
3893
+ .forEach(function(path){
3894
+ path = join(dir, path);
3895
+ if (fs.statSync(path).isDirectory()) {
3896
+ exports.files(path, ret);
3897
+ } else if (path.match(/\.(js|coffee)$/)) {
3898
+ ret.push(path);
3899
+ }
3900
+ });
3901
+
3902
+ return ret;
3903
+ };
3904
+
3905
+ /**
3906
+ * Compute a slug from the given `str`.
3907
+ *
3908
+ * @param {String} str
3909
+ * @return {String}
3910
+ */
3911
+
3912
+ exports.slug = function(str){
3913
+ return str
3914
+ .toLowerCase()
3915
+ .replace(/ +/g, '-')
3916
+ .replace(/[^-\w]/g, '');
3917
+ };
3918
+ }); // module: utils.js
3919
+
3920
+ /**
3921
+ * Node shims.
3922
+ *
3923
+ * These are meant only to allow
3924
+ * mocha.js to run untouched, not
3925
+ * to allow running node code in
3926
+ * the browser.
3927
+ */
3928
+
3929
+ process = {};
3930
+ process.exit = function(status){};
3931
+ process.stdout = {};
3932
+ global = window;
3933
+
3934
+ /**
3935
+ * next tick implementation.
3936
+ */
3937
+
3938
+ process.nextTick = (function(){
3939
+ // postMessage behaves badly on IE8
3940
+ if (window.ActiveXObject || !window.postMessage) {
3941
+ return function(fn){ fn() };
3942
+ }
3943
+
3944
+ // based on setZeroTimeout by David Baron
3945
+ // - http://dbaron.org/log/20100309-faster-timeouts
3946
+ var timeouts = []
3947
+ , name = 'mocha-zero-timeout'
3948
+
3949
+ return function(fn){
3950
+ timeouts.push(fn);
3951
+ window.postMessage(name, '*');
3952
+ window.addEventListener('message', function(e){
3953
+ if (e.source == window && e.data == name) {
3954
+ if (e.stopPropagation) e.stopPropagation();
3955
+ if (timeouts.length) timeouts.shift()();
3956
+ }
3957
+ }, true);
3958
+ }
3959
+ })();
3960
+
3961
+ /**
3962
+ * Remove uncaughtException listener.
3963
+ */
3964
+
3965
+ process.removeListener = function(e){
3966
+ if ('uncaughtException' == e) {
3967
+ window.onerror = null;
3968
+ }
3969
+ };
3970
+
3971
+ /**
3972
+ * Implements uncaughtException listener.
3973
+ */
3974
+
3975
+ process.on = function(e, fn){
3976
+ if ('uncaughtException' == e) {
3977
+ window.onerror = fn;
3978
+ }
3979
+ };
3980
+
3981
+ /**
3982
+ * Expose mocha.
3983
+ */
3984
+
3985
+ window.mocha = require('mocha');
3986
+
3987
+ // boot
3988
+ ;(function(){
3989
+ var suite = new mocha.Suite('', new mocha.Context)
3990
+ , utils = mocha.utils
3991
+ , options = {}
3992
+
3993
+ /**
3994
+ * Highlight the given string of `js`.
3995
+ */
3996
+
3997
+ function highlight(js) {
3998
+ return js
3999
+ .replace(/</g, '&lt;')
4000
+ .replace(/>/g, '&gt;')
4001
+ .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
4002
+ .replace(/('.*?')/gm, '<span class="string">$1</span>')
4003
+ .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
4004
+ .replace(/(\d+)/gm, '<span class="number">$1</span>')
4005
+ .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
4006
+ .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
4007
+ }
4008
+
4009
+ /**
4010
+ * Highlight code contents.
4011
+ */
4012
+
4013
+ function highlightCode() {
4014
+ var code = document.getElementsByTagName('code');
4015
+ for (var i = 0, len = code.length; i < len; ++i) {
4016
+ code[i].innerHTML = highlight(code[i].innerHTML);
4017
+ }
4018
+ }
4019
+
4020
+ /**
4021
+ * Parse the given `qs`.
4022
+ */
4023
+
4024
+ function parse(qs) {
4025
+ return utils.reduce(qs.replace('?', '').split('&'), function(obj, pair){
4026
+ var i = pair.indexOf('=')
4027
+ , key = pair.slice(0, i)
4028
+ , val = pair.slice(++i);
4029
+
4030
+ obj[key] = decodeURIComponent(val);
4031
+ return obj;
4032
+ }, {});
4033
+ }
4034
+
4035
+ /**
4036
+ * Setup mocha with the given setting options.
4037
+ */
4038
+
4039
+ mocha.setup = function(opts){
4040
+ if ('string' === typeof opts) options.ui = opts;
4041
+ else options = opts;
4042
+
4043
+ ui = mocha.interfaces[options.ui];
4044
+ if (!ui) throw new Error('invalid mocha interface "' + ui + '"');
4045
+ if (options.timeout) suite.timeout(options.timeout);
4046
+ ui(suite);
4047
+ suite.emit('pre-require', window);
4048
+ };
4049
+
4050
+ /**
4051
+ * Run mocha, returning the Runner.
4052
+ */
4053
+
4054
+ mocha.run = function(){
4055
+ suite.emit('run');
4056
+ var runner = new mocha.Runner(suite);
4057
+ var Reporter = options.reporter || mocha.reporters.HTML;
4058
+ var reporter = new Reporter(runner);
4059
+ var query = parse(window.location.search || "");
4060
+ if (query.grep) runner.grep(new RegExp(query.grep));
4061
+ if (options.ignoreLeaks) runner.ignoreLeaks = true;
4062
+ if (options.globals) runner.globals(options.globals);
4063
+ runner.globals(['location']);
4064
+ runner.on('end', highlightCode);
4065
+ return runner.run();
4066
+ };
4067
+ })();
4068
+ })();