mocha_rails 0.0.1

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 (51) hide show
  1. data/MIT-LICENSE +22 -0
  2. data/Rakefile +38 -0
  3. data/Readme.md +78 -0
  4. data/app/assets/javascripts/mocha_rails/application.js +4 -0
  5. data/app/assets/javascripts/mocha_rails/mocha-rails.js +5 -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 +6 -0
  9. data/app/helpers/mocha_rails/application_helper.rb +4 -0
  10. data/app/views/mocha_rails/tests/index.html.erb +13 -0
  11. data/config/initializers/mocha_rails.rb +4 -0
  12. data/config/routes.rb +3 -0
  13. data/lib/mocha_rails/engine.rb +5 -0
  14. data/lib/mocha_rails/version.rb +3 -0
  15. data/lib/mocha_rails.rb +4 -0
  16. data/lib/tasks/mocha_rails_tasks.rake +4 -0
  17. data/test/dummy/README.rdoc +261 -0
  18. data/test/dummy/Rakefile +7 -0
  19. data/test/dummy/app/assets/javascripts/application.js +15 -0
  20. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  21. data/test/dummy/app/controllers/application_controller.rb +3 -0
  22. data/test/dummy/app/helpers/application_helper.rb +2 -0
  23. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  24. data/test/dummy/config/application.rb +62 -0
  25. data/test/dummy/config/boot.rb +10 -0
  26. data/test/dummy/config/environment.rb +5 -0
  27. data/test/dummy/config/environments/development.rb +31 -0
  28. data/test/dummy/config/environments/production.rb +64 -0
  29. data/test/dummy/config/environments/test.rb +35 -0
  30. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  31. data/test/dummy/config/initializers/inflections.rb +15 -0
  32. data/test/dummy/config/initializers/mime_types.rb +5 -0
  33. data/test/dummy/config/initializers/secret_token.rb +7 -0
  34. data/test/dummy/config/initializers/session_store.rb +8 -0
  35. data/test/dummy/config/initializers/wrap_parameters.rb +10 -0
  36. data/test/dummy/config/locales/en.yml +5 -0
  37. data/test/dummy/config/routes.rb +4 -0
  38. data/test/dummy/config.ru +4 -0
  39. data/test/dummy/log/test.log +0 -0
  40. data/test/dummy/public/404.html +26 -0
  41. data/test/dummy/public/422.html +26 -0
  42. data/test/dummy/public/500.html +25 -0
  43. data/test/dummy/public/favicon.ico +0 -0
  44. data/test/dummy/script/rails +6 -0
  45. data/test/integration/navigation_test.rb +9 -0
  46. data/test/mocha_rails_test.rb +7 -0
  47. data/test/test_helper.rb +10 -0
  48. data/vendor/assets/javascripts/expect.js +1202 -0
  49. data/vendor/assets/javascripts/mocha.css +133 -0
  50. data/vendor/assets/javascripts/mocha.js +3381 -0
  51. metadata +164 -0
@@ -0,0 +1,3381 @@
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/events.js", function(module, exports, require){
61
+
62
+ /**
63
+ * Module exports.
64
+ */
65
+
66
+ exports.EventEmitter = EventEmitter;
67
+
68
+ /**
69
+ * Check if `obj` is an array.
70
+ */
71
+
72
+ function isArray(obj) {
73
+ return '[object Array]' == {}.toString.call(obj);
74
+ }
75
+
76
+ /**
77
+ * Event emitter constructor.
78
+ *
79
+ * @api public.
80
+ */
81
+
82
+ function EventEmitter(){};
83
+
84
+ /**
85
+ * Adds a listener.
86
+ *
87
+ * @api public
88
+ */
89
+
90
+ EventEmitter.prototype.on = function (name, fn) {
91
+ if (!this.$events) {
92
+ this.$events = {};
93
+ }
94
+
95
+ if (!this.$events[name]) {
96
+ this.$events[name] = fn;
97
+ } else if (isArray(this.$events[name])) {
98
+ this.$events[name].push(fn);
99
+ } else {
100
+ this.$events[name] = [this.$events[name], fn];
101
+ }
102
+
103
+ return this;
104
+ };
105
+
106
+ EventEmitter.prototype.addListener = EventEmitter.prototype.on;
107
+
108
+ /**
109
+ * Adds a volatile listener.
110
+ *
111
+ * @api public
112
+ */
113
+
114
+ EventEmitter.prototype.once = function (name, fn) {
115
+ var self = this;
116
+
117
+ function on () {
118
+ self.removeListener(name, on);
119
+ fn.apply(this, arguments);
120
+ };
121
+
122
+ on.listener = fn;
123
+ this.on(name, on);
124
+
125
+ return this;
126
+ };
127
+
128
+ /**
129
+ * Removes a listener.
130
+ *
131
+ * @api public
132
+ */
133
+
134
+ EventEmitter.prototype.removeListener = function (name, fn) {
135
+ if (this.$events && this.$events[name]) {
136
+ var list = this.$events[name];
137
+
138
+ if (isArray(list)) {
139
+ var pos = -1;
140
+
141
+ for (var i = 0, l = list.length; i < l; i++) {
142
+ if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
143
+ pos = i;
144
+ break;
145
+ }
146
+ }
147
+
148
+ if (pos < 0) {
149
+ return this;
150
+ }
151
+
152
+ list.splice(pos, 1);
153
+
154
+ if (!list.length) {
155
+ delete this.$events[name];
156
+ }
157
+ } else if (list === fn || (list.listener && list.listener === fn)) {
158
+ delete this.$events[name];
159
+ }
160
+ }
161
+
162
+ return this;
163
+ };
164
+
165
+ /**
166
+ * Removes all listeners for an event.
167
+ *
168
+ * @api public
169
+ */
170
+
171
+ EventEmitter.prototype.removeAllListeners = function (name) {
172
+ if (name === undefined) {
173
+ this.$events = {};
174
+ return this;
175
+ }
176
+
177
+ if (this.$events && this.$events[name]) {
178
+ this.$events[name] = null;
179
+ }
180
+
181
+ return this;
182
+ };
183
+
184
+ /**
185
+ * Gets all listeners for a certain event.
186
+ *
187
+ * @api publci
188
+ */
189
+
190
+ EventEmitter.prototype.listeners = function (name) {
191
+ if (!this.$events) {
192
+ this.$events = {};
193
+ }
194
+
195
+ if (!this.$events[name]) {
196
+ this.$events[name] = [];
197
+ }
198
+
199
+ if (!isArray(this.$events[name])) {
200
+ this.$events[name] = [this.$events[name]];
201
+ }
202
+
203
+ return this.$events[name];
204
+ };
205
+
206
+ /**
207
+ * Emits an event.
208
+ *
209
+ * @api public
210
+ */
211
+
212
+ EventEmitter.prototype.emit = function (name) {
213
+ if (!this.$events) {
214
+ return false;
215
+ }
216
+
217
+ var handler = this.$events[name];
218
+
219
+ if (!handler) {
220
+ return false;
221
+ }
222
+
223
+ var args = [].slice.call(arguments, 1);
224
+
225
+ if ('function' == typeof handler) {
226
+ handler.apply(this, args);
227
+ } else if (isArray(handler)) {
228
+ var listeners = handler.slice();
229
+
230
+ for (var i = 0, l = listeners.length; i < l; i++) {
231
+ listeners[i].apply(this, args);
232
+ }
233
+ } else {
234
+ return false;
235
+ }
236
+
237
+ return true;
238
+ };
239
+ }); // module: browser/events.js
240
+
241
+ require.register("browser/fs.js", function(module, exports, require){
242
+
243
+ }); // module: browser/fs.js
244
+
245
+ require.register("browser/path.js", function(module, exports, require){
246
+
247
+ }); // module: browser/path.js
248
+
249
+ require.register("browser/progress.js", function(module, exports, require){
250
+
251
+ /**
252
+ * Expose `Progress`.
253
+ */
254
+
255
+ module.exports = Progress;
256
+
257
+ /**
258
+ * Initialize a new `Progress` indicator.
259
+ */
260
+
261
+ function Progress() {
262
+ this.percent = 0;
263
+ this.size(0);
264
+ this.fontSize(11);
265
+ this.font('helvetica, arial, sans-serif');
266
+ }
267
+
268
+ /**
269
+ * Set progress size to `n`.
270
+ *
271
+ * @param {Number} n
272
+ * @return {Progress} for chaining
273
+ * @api public
274
+ */
275
+
276
+ Progress.prototype.size = function(n){
277
+ this._size = n;
278
+ return this;
279
+ };
280
+
281
+ /**
282
+ * Set text to `str`.
283
+ *
284
+ * @param {String} str
285
+ * @return {Progress} for chaining
286
+ * @api public
287
+ */
288
+
289
+ Progress.prototype.text = function(str){
290
+ this._text = str;
291
+ return this;
292
+ };
293
+
294
+ /**
295
+ * Set font size to `n`.
296
+ *
297
+ * @param {Number} n
298
+ * @return {Progress} for chaining
299
+ * @api public
300
+ */
301
+
302
+ Progress.prototype.fontSize = function(n){
303
+ this._fontSize = n;
304
+ return this;
305
+ };
306
+
307
+ /**
308
+ * Set font `family`.
309
+ *
310
+ * @param {String} family
311
+ * @return {Progress} for chaining
312
+ */
313
+
314
+ Progress.prototype.font = function(family){
315
+ this._font = family;
316
+ return this;
317
+ };
318
+
319
+ /**
320
+ * Update percentage to `n`.
321
+ *
322
+ * @param {Number} n
323
+ * @return {Progress} for chaining
324
+ */
325
+
326
+ Progress.prototype.update = function(n){
327
+ this.percent = n;
328
+ return this;
329
+ };
330
+
331
+ /**
332
+ * Draw on `ctx`.
333
+ *
334
+ * @param {CanvasRenderingContext2d} ctx
335
+ * @return {Progress} for chaining
336
+ */
337
+
338
+ Progress.prototype.draw = function(ctx){
339
+ var percent = Math.min(this.percent, 100)
340
+ , size = this._size
341
+ , half = size / 2
342
+ , x = half
343
+ , y = half
344
+ , rad = half - 1
345
+ , fontSize = this._fontSize;
346
+
347
+ ctx.font = fontSize + 'px ' + this._font;
348
+
349
+ var angle = Math.PI * 2 * (percent / 100);
350
+ ctx.clearRect(0, 0, size, size);
351
+
352
+ // outer circle
353
+ ctx.strokeStyle = '#9f9f9f';
354
+ ctx.beginPath();
355
+ ctx.arc(x, y, rad, 0, angle, false);
356
+ ctx.stroke();
357
+
358
+ // inner circle
359
+ ctx.strokeStyle = '#eee';
360
+ ctx.beginPath();
361
+ ctx.arc(x, y, rad - 1, 0, angle, true);
362
+ ctx.stroke();
363
+
364
+ // text
365
+ var text = this._text || (percent | 0) + '%'
366
+ , w = ctx.measureText(text).width;
367
+
368
+ ctx.fillText(
369
+ text
370
+ , x - w / 2 + 1
371
+ , y + fontSize / 2 - 1);
372
+
373
+ return this;
374
+ };
375
+
376
+ }); // module: browser/progress.js
377
+
378
+ require.register("browser/tty.js", function(module, exports, require){
379
+
380
+ exports.isatty = function(){
381
+ return true;
382
+ };
383
+
384
+ exports.getWindowSize = function(){
385
+ return [window.innerHeight, window.innerWidth];
386
+ };
387
+ }); // module: browser/tty.js
388
+
389
+ require.register("context.js", function(module, exports, require){
390
+
391
+ /**
392
+ * Expose `Context`.
393
+ */
394
+
395
+ module.exports = Context;
396
+
397
+ /**
398
+ * Initialize a new `Context`.
399
+ *
400
+ * @api private
401
+ */
402
+
403
+ function Context(){}
404
+
405
+ /**
406
+ * Set the context `Test` to `test`.
407
+ *
408
+ * @param {Test} test
409
+ * @return {Context}
410
+ * @api private
411
+ */
412
+
413
+ Context.prototype.test = function(test){
414
+ this._test = test;
415
+ return this;
416
+ };
417
+
418
+ /**
419
+ * Set test timeout `ms`.
420
+ *
421
+ * @param {Number} ms
422
+ * @return {Context} self
423
+ * @api private
424
+ */
425
+
426
+ Context.prototype.timeout = function(ms){
427
+ this._test.timeout(ms);
428
+ return this;
429
+ };
430
+
431
+ /**
432
+ * Inspect the context void of `._test`.
433
+ *
434
+ * @return {String}
435
+ * @api private
436
+ */
437
+
438
+ Context.prototype.inspect = function(){
439
+ return JSON.stringify(this, function(key, val){
440
+ return '_test' == key
441
+ ? undefined
442
+ : val;
443
+ }, 2);
444
+ };
445
+
446
+ }); // module: context.js
447
+
448
+ require.register("hook.js", function(module, exports, require){
449
+
450
+ /**
451
+ * Module dependencies.
452
+ */
453
+
454
+ var Runnable = require('./runnable');
455
+
456
+ /**
457
+ * Expose `Hook`.
458
+ */
459
+
460
+ module.exports = Hook;
461
+
462
+ /**
463
+ * Initialize a new `Hook` with the given `title` and callback `fn`.
464
+ *
465
+ * @param {String} title
466
+ * @param {Function} fn
467
+ * @api private
468
+ */
469
+
470
+ function Hook(title, fn) {
471
+ Runnable.call(this, title, fn);
472
+ this.type = 'hook';
473
+ }
474
+
475
+ /**
476
+ * Inherit from `Runnable.prototype`.
477
+ */
478
+
479
+ Hook.prototype = new Runnable;
480
+ Hook.prototype.constructor = Hook;
481
+
482
+
483
+ }); // module: hook.js
484
+
485
+ require.register("interfaces/bdd.js", function(module, exports, require){
486
+
487
+ /**
488
+ * Module dependencies.
489
+ */
490
+
491
+ var Suite = require('../suite')
492
+ , Test = require('../test');
493
+
494
+ /**
495
+ * BDD-style interface:
496
+ *
497
+ * describe('Array', function(){
498
+ * describe('#indexOf()', function(){
499
+ * it('should return -1 when not present', function(){
500
+ *
501
+ * });
502
+ *
503
+ * it('should return the index when present', function(){
504
+ *
505
+ * });
506
+ * });
507
+ * });
508
+ *
509
+ */
510
+
511
+ module.exports = function(suite){
512
+ var suites = [suite];
513
+
514
+ suite.on('pre-require', function(context){
515
+
516
+ /**
517
+ * Execute before running tests.
518
+ */
519
+
520
+ context.before = function(fn){
521
+ suites[0].beforeAll(fn);
522
+ };
523
+
524
+ /**
525
+ * Execute after running tests.
526
+ */
527
+
528
+ context.after = function(fn){
529
+ suites[0].afterAll(fn);
530
+ };
531
+
532
+ /**
533
+ * Execute before each test case.
534
+ */
535
+
536
+ context.beforeEach = function(fn){
537
+ suites[0].beforeEach(fn);
538
+ };
539
+
540
+ /**
541
+ * Execute after each test case.
542
+ */
543
+
544
+ context.afterEach = function(fn){
545
+ suites[0].afterEach(fn);
546
+ };
547
+
548
+ /**
549
+ * Describe a "suite" with the given `title`
550
+ * and callback `fn` containing nested suites
551
+ * and/or tests.
552
+ */
553
+
554
+ context.describe = function(title, fn){
555
+ var suite = Suite.create(suites[0], title);
556
+ suites.unshift(suite);
557
+ fn();
558
+ suites.shift();
559
+ };
560
+
561
+ /**
562
+ * Describe a specification or test-case
563
+ * with the given `title` and callback `fn`
564
+ * acting as a thunk.
565
+ */
566
+
567
+ context.it = function(title, fn){
568
+ suites[0].addTest(new Test(title, fn));
569
+ };
570
+ });
571
+ };
572
+
573
+ }); // module: interfaces/bdd.js
574
+
575
+ require.register("interfaces/exports.js", function(module, exports, require){
576
+
577
+ /**
578
+ * Module dependencies.
579
+ */
580
+
581
+ var Suite = require('../suite')
582
+ , Test = require('../test');
583
+
584
+ /**
585
+ * TDD-style interface:
586
+ *
587
+ * exports.Array = {
588
+ * '#indexOf()': {
589
+ * 'should return -1 when the value is not present': function(){
590
+ *
591
+ * },
592
+ *
593
+ * 'should return the correct index when the value is present': function(){
594
+ *
595
+ * }
596
+ * }
597
+ * };
598
+ *
599
+ */
600
+
601
+ module.exports = function(suite){
602
+ var suites = [suite];
603
+
604
+ suite.on('require', visit);
605
+
606
+ function visit(obj) {
607
+ var suite;
608
+ for (var key in obj) {
609
+ if ('function' == typeof obj[key]) {
610
+ var fn = obj[key];
611
+ switch (key) {
612
+ case 'before':
613
+ suites[0].beforeAll(fn);
614
+ break;
615
+ case 'after':
616
+ suites[0].afterAll(fn);
617
+ break;
618
+ case 'beforeEach':
619
+ suites[0].beforeEach(fn);
620
+ break;
621
+ case 'afterEach':
622
+ suites[0].afterEach(fn);
623
+ break;
624
+ default:
625
+ suites[0].addTest(new Test(key, fn));
626
+ }
627
+ } else {
628
+ var suite = Suite.create(suites[0], key);
629
+ suites.unshift(suite);
630
+ visit(obj[key]);
631
+ suites.shift();
632
+ }
633
+ }
634
+ }
635
+ };
636
+ }); // module: interfaces/exports.js
637
+
638
+ require.register("interfaces/index.js", function(module, exports, require){
639
+
640
+ exports.bdd = require('./bdd');
641
+ exports.tdd = require('./tdd');
642
+ exports.qunit = require('./qunit');
643
+ exports.exports = require('./exports');
644
+
645
+ }); // module: interfaces/index.js
646
+
647
+ require.register("interfaces/qunit.js", function(module, exports, require){
648
+
649
+ /**
650
+ * Module dependencies.
651
+ */
652
+
653
+ var Suite = require('../suite')
654
+ , Test = require('../test');
655
+
656
+ /**
657
+ * QUnit-style interface:
658
+ *
659
+ * suite('Array');
660
+ *
661
+ * test('#length', function(){
662
+ * var arr = [1,2,3];
663
+ * ok(arr.length == 3);
664
+ * });
665
+ *
666
+ * test('#indexOf()', function(){
667
+ * var arr = [1,2,3];
668
+ * ok(arr.indexOf(1) == 0);
669
+ * ok(arr.indexOf(2) == 1);
670
+ * ok(arr.indexOf(3) == 2);
671
+ * });
672
+ *
673
+ * suite('String');
674
+ *
675
+ * test('#length', function(){
676
+ * ok('foo'.length == 3);
677
+ * });
678
+ *
679
+ */
680
+
681
+ module.exports = function(suite){
682
+ var suites = [suite];
683
+
684
+ suite.on('pre-require', function(context){
685
+
686
+ /**
687
+ * Execute before running tests.
688
+ */
689
+
690
+ context.before = function(fn){
691
+ suites[0].beforeAll(fn);
692
+ };
693
+
694
+ /**
695
+ * Execute after running tests.
696
+ */
697
+
698
+ context.after = function(fn){
699
+ suites[0].afterAll(fn);
700
+ };
701
+
702
+ /**
703
+ * Execute before each test case.
704
+ */
705
+
706
+ context.beforeEach = function(fn){
707
+ suites[0].beforeEach(fn);
708
+ };
709
+
710
+ /**
711
+ * Execute after each test case.
712
+ */
713
+
714
+ context.afterEach = function(fn){
715
+ suites[0].afterEach(fn);
716
+ };
717
+
718
+ /**
719
+ * Describe a "suite" with the given `title`.
720
+ */
721
+
722
+ context.suite = function(title){
723
+ if (suites.length > 1) suites.shift();
724
+ var suite = Suite.create(suites[0], title);
725
+ suites.unshift(suite);
726
+ };
727
+
728
+ /**
729
+ * Describe a specification or test-case
730
+ * with the given `title` and callback `fn`
731
+ * acting as a thunk.
732
+ */
733
+
734
+ context.test = function(title, fn){
735
+ suites[0].addTest(new Test(title, fn));
736
+ };
737
+ });
738
+ };
739
+
740
+ }); // module: interfaces/qunit.js
741
+
742
+ require.register("interfaces/tdd.js", function(module, exports, require){
743
+
744
+ /**
745
+ * Module dependencies.
746
+ */
747
+
748
+ var Suite = require('../suite')
749
+ , Test = require('../test');
750
+
751
+ /**
752
+ * TDD-style interface:
753
+ *
754
+ * suite('Array', function(){
755
+ * suite('#indexOf()', function(){
756
+ * suiteSetup(function(){
757
+ *
758
+ * });
759
+ *
760
+ * test('should return -1 when not present', function(){
761
+ *
762
+ * });
763
+ *
764
+ * test('should return the index when present', function(){
765
+ *
766
+ * });
767
+ *
768
+ * suiteTeardown(function(){
769
+ *
770
+ * });
771
+ * });
772
+ * });
773
+ *
774
+ */
775
+
776
+ module.exports = function(suite){
777
+ var suites = [suite];
778
+
779
+ suite.on('pre-require', function(context){
780
+
781
+ /**
782
+ * Execute before each test case.
783
+ */
784
+
785
+ context.setup = function(fn){
786
+ suites[0].beforeEach(fn);
787
+ };
788
+
789
+ /**
790
+ * Execute after each test case.
791
+ */
792
+
793
+ context.teardown = function(fn){
794
+ suites[0].afterEach(fn);
795
+ };
796
+
797
+ /**
798
+ * Execute before the suite.
799
+ */
800
+
801
+ context.suiteSetup = function(fn){
802
+ suites[0].beforeAll(fn);
803
+ };
804
+
805
+ /**
806
+ * Execute after the suite.
807
+ */
808
+
809
+ context.suiteTeardown = function(fn){
810
+ suites[0].afterAll(fn);
811
+ };
812
+
813
+ /**
814
+ * Describe a "suite" with the given `title`
815
+ * and callback `fn` containing nested suites
816
+ * and/or tests.
817
+ */
818
+
819
+ context.suite = function(title, fn){
820
+ var suite = Suite.create(suites[0], title);
821
+ suites.unshift(suite);
822
+ fn();
823
+ suites.shift();
824
+ };
825
+
826
+ /**
827
+ * Describe a specification or test-case
828
+ * with the given `title` and callback `fn`
829
+ * acting as a thunk.
830
+ */
831
+
832
+ context.test = function(title, fn){
833
+ suites[0].addTest(new Test(title, fn));
834
+ };
835
+ });
836
+ };
837
+
838
+ }); // module: interfaces/tdd.js
839
+
840
+ require.register("mocha.js", function(module, exports, require){
841
+
842
+ /*!
843
+ * mocha
844
+ * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
845
+ * MIT Licensed
846
+ */
847
+
848
+ /**
849
+ * Library version.
850
+ */
851
+
852
+ exports.version = '0.12.0';
853
+
854
+ exports.utils = require('./utils');
855
+ exports.interfaces = require('./interfaces');
856
+ exports.reporters = require('./reporters');
857
+ exports.Runnable = require('./runnable');
858
+ exports.Context = require('./context');
859
+ exports.Runner = require('./runner');
860
+ exports.Suite = require('./suite');
861
+ exports.Hook = require('./hook');
862
+ exports.Test = require('./test');
863
+
864
+ }); // module: mocha.js
865
+
866
+ require.register("reporters/base.js", function(module, exports, require){
867
+
868
+ /**
869
+ * Module dependencies.
870
+ */
871
+
872
+ var tty = require('browser/tty');
873
+
874
+ /**
875
+ * Check if both stdio streams are associated with a tty.
876
+ */
877
+
878
+ var isatty = tty.isatty(1) && tty.isatty(2);
879
+
880
+ /**
881
+ * Expose `Base`.
882
+ */
883
+
884
+ exports = module.exports = Base;
885
+
886
+ /**
887
+ * Enable coloring by default.
888
+ */
889
+
890
+ exports.useColors = isatty;
891
+
892
+ /**
893
+ * Default color map.
894
+ */
895
+
896
+ exports.colors = {
897
+ 'pass': 90
898
+ , 'fail': 31
899
+ , 'bright pass': 92
900
+ , 'bright fail': 91
901
+ , 'bright yellow': 93
902
+ , 'pending': 36
903
+ , 'suite': 0
904
+ , 'error title': 0
905
+ , 'error message': 31
906
+ , 'error stack': 90
907
+ , 'checkmark': 32
908
+ , 'fast': 90
909
+ , 'medium': 33
910
+ , 'slow': 31
911
+ , 'green': 32
912
+ , 'light': 90
913
+ };
914
+
915
+ /**
916
+ * Color `str` with the given `type`,
917
+ * allowing colors to be disabled,
918
+ * as well as user-defined color
919
+ * schemes.
920
+ *
921
+ * @param {String} type
922
+ * @param {String} str
923
+ * @return {String}
924
+ * @api private
925
+ */
926
+
927
+ var color = exports.color = function(type, str) {
928
+ if (!exports.useColors) return str;
929
+ return '\033[' + exports.colors[type] + 'm' + str + '\033[0m';
930
+ };
931
+
932
+ /**
933
+ * Expose term window size, with some
934
+ * defaults for when stderr is not a tty.
935
+ */
936
+
937
+ exports.window = {
938
+ width: isatty
939
+ ? process.stdout.getWindowSize
940
+ ? process.stdout.getWindowSize(1)[0]
941
+ : tty.getWindowSize()[1]
942
+ : 75
943
+ };
944
+
945
+ /**
946
+ * Expose some basic cursor interactions
947
+ * that are common among reporters.
948
+ */
949
+
950
+ exports.cursor = {
951
+ hide: function(){
952
+ process.stdout.write('\033[?25l');
953
+ },
954
+
955
+ show: function(){
956
+ process.stdout.write('\033[?25h');
957
+ },
958
+
959
+ deleteLine: function(){
960
+ process.stdout.write('\033[2K');
961
+ },
962
+
963
+ beginningOfLine: function(){
964
+ process.stdout.write('\033[0G');
965
+ },
966
+
967
+ CR: function(){
968
+ exports.cursor.deleteLine();
969
+ exports.cursor.beginningOfLine();
970
+ }
971
+ };
972
+
973
+ /**
974
+ * A test is considered slow if it
975
+ * exceeds the following value in milliseconds.
976
+ */
977
+
978
+ exports.slow = 75;
979
+
980
+ /**
981
+ * Outut the given `failures` as a list.
982
+ *
983
+ * @param {Array} failures
984
+ * @api public
985
+ */
986
+
987
+ exports.list = function(failures){
988
+ console.error();
989
+ failures.forEach(function(test, i){
990
+ // format
991
+ var fmt = color('error title', ' %s) %s:\n')
992
+ + color('error message', ' %s')
993
+ + color('error stack', '\n%s\n');
994
+
995
+ // msg
996
+ var err = test.err
997
+ , message = err.message || ''
998
+ , stack = err.stack || message
999
+ , index = stack.indexOf(message) + message.length
1000
+ , msg = stack.slice(0, index);
1001
+
1002
+ // indent stack trace without msg
1003
+ stack = stack.slice(index + 1)
1004
+ .replace(/^/gm, ' ');
1005
+
1006
+ console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
1007
+ });
1008
+ };
1009
+
1010
+ /**
1011
+ * Initialize a new `Base` reporter.
1012
+ *
1013
+ * All other reporters generally
1014
+ * inherit from this reporter, providing
1015
+ * stats such as test duration, number
1016
+ * of tests passed / failed etc.
1017
+ *
1018
+ * @param {Runner} runner
1019
+ * @api public
1020
+ */
1021
+
1022
+ function Base(runner) {
1023
+ var self = this
1024
+ , stats = this.stats = { suites: 0, tests: 0, passes: 0, failures: 0 }
1025
+ , failures = this.failures = [];
1026
+
1027
+ if (!runner) return;
1028
+ this.runner = runner;
1029
+
1030
+ runner.on('start', function(){
1031
+ stats.start = new Date;
1032
+ });
1033
+
1034
+ runner.on('suite', function(suite){
1035
+ stats.suites = stats.suites || 0;
1036
+ suite.root || stats.suites++;
1037
+ });
1038
+
1039
+ runner.on('test end', function(test){
1040
+ stats.tests = stats.tests || 0;
1041
+ stats.tests++;
1042
+ });
1043
+
1044
+ runner.on('pass', function(test){
1045
+ stats.passes = stats.passes || 0;
1046
+
1047
+ var medium = exports.slow / 2;
1048
+ test.speed = test.duration > exports.slow
1049
+ ? 'slow'
1050
+ : test.duration > medium
1051
+ ? 'medium'
1052
+ : 'fast';
1053
+
1054
+ stats.passes++;
1055
+ });
1056
+
1057
+ runner.on('fail', function(test, err){
1058
+ stats.failures = stats.failures || 0;
1059
+ stats.failures++;
1060
+ test.err = err;
1061
+ failures.push(test);
1062
+ });
1063
+
1064
+ runner.on('end', function(){
1065
+ stats.end = new Date;
1066
+ stats.duration = new Date - stats.start;
1067
+ });
1068
+ }
1069
+
1070
+ /**
1071
+ * Output common epilogue used by many of
1072
+ * the bundled reporters.
1073
+ *
1074
+ * @api public
1075
+ */
1076
+
1077
+ Base.prototype.epilogue = function(){
1078
+ var stats = this.stats
1079
+ , fmt;
1080
+
1081
+ console.log();
1082
+
1083
+ // failure
1084
+ if (stats.failures) {
1085
+ fmt = color('bright fail', ' ✖')
1086
+ + color('fail', ' %d of %d tests failed')
1087
+ + color('light', ':')
1088
+
1089
+ console.error(fmt, stats.failures, this.runner.total);
1090
+ Base.list(this.failures);
1091
+ console.error();
1092
+ return;
1093
+ }
1094
+
1095
+ // pass
1096
+ fmt = color('bright pass', ' ✔')
1097
+ + color('green', ' %d tests complete')
1098
+ + color('light', ' (%dms)');
1099
+
1100
+ console.log(fmt, stats.tests || 0, stats.duration);
1101
+ console.log();
1102
+ };
1103
+
1104
+ }); // module: reporters/base.js
1105
+
1106
+ require.register("reporters/doc.js", function(module, exports, require){
1107
+
1108
+ /**
1109
+ * Module dependencies.
1110
+ */
1111
+
1112
+ var Base = require('./base')
1113
+ , utils = require('../utils');
1114
+
1115
+ /**
1116
+ * Expose `Doc`.
1117
+ */
1118
+
1119
+ exports = module.exports = Doc;
1120
+
1121
+ /**
1122
+ * Initialize a new `Doc` reporter.
1123
+ *
1124
+ * @param {Runner} runner
1125
+ * @api public
1126
+ */
1127
+
1128
+ function Doc(runner) {
1129
+ Base.call(this, runner);
1130
+
1131
+ var self = this
1132
+ , stats = this.stats
1133
+ , total = runner.total
1134
+ , indents = 2;
1135
+
1136
+ function indent() {
1137
+ return Array(indents).join(' ');
1138
+ }
1139
+
1140
+ runner.on('suite', function(suite){
1141
+ if (suite.root) return;
1142
+ ++indents;
1143
+ console.log('%s<section class="suite">', indent());
1144
+ ++indents;
1145
+ console.log('%s<h1>%s</h1>', indent(), suite.title);
1146
+ console.log('%s<dl>', indent());
1147
+ });
1148
+
1149
+ runner.on('suite end', function(suite){
1150
+ if (suite.root) return;
1151
+ console.log('%s</dl>', indent());
1152
+ --indents;
1153
+ console.log('%s</section>', indent());
1154
+ --indents;
1155
+ });
1156
+
1157
+ runner.on('pass', function(test){
1158
+ console.log('%s <dt>%s</dt>', indent(), test.title);
1159
+ var code = utils.escape(clean(test.fn.toString()));
1160
+ console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code);
1161
+ });
1162
+ }
1163
+
1164
+ /**
1165
+ * Strip the function definition from `str`,
1166
+ * and re-indent for pre whitespace.
1167
+ */
1168
+
1169
+ function clean(str) {
1170
+ str = str
1171
+ .replace(/^function *\(.*\) *{/, '')
1172
+ .replace(/\s+\}$/, '');
1173
+
1174
+ var spaces = str.match(/^\n?( *)/)[1].length
1175
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
1176
+
1177
+ str = str.replace(re, '');
1178
+
1179
+ return str;
1180
+ }
1181
+ }); // module: reporters/doc.js
1182
+
1183
+ require.register("reporters/dot.js", function(module, exports, require){
1184
+
1185
+ /**
1186
+ * Module dependencies.
1187
+ */
1188
+
1189
+ var Base = require('./base')
1190
+ , color = Base.color;
1191
+
1192
+ /**
1193
+ * Expose `Dot`.
1194
+ */
1195
+
1196
+ exports = module.exports = Dot;
1197
+
1198
+ /**
1199
+ * Initialize a new `Dot` matrix test reporter.
1200
+ *
1201
+ * @param {Runner} runner
1202
+ * @api public
1203
+ */
1204
+
1205
+ function Dot(runner) {
1206
+ Base.call(this, runner);
1207
+
1208
+ var self = this
1209
+ , stats = this.stats
1210
+ , width = Base.window.width * .75 | 0
1211
+ , n = 0;
1212
+
1213
+ runner.on('start', function(){
1214
+ process.stdout.write('\n ');
1215
+ });
1216
+
1217
+ runner.on('pending', function(test){
1218
+ process.stdout.write(color('pending', '.'));
1219
+ });
1220
+
1221
+ runner.on('pass', function(test){
1222
+ if (++n % width == 0) process.stdout.write('\n ');
1223
+ if ('slow' == test.speed) {
1224
+ process.stdout.write(color('bright yellow', '.'));
1225
+ } else {
1226
+ process.stdout.write(color(test.speed, '.'));
1227
+ }
1228
+ });
1229
+
1230
+ runner.on('fail', function(test, err){
1231
+ if (++n % width == 0) process.stdout.write('\n ');
1232
+ process.stdout.write(color('fail', '.'));
1233
+ });
1234
+
1235
+ runner.on('end', function(){
1236
+ console.log();
1237
+ self.epilogue();
1238
+ });
1239
+ }
1240
+
1241
+ /**
1242
+ * Inherit from `Base.prototype`.
1243
+ */
1244
+
1245
+ Dot.prototype = new Base;
1246
+ Dot.prototype.constructor = Dot;
1247
+
1248
+ }); // module: reporters/dot.js
1249
+
1250
+ require.register("reporters/html.js", function(module, exports, require){
1251
+
1252
+ /**
1253
+ * Module dependencies.
1254
+ */
1255
+
1256
+ var Base = require('./base')
1257
+ , utils = require('../utils')
1258
+ , Progress = require('../browser/progress')
1259
+ , escape = utils.escape;
1260
+
1261
+ /**
1262
+ * Expose `Doc`.
1263
+ */
1264
+
1265
+ exports = module.exports = HTML;
1266
+
1267
+ /**
1268
+ * Stats template.
1269
+ */
1270
+
1271
+ var statsTemplate = '<ul id="stats">'
1272
+ + '<li class="progress"><canvas width="40" height="40"></canvas></li>'
1273
+ + '<li class="passes">passes: <em>0</em></li>'
1274
+ + '<li class="failures">failures: <em>0</em></li>'
1275
+ + '<li class="duration">duration: <em>0</em>s</li>'
1276
+ + '</ul>';
1277
+
1278
+ /**
1279
+ * Initialize a new `Doc` reporter.
1280
+ *
1281
+ * @param {Runner} runner
1282
+ * @api public
1283
+ */
1284
+
1285
+ function HTML(runner) {
1286
+ Base.call(this, runner);
1287
+
1288
+ // TODO: clean up
1289
+
1290
+ var self = this
1291
+ , stats = this.stats
1292
+ , total = runner.total
1293
+ , root = $('#mocha')
1294
+ , stack = [root]
1295
+ , stat = $(statsTemplate).appendTo(root)
1296
+ , canvas = stat.find('canvas').get(0)
1297
+ , progress
1298
+ , ctx
1299
+
1300
+ if (canvas.getContext) {
1301
+ ctx = canvas.getContext('2d');
1302
+ progress = new Progress;
1303
+ }
1304
+
1305
+ if (!root.length) return error('#mocha div missing, add it to your document');
1306
+
1307
+ if (progress) progress.size(40);
1308
+
1309
+ runner.on('suite', function(suite){
1310
+ if (suite.root) return;
1311
+
1312
+ // suite
1313
+ var el = $('<div class="suite"><h1>' + suite.title + '</h1></div>');
1314
+
1315
+ // container
1316
+ stack[0].append(el);
1317
+ stack.unshift($('<div>'));
1318
+ el.append(stack[0]);
1319
+ });
1320
+
1321
+ runner.on('suite end', function(suite){
1322
+ if (suite.root) return;
1323
+ stack.shift();
1324
+ });
1325
+
1326
+ runner.on('fail', function(test, err){
1327
+ if (err.uncaught) runner.emit('test end', test);
1328
+ });
1329
+
1330
+ runner.on('test end', function(test){
1331
+ // TODO: add to stats
1332
+ var percent = stats.tests / total * 100 | 0;
1333
+
1334
+ if (progress) {
1335
+ progress.update(percent).draw(ctx);
1336
+ }
1337
+
1338
+ // update stats
1339
+ var ms = new Date - stats.start;
1340
+ stat.find('.passes em').text(stats.passes);
1341
+ stat.find('.failures em').text(stats.failures);
1342
+ stat.find('.duration em').text((ms / 1000).toFixed(2));
1343
+
1344
+ // test
1345
+ if (test.passed) {
1346
+ var el = $('<div class="test pass"><h2>' + escape(test.title) + '</h2></div>')
1347
+ } else if (test.pending) {
1348
+ var el = $('<div class="test pass pending"><h2>' + escape(test.title) + '</h2></div>')
1349
+ } else {
1350
+ var el = $('<div class="test fail"><h2>' + escape(test.title) + '</h2></div>');
1351
+ var str = test.err.stack || test.err;
1352
+
1353
+ // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
1354
+ // check for the result of the stringifying.
1355
+ if ('[object Error]' == str) str = test.err.message;
1356
+
1357
+ $('<pre class="error">' + escape(str) + '</pre>').appendTo(el);
1358
+ }
1359
+
1360
+ // toggle code
1361
+ el.find('h2').toggle(function(){
1362
+ pre && pre.slideDown('fast');
1363
+ }, function(){
1364
+ pre && pre.slideUp('fast');
1365
+ });
1366
+
1367
+ // code
1368
+ // TODO: defer
1369
+ if (!test.pending) {
1370
+ var code = escape(clean(test.fn.toString()));
1371
+ var pre = $('<pre><code>' + code + '</code></pre>');
1372
+ pre.appendTo(el).hide();
1373
+ }
1374
+ stack[0].append(el);
1375
+ });
1376
+ }
1377
+
1378
+ /**
1379
+ * Display error `msg`.
1380
+ */
1381
+
1382
+ function error(msg) {
1383
+ $('<div id="error">' + msg + '</div>').appendTo('body');
1384
+ }
1385
+
1386
+ /**
1387
+ * Strip the function definition from `str`,
1388
+ * and re-indent for pre whitespace.
1389
+ */
1390
+
1391
+ function clean(str) {
1392
+ str = str
1393
+ .replace(/^function *\(.*\) *{/, '')
1394
+ .replace(/\s+\}$/, '');
1395
+
1396
+ var spaces = str.match(/^\n?( *)/)[1].length
1397
+ , re = new RegExp('^ {' + spaces + '}', 'gm');
1398
+
1399
+ str = str
1400
+ .replace(re, '')
1401
+ .replace(/^\s+/, '');
1402
+
1403
+ return str;
1404
+ }
1405
+
1406
+ }); // module: reporters/html.js
1407
+
1408
+ require.register("reporters/index.js", function(module, exports, require){
1409
+
1410
+ exports.Base = require('./base');
1411
+ exports.Dot = require('./dot');
1412
+ exports.Doc = require('./doc');
1413
+ exports.TAP = require('./tap');
1414
+ exports.JSON = require('./json');
1415
+ exports.HTML = require('./html');
1416
+ exports.List = require('./list');
1417
+ exports.Spec = require('./spec');
1418
+ exports.Progress = require('./progress');
1419
+ exports.Landing = require('./landing');
1420
+ exports.JSONStream = require('./json-stream');
1421
+ exports.XUnit = require('./xunit')
1422
+
1423
+ }); // module: reporters/index.js
1424
+
1425
+ require.register("reporters/json-stream.js", function(module, exports, require){
1426
+
1427
+ /**
1428
+ * Module dependencies.
1429
+ */
1430
+
1431
+ var Base = require('./base')
1432
+ , color = Base.color;
1433
+
1434
+ /**
1435
+ * Expose `List`.
1436
+ */
1437
+
1438
+ exports = module.exports = List;
1439
+
1440
+ /**
1441
+ * Initialize a new `List` test reporter.
1442
+ *
1443
+ * @param {Runner} runner
1444
+ * @api public
1445
+ */
1446
+
1447
+ function List(runner) {
1448
+ Base.call(this, runner);
1449
+
1450
+ var self = this
1451
+ , stats = this.stats
1452
+ , total = runner.total;
1453
+
1454
+ runner.on('start', function(){
1455
+ console.log(JSON.stringify(['start', { total: total }]));
1456
+ });
1457
+
1458
+ runner.on('pass', function(test){
1459
+ console.log(JSON.stringify(['pass', clean(test)]));
1460
+ });
1461
+
1462
+ runner.on('fail', function(test, err){
1463
+ console.log(JSON.stringify(['fail', clean(test)]));
1464
+ });
1465
+
1466
+ runner.on('end', function(){
1467
+ process.stdout.write(JSON.stringify(['end', self.stats]));
1468
+ });
1469
+ }
1470
+
1471
+ /**
1472
+ * Return a plain-object representation of `test`
1473
+ * free of cyclic properties etc.
1474
+ *
1475
+ * @param {Object} test
1476
+ * @return {Object}
1477
+ * @api private
1478
+ */
1479
+
1480
+ function clean(test) {
1481
+ return {
1482
+ title: test.title
1483
+ , fullTitle: test.fullTitle()
1484
+ , duration: test.duration
1485
+ }
1486
+ }
1487
+ }); // module: reporters/json-stream.js
1488
+
1489
+ require.register("reporters/json.js", function(module, exports, require){
1490
+
1491
+ /**
1492
+ * Module dependencies.
1493
+ */
1494
+
1495
+ var Base = require('./base')
1496
+ , cursor = Base.cursor
1497
+ , color = Base.color;
1498
+
1499
+ /**
1500
+ * Expose `JSON`.
1501
+ */
1502
+
1503
+ exports = module.exports = JSONReporter;
1504
+
1505
+ /**
1506
+ * Initialize a new `JSON` reporter.
1507
+ *
1508
+ * @param {Runner} runner
1509
+ * @api public
1510
+ */
1511
+
1512
+ function JSONReporter(runner) {
1513
+ var self = this;
1514
+ Base.call(this, runner);
1515
+
1516
+ var tests = []
1517
+ , failures = []
1518
+ , passes = [];
1519
+
1520
+ runner.on('test end', function(test){
1521
+ tests.push(test);
1522
+ });
1523
+
1524
+ runner.on('pass', function(test){
1525
+ passes.push(test);
1526
+ });
1527
+
1528
+ runner.on('fail', function(test){
1529
+ failures.push(test);
1530
+ });
1531
+
1532
+ runner.on('end', function(){
1533
+ var obj = {
1534
+ stats: self.stats
1535
+ , tests: tests.map(clean)
1536
+ , failures: failures.map(clean)
1537
+ , passes: passes.map(clean)
1538
+ };
1539
+
1540
+ process.stdout.write(JSON.stringify(obj));
1541
+ });
1542
+ }
1543
+
1544
+ /**
1545
+ * Return a plain-object representation of `test`
1546
+ * free of cyclic properties etc.
1547
+ *
1548
+ * @param {Object} test
1549
+ * @return {Object}
1550
+ * @api private
1551
+ */
1552
+
1553
+ function clean(test) {
1554
+ return {
1555
+ title: test.title
1556
+ , fullTitle: test.fullTitle()
1557
+ , duration: test.duration
1558
+ }
1559
+ }
1560
+ }); // module: reporters/json.js
1561
+
1562
+ require.register("reporters/landing.js", function(module, exports, require){
1563
+
1564
+ /**
1565
+ * Module dependencies.
1566
+ */
1567
+
1568
+ var Base = require('./base')
1569
+ , cursor = Base.cursor
1570
+ , color = Base.color;
1571
+
1572
+ /**
1573
+ * Expose `Landing`.
1574
+ */
1575
+
1576
+ exports = module.exports = Landing;
1577
+
1578
+ /**
1579
+ * Airplane color.
1580
+ */
1581
+
1582
+ Base.colors.plane = 0;
1583
+
1584
+ /**
1585
+ * Airplane crash color.
1586
+ */
1587
+
1588
+ Base.colors['plane crash'] = 31;
1589
+
1590
+ /**
1591
+ * Runway color.
1592
+ */
1593
+
1594
+ Base.colors.runway = 90;
1595
+
1596
+ /**
1597
+ * Initialize a new `Landing` reporter.
1598
+ *
1599
+ * @param {Runner} runner
1600
+ * @api public
1601
+ */
1602
+
1603
+ function Landing(runner) {
1604
+ Base.call(this, runner);
1605
+
1606
+ var self = this
1607
+ , stats = this.stats
1608
+ , width = Base.window.width * .75 | 0
1609
+ , total = runner.total
1610
+ , stream = process.stdout
1611
+ , plane = color('plane', '✈')
1612
+ , crashed = -1
1613
+ , n = 0;
1614
+
1615
+ function runway() {
1616
+ var buf = Array(width).join('-');
1617
+ return ' ' + color('runway', buf);
1618
+ }
1619
+
1620
+ runner.on('start', function(){
1621
+ stream.write('\n ');
1622
+ cursor.hide();
1623
+ });
1624
+
1625
+ runner.on('test end', function(test){
1626
+ // check if the plane crashed
1627
+ var col = -1 == crashed
1628
+ ? width * ++n / total | 0
1629
+ : crashed;
1630
+
1631
+ // show the crash
1632
+ if (test.failed) {
1633
+ plane = color('plane crash', '✈');
1634
+ crashed = col;
1635
+ }
1636
+
1637
+ // render landing strip
1638
+ stream.write('\033[4F\n\n');
1639
+ stream.write(runway());
1640
+ stream.write('\n ');
1641
+ stream.write(color('runway', Array(col).join('⋅')));
1642
+ stream.write(plane)
1643
+ stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
1644
+ stream.write(runway());
1645
+ stream.write('\033[0m');
1646
+ });
1647
+
1648
+ runner.on('end', function(){
1649
+ cursor.show();
1650
+ console.log();
1651
+ self.epilogue();
1652
+ });
1653
+ }
1654
+
1655
+ /**
1656
+ * Inherit from `Base.prototype`.
1657
+ */
1658
+
1659
+ Landing.prototype = new Base;
1660
+ Landing.prototype.constructor = Landing;
1661
+
1662
+ }); // module: reporters/landing.js
1663
+
1664
+ require.register("reporters/list.js", function(module, exports, require){
1665
+
1666
+ /**
1667
+ * Module dependencies.
1668
+ */
1669
+
1670
+ var Base = require('./base')
1671
+ , cursor = Base.cursor
1672
+ , color = Base.color;
1673
+
1674
+ /**
1675
+ * Expose `List`.
1676
+ */
1677
+
1678
+ exports = module.exports = List;
1679
+
1680
+ /**
1681
+ * Initialize a new `List` test reporter.
1682
+ *
1683
+ * @param {Runner} runner
1684
+ * @api public
1685
+ */
1686
+
1687
+ function List(runner) {
1688
+ Base.call(this, runner);
1689
+
1690
+ var self = this
1691
+ , stats = this.stats
1692
+ , n = 0;
1693
+
1694
+ runner.on('start', function(){
1695
+ console.log();
1696
+ });
1697
+
1698
+ runner.on('test', function(test){
1699
+ process.stdout.write(color('pass', ' ' + test.fullTitle() + ': '));
1700
+ });
1701
+
1702
+ runner.on('pending', function(test){
1703
+ var fmt = color('checkmark', ' -')
1704
+ + color('pending', ' %s');
1705
+ console.log(fmt, test.fullTitle());
1706
+ });
1707
+
1708
+ runner.on('pass', function(test){
1709
+ var fmt = color('checkmark', ' ✓')
1710
+ + color('pass', ' %s: ')
1711
+ + color(test.speed, '%dms');
1712
+ cursor.CR();
1713
+ console.log(fmt, test.fullTitle(), test.duration);
1714
+ });
1715
+
1716
+ runner.on('fail', function(test, err){
1717
+ cursor.CR();
1718
+ console.log(color('fail', ' %d) %s'), ++n, test.fullTitle());
1719
+ });
1720
+
1721
+ runner.on('end', self.epilogue.bind(self));
1722
+ }
1723
+
1724
+ /**
1725
+ * Inherit from `Base.prototype`.
1726
+ */
1727
+
1728
+ List.prototype = new Base;
1729
+ List.prototype.constructor = List;
1730
+
1731
+
1732
+ }); // module: reporters/list.js
1733
+
1734
+ require.register("reporters/progress.js", function(module, exports, require){
1735
+
1736
+ /**
1737
+ * Module dependencies.
1738
+ */
1739
+
1740
+ var Base = require('./base')
1741
+ , cursor = Base.cursor
1742
+ , color = Base.color;
1743
+
1744
+ /**
1745
+ * Expose `Progress`.
1746
+ */
1747
+
1748
+ exports = module.exports = Progress;
1749
+
1750
+ /**
1751
+ * General progress bar color.
1752
+ */
1753
+
1754
+ Base.colors.progress = 90;
1755
+
1756
+ /**
1757
+ * Initialize a new `Progress` bar test reporter.
1758
+ *
1759
+ * @param {Runner} runner
1760
+ * @param {Object} options
1761
+ * @api public
1762
+ */
1763
+
1764
+ function Progress(runner, options) {
1765
+ Base.call(this, runner);
1766
+
1767
+ var self = this
1768
+ , options = options || {}
1769
+ , stats = this.stats
1770
+ , width = Base.window.width * .50 | 0
1771
+ , total = runner.total
1772
+ , complete = 0
1773
+ , max = Math.max;
1774
+
1775
+ // default chars
1776
+ options.open = options.open || '[';
1777
+ options.complete = options.complete || '▬';
1778
+ options.incomplete = options.incomplete || '⋅';
1779
+ options.close = options.close || ']';
1780
+ options.verbose = false;
1781
+
1782
+ // tests started
1783
+ runner.on('start', function(){
1784
+ console.log();
1785
+ cursor.hide();
1786
+ });
1787
+
1788
+ // tests complete
1789
+ runner.on('test end', function(){
1790
+ var incomplete = total - complete
1791
+ , percent = complete++ / total
1792
+ , n = width * percent | 0
1793
+ , i = width - n;
1794
+
1795
+ cursor.CR();
1796
+ process.stdout.write('\033[J');
1797
+ process.stdout.write(color('progress', ' ' + options.open));
1798
+ process.stdout.write(Array(n).join(options.complete));
1799
+ process.stdout.write(Array(i).join(options.incomplete));
1800
+ process.stdout.write(color('progress', options.close));
1801
+ if (options.verbose) {
1802
+ process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
1803
+ }
1804
+ });
1805
+
1806
+ // tests are complete, output some stats
1807
+ // and the failures if any
1808
+ runner.on('end', function(){
1809
+ cursor.show();
1810
+ console.log();
1811
+ self.epilogue();
1812
+ });
1813
+ }
1814
+
1815
+ /**
1816
+ * Inherit from `Base.prototype`.
1817
+ */
1818
+
1819
+ Progress.prototype = new Base;
1820
+ Progress.prototype.constructor = Progress;
1821
+
1822
+
1823
+ }); // module: reporters/progress.js
1824
+
1825
+ require.register("reporters/spec.js", function(module, exports, require){
1826
+
1827
+ /**
1828
+ * Module dependencies.
1829
+ */
1830
+
1831
+ var Base = require('./base')
1832
+ , cursor = Base.cursor
1833
+ , color = Base.color;
1834
+
1835
+ /**
1836
+ * Expose `Spec`.
1837
+ */
1838
+
1839
+ exports = module.exports = Spec;
1840
+
1841
+ /**
1842
+ * Initialize a new `Spec` test reporter.
1843
+ *
1844
+ * @param {Runner} runner
1845
+ * @api public
1846
+ */
1847
+
1848
+ function Spec(runner) {
1849
+ Base.call(this, runner);
1850
+
1851
+ var self = this
1852
+ , stats = this.stats
1853
+ , indents = 0
1854
+ , n = 0;
1855
+
1856
+ function indent() {
1857
+ return Array(indents).join(' ')
1858
+ }
1859
+
1860
+ runner.on('start', function(){
1861
+ console.log();
1862
+ });
1863
+
1864
+ runner.on('suite', function(suite){
1865
+ ++indents;
1866
+ console.log(color('suite', '%s%s'), indent(), suite.title);
1867
+ });
1868
+
1869
+ runner.on('suite end', function(suite){
1870
+ --indents;
1871
+ if (1 == indents) console.log();
1872
+ });
1873
+
1874
+ runner.on('test', function(test){
1875
+ process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': '));
1876
+ });
1877
+
1878
+ runner.on('pending', function(test){
1879
+ var fmt = indent() + color('pending', ' - %s');
1880
+ console.log(fmt, test.title);
1881
+ });
1882
+
1883
+ runner.on('pass', function(test){
1884
+ if ('fast' == test.speed) {
1885
+ var fmt = indent()
1886
+ + color('checkmark', ' ✓')
1887
+ + color('pass', ' %s ');
1888
+ cursor.CR();
1889
+ console.log(fmt, test.title);
1890
+ } else {
1891
+ var fmt = indent()
1892
+ + color('checkmark', ' ✓')
1893
+ + color('pass', ' %s ')
1894
+ + color(test.speed, '(%dms)');
1895
+ cursor.CR();
1896
+ console.log(fmt, test.title, test.duration);
1897
+ }
1898
+ });
1899
+
1900
+ runner.on('fail', function(test, err){
1901
+ cursor.CR();
1902
+ console.log(indent() + color('fail', ' %d) %s'), ++n, test.title);
1903
+ });
1904
+
1905
+ runner.on('end', self.epilogue.bind(self));
1906
+ }
1907
+
1908
+ /**
1909
+ * Inherit from `Base.prototype`.
1910
+ */
1911
+
1912
+ Spec.prototype = new Base;
1913
+ Spec.prototype.constructor = Spec;
1914
+
1915
+
1916
+ }); // module: reporters/spec.js
1917
+
1918
+ require.register("reporters/tap.js", function(module, exports, require){
1919
+
1920
+ /**
1921
+ * Module dependencies.
1922
+ */
1923
+
1924
+ var Base = require('./base')
1925
+ , cursor = Base.cursor
1926
+ , color = Base.color;
1927
+
1928
+ /**
1929
+ * Expose `TAP`.
1930
+ */
1931
+
1932
+ exports = module.exports = TAP;
1933
+
1934
+ /**
1935
+ * Initialize a new `TAP` reporter.
1936
+ *
1937
+ * @param {Runner} runner
1938
+ * @api public
1939
+ */
1940
+
1941
+ function TAP(runner) {
1942
+ Base.call(this, runner);
1943
+
1944
+ var self = this
1945
+ , stats = this.stats
1946
+ , total = runner.total
1947
+ , n = 1;
1948
+
1949
+ runner.on('start', function(){
1950
+ console.log('%d..%d', 1, total);
1951
+ });
1952
+
1953
+ runner.on('test end', function(){
1954
+ ++n;
1955
+ });
1956
+
1957
+ runner.on('pending', function(test){
1958
+ console.log('ok %d %s # SKIP -', n, title(test));
1959
+ });
1960
+
1961
+ runner.on('pass', function(test){
1962
+ console.log('ok %d %s', n, title(test));
1963
+ });
1964
+
1965
+ runner.on('fail', function(test, err){
1966
+ console.log('not ok %d %s', n, title(test));
1967
+ console.log(err.stack.replace(/^/gm, ' '));
1968
+ });
1969
+ }
1970
+
1971
+ /**
1972
+ * Return a TAP-safe title of `test`
1973
+ *
1974
+ * @param {Object} test
1975
+ * @return {String}
1976
+ * @api private
1977
+ */
1978
+
1979
+ function title(test) {
1980
+ return test.fullTitle().replace(/#/g, '');
1981
+ }
1982
+
1983
+ }); // module: reporters/tap.js
1984
+
1985
+ require.register("reporters/teamcity.js", function(module, exports, require){
1986
+
1987
+ /**
1988
+ * Module dependencies.
1989
+ */
1990
+
1991
+ var Base = require('./base');
1992
+
1993
+ /**
1994
+ * Expose `Teamcity`.
1995
+ */
1996
+
1997
+ exports = module.exports = Teamcity;
1998
+
1999
+ /**
2000
+ * Initialize a new `Teamcity` reporter.
2001
+ *
2002
+ * @param {Runner} runner
2003
+ * @api public
2004
+ */
2005
+
2006
+ function Teamcity(runner) {
2007
+ Base.call(this, runner);
2008
+ var stats = this.stats;
2009
+
2010
+ runner.on('start', function() {
2011
+ console.log("##teamcity[testSuiteStarted name='mocha.suite']");
2012
+ });
2013
+
2014
+ runner.on('test', function(test) {
2015
+ console.log("##teamcity[testStarted name='%s']", escape(test.fullTitle()));
2016
+ });
2017
+
2018
+ runner.on('fail', function(test, err) {
2019
+ console.log("##teamcity[testFailed name='%s' message='%s']", escape(test.fullTitle()), escape(err.message));
2020
+ });
2021
+
2022
+ runner.on('pending', function(test) {
2023
+ console.log("##teamcity[testIgnored name='%s' message='pending']", escape(test.fullTitle()));
2024
+ });
2025
+
2026
+ runner.on('test end', function(test) {
2027
+ console.log("##teamcity[testFinished name='%s' duration='%s']", escape(test.fullTitle()), test.duration);
2028
+ });
2029
+
2030
+ runner.on('end', function() {
2031
+ console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='%s']", stats.duration);
2032
+ });
2033
+ }
2034
+
2035
+ /**
2036
+ * Escape the given `str`.
2037
+ */
2038
+
2039
+ function escape(str) {
2040
+ return str.replace(/'/g, "|'");
2041
+ }
2042
+ }); // module: reporters/teamcity.js
2043
+
2044
+ require.register("reporters/xunit.js", function(module, exports, require){
2045
+
2046
+ /**
2047
+ * Module dependencies.
2048
+ */
2049
+
2050
+ var Base = require('./base')
2051
+ , utils = require('../utils')
2052
+ , escape = utils.escape;
2053
+
2054
+ /**
2055
+ * Expose `XUnit`.
2056
+ */
2057
+
2058
+ exports = module.exports = XUnit;
2059
+
2060
+ /**
2061
+ * Initialize a new `XUnit` reporter.
2062
+ *
2063
+ * @param {Runner} runner
2064
+ * @api public
2065
+ */
2066
+
2067
+ function XUnit(runner) {
2068
+ Base.call(this, runner);
2069
+ var stats = this.stats
2070
+ , tests = []
2071
+ , self = this;
2072
+
2073
+ runner.on('test end', function(test){
2074
+ tests.push(test);
2075
+ });
2076
+
2077
+ runner.on('end', function(){
2078
+ console.log(tag('testsuite', {
2079
+ name: 'Mocha Tests'
2080
+ , tests: stats.tests
2081
+ , failures: stats.failures
2082
+ , errors: stats.failures
2083
+ , skip: stats.tests - stats.failures - stats.passes
2084
+ , timestamp: (new Date).toUTCString()
2085
+ , time: stats.duration / 1000
2086
+ }, false));
2087
+
2088
+ tests.forEach(test);
2089
+ console.log('</testsuite>');
2090
+ });
2091
+ }
2092
+
2093
+ /**
2094
+ * Inherit from `Base.prototype`.
2095
+ */
2096
+
2097
+ XUnit.prototype = new Base;
2098
+ XUnit.prototype.constructor = XUnit;
2099
+
2100
+
2101
+ /**
2102
+ * Output tag for the given `test.`
2103
+ */
2104
+
2105
+ function test(test) {
2106
+ var attrs = {
2107
+ classname: test.parent.fullTitle()
2108
+ , name: test.title
2109
+ , time: test.duration / 1000
2110
+ };
2111
+
2112
+ if (test.failed) {
2113
+ var err = test.err;
2114
+ attrs.message = escape(err.message);
2115
+ console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
2116
+ } else if (test.pending) {
2117
+ console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
2118
+ } else {
2119
+ console.log(tag('testcase', attrs, true) );
2120
+ }
2121
+ }
2122
+
2123
+ /**
2124
+ * HTML tag helper.
2125
+ */
2126
+
2127
+ function tag(name, attrs, close, content) {
2128
+ var end = close ? '/>' : '>'
2129
+ , pairs = []
2130
+ , tag;
2131
+
2132
+ for (var key in attrs) {
2133
+ pairs.push(key + '="' + escape(attrs[key]) + '"');
2134
+ }
2135
+
2136
+ tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
2137
+ if (content) tag += content + '</' + name + end;
2138
+ return tag;
2139
+ }
2140
+
2141
+ /**
2142
+ * Return cdata escaped CDATA `str`.
2143
+ */
2144
+
2145
+ function cdata(str) {
2146
+ return '<![CDATA[' + escape(str) + ']]>';
2147
+ }
2148
+
2149
+ }); // module: reporters/xunit.js
2150
+
2151
+ require.register("runnable.js", function(module, exports, require){
2152
+
2153
+ /**
2154
+ * Module dependencies.
2155
+ */
2156
+
2157
+ var EventEmitter = require('browser/events').EventEmitter
2158
+ , debug = require('browser/debug')('runnable');
2159
+
2160
+ /**
2161
+ * Expose `Runnable`.
2162
+ */
2163
+
2164
+ module.exports = Runnable;
2165
+
2166
+ /**
2167
+ * Initialize a new `Runnable` with the given `title` and callback `fn`.
2168
+ *
2169
+ * @param {String} title
2170
+ * @param {Function} fn
2171
+ * @api private
2172
+ */
2173
+
2174
+ function Runnable(title, fn) {
2175
+ this.title = title;
2176
+ this.fn = fn;
2177
+ this.async = fn && fn.length;
2178
+ this.sync = ! this.async;
2179
+ this._timeout = 2000;
2180
+ this.timedOut = false;
2181
+ }
2182
+
2183
+ /**
2184
+ * Inherit from `EventEmitter.prototype`.
2185
+ */
2186
+
2187
+ Runnable.prototype = new EventEmitter;
2188
+ Runnable.prototype.constructor = Runnable;
2189
+
2190
+
2191
+ /**
2192
+ * Set & get timeout `ms`.
2193
+ *
2194
+ * @param {Number} ms
2195
+ * @return {Runnable|Number} ms or self
2196
+ * @api private
2197
+ */
2198
+
2199
+ Runnable.prototype.timeout = function(ms){
2200
+ if (0 == arguments.length) return this._timeout;
2201
+ debug('timeout %d', ms);
2202
+ this._timeout = ms;
2203
+ if (this.timer) this.resetTimeout();
2204
+ return this;
2205
+ };
2206
+
2207
+ /**
2208
+ * Return the full title generated by recursively
2209
+ * concatenating the parent's full title.
2210
+ *
2211
+ * @return {String}
2212
+ * @api public
2213
+ */
2214
+
2215
+ Runnable.prototype.fullTitle = function(){
2216
+ return this.parent.fullTitle() + ' ' + this.title;
2217
+ };
2218
+
2219
+ /**
2220
+ * Clear the timeout.
2221
+ *
2222
+ * @api private
2223
+ */
2224
+
2225
+ Runnable.prototype.clearTimeout = function(){
2226
+ clearTimeout(this.timer);
2227
+ };
2228
+
2229
+ /**
2230
+ * Reset the timeout.
2231
+ *
2232
+ * @api private
2233
+ */
2234
+
2235
+ Runnable.prototype.resetTimeout = function(){
2236
+ var self = this
2237
+ , ms = this.timeout();
2238
+
2239
+ this.clearTimeout();
2240
+ if (ms) {
2241
+ this.timer = setTimeout(function(){
2242
+ self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
2243
+ self.timedOut = true;
2244
+ }, ms);
2245
+ }
2246
+ };
2247
+
2248
+ /**
2249
+ * Run the test and invoke `fn(err)`.
2250
+ *
2251
+ * @param {Function} fn
2252
+ * @api private
2253
+ */
2254
+
2255
+ Runnable.prototype.run = function(fn){
2256
+ var self = this
2257
+ , ms = this.timeout()
2258
+ , start = new Date
2259
+ , ctx = this.ctx
2260
+ , finished
2261
+ , emitted;
2262
+
2263
+ // timeout
2264
+ if (this.async) {
2265
+ if (ms) {
2266
+ this.timer = setTimeout(function(){
2267
+ done(new Error('timeout of ' + ms + 'ms exceeded'));
2268
+ self.timedOut = true;
2269
+ }, ms);
2270
+ }
2271
+ }
2272
+
2273
+ // called multiple times
2274
+ function multiple() {
2275
+ if (emitted) return;
2276
+ emitted = true;
2277
+ self.emit('error', new Error('done() called multiple times'));
2278
+ }
2279
+
2280
+ // finished
2281
+ function done(err) {
2282
+ if (self.timedOut) return;
2283
+ if (finished) return multiple();
2284
+ self.clearTimeout();
2285
+ self.duration = new Date - start;
2286
+ finished = true;
2287
+ fn(err);
2288
+ }
2289
+
2290
+ // for .resetTimeout()
2291
+ this.callback = done;
2292
+
2293
+ // async
2294
+ if (this.async) {
2295
+ try {
2296
+ this.fn.call(ctx, function(err){
2297
+ if (err instanceof Error) return done(err);
2298
+ if (null != err) return done(new Error('done() invoked with non-Error: ' + err));
2299
+ done();
2300
+ });
2301
+ } catch (err) {
2302
+ done(err);
2303
+ }
2304
+ return;
2305
+ }
2306
+
2307
+ // sync
2308
+ try {
2309
+ if (!this.pending) this.fn.call(ctx);
2310
+ this.duration = new Date - start;
2311
+ fn();
2312
+ } catch (err) {
2313
+ fn(err);
2314
+ }
2315
+ };
2316
+
2317
+ }); // module: runnable.js
2318
+
2319
+ require.register("runner.js", function(module, exports, require){
2320
+
2321
+ /**
2322
+ * Module dependencies.
2323
+ */
2324
+
2325
+ var EventEmitter = require('browser/events').EventEmitter
2326
+ , debug = require('browser/debug')('runner')
2327
+ , Test = require('./test')
2328
+ , utils = require('./utils')
2329
+ , noop = function(){};
2330
+
2331
+ /**
2332
+ * Expose `Runner`.
2333
+ */
2334
+
2335
+ module.exports = Runner;
2336
+
2337
+ /**
2338
+ * Initialize a `Runner` for the given `suite`.
2339
+ *
2340
+ * Events:
2341
+ *
2342
+ * - `start` execution started
2343
+ * - `end` execution complete
2344
+ * - `suite` (suite) test suite execution started
2345
+ * - `suite end` (suite) all tests (and sub-suites) have finished
2346
+ * - `test` (test) test execution started
2347
+ * - `test end` (test) test completed
2348
+ * - `hook` (hook) hook execution started
2349
+ * - `hook end` (hook) hook complete
2350
+ * - `pass` (test) test passed
2351
+ * - `fail` (test, err) test failed
2352
+ *
2353
+ * @api public
2354
+ */
2355
+
2356
+ function Runner(suite) {
2357
+ var self = this;
2358
+ this._globals = [];
2359
+ this.suite = suite;
2360
+ this.total = suite.total();
2361
+ this.failures = 0;
2362
+ this.on('test end', function(test){ self.checkGlobals(test); });
2363
+ this.on('hook end', function(hook){ self.checkGlobals(hook); });
2364
+ this.grep(/.*/);
2365
+ this.globals(utils.keys(global).concat(['errno']));
2366
+ }
2367
+
2368
+ /**
2369
+ * Inherit from `EventEmitter.prototype`.
2370
+ */
2371
+
2372
+ Runner.prototype = new EventEmitter;
2373
+ Runner.prototype.constructor = Runner;
2374
+
2375
+
2376
+ /**
2377
+ * Run tests with full titles matching `re`.
2378
+ *
2379
+ * @param {RegExp} re
2380
+ * @return {Runner} for chaining
2381
+ * @api public
2382
+ */
2383
+
2384
+ Runner.prototype.grep = function(re){
2385
+ debug('grep %s', re);
2386
+ this._grep = re;
2387
+ return this;
2388
+ };
2389
+
2390
+ /**
2391
+ * Allow the given `arr` of globals.
2392
+ *
2393
+ * @param {Array} arr
2394
+ * @return {Runner} for chaining
2395
+ * @api public
2396
+ */
2397
+
2398
+ Runner.prototype.globals = function(arr){
2399
+ if (0 == arguments.length) return this._globals;
2400
+ debug('globals %j', arr);
2401
+ utils.forEach(arr, function(arr){
2402
+ this._globals.push(arr);
2403
+ }, this);
2404
+ return this;
2405
+ };
2406
+
2407
+ /**
2408
+ * Check for global variable leaks.
2409
+ *
2410
+ * @api private
2411
+ */
2412
+
2413
+ Runner.prototype.checkGlobals = function(test){
2414
+ if (this.ignoreLeaks) return;
2415
+
2416
+ var leaks = utils.filter(utils.keys(global), function(key){
2417
+ return !~utils.indexOf(this._globals, key) && (!global.navigator || 'onerror' !== key);
2418
+ }, this);
2419
+
2420
+ this._globals = this._globals.concat(leaks);
2421
+
2422
+ if (leaks.length > 1) {
2423
+ this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
2424
+ } else if (leaks.length) {
2425
+ this.fail(test, new Error('global leak detected: ' + leaks[0]));
2426
+ }
2427
+ };
2428
+
2429
+ /**
2430
+ * Fail the given `test`.
2431
+ *
2432
+ * @param {Test} test
2433
+ * @param {Error} err
2434
+ * @api private
2435
+ */
2436
+
2437
+ Runner.prototype.fail = function(test, err){
2438
+ ++this.failures;
2439
+ test.failed = true;
2440
+ this.emit('fail', test, err);
2441
+ };
2442
+
2443
+ /**
2444
+ * Fail the given `hook` with `err`.
2445
+ *
2446
+ * Hook failures (currently) hard-end due
2447
+ * to that fact that a failing hook will
2448
+ * surely cause subsequent tests to fail,
2449
+ * causing jumbled reporting.
2450
+ *
2451
+ * @param {Hook} hook
2452
+ * @param {Error} err
2453
+ * @api private
2454
+ */
2455
+
2456
+ Runner.prototype.failHook = function(hook, err){
2457
+ this.fail(hook, err);
2458
+ this.emit('end');
2459
+ };
2460
+
2461
+ /**
2462
+ * Run hook `name` callbacks and then invoke `fn()`.
2463
+ *
2464
+ * @param {String} name
2465
+ * @param {Function} function
2466
+ * @api private
2467
+ */
2468
+
2469
+ Runner.prototype.hook = function(name, fn){
2470
+ var suite = this.suite
2471
+ , hooks = suite['_' + name]
2472
+ , ms = suite._timeout
2473
+ , self = this
2474
+ , timer;
2475
+
2476
+ function next(i) {
2477
+ var hook = hooks[i];
2478
+ if (!hook) return fn();
2479
+ self.currentRunnable = hook;
2480
+ hook.ctx.test(self.test);
2481
+
2482
+ self.emit('hook', hook);
2483
+
2484
+ hook.on('error', function(err){
2485
+ self.failHook(hook, err);
2486
+ });
2487
+
2488
+ hook.run(function(err){
2489
+ hook.removeAllListeners('error');
2490
+ if (err) return self.failHook(hook, err);
2491
+ self.emit('hook end', hook);
2492
+ next(++i);
2493
+ });
2494
+ }
2495
+
2496
+ process.nextTick(function(){
2497
+ next(0);
2498
+ });
2499
+ };
2500
+
2501
+ /**
2502
+ * Run hook `name` for the given array of `suites`
2503
+ * in order, and callback `fn(err)`.
2504
+ *
2505
+ * @param {String} name
2506
+ * @param {Array} suites
2507
+ * @param {Function} fn
2508
+ * @api private
2509
+ */
2510
+
2511
+ Runner.prototype.hooks = function(name, suites, fn){
2512
+ var self = this
2513
+ , orig = this.suite;
2514
+
2515
+ function next(suite) {
2516
+ self.suite = suite;
2517
+
2518
+ if (!suite) {
2519
+ self.suite = orig;
2520
+ return fn();
2521
+ }
2522
+
2523
+ self.hook(name, function(err){
2524
+ if (err) {
2525
+ self.suite = orig;
2526
+ return fn(err);
2527
+ }
2528
+
2529
+ next(suites.pop());
2530
+ });
2531
+ }
2532
+
2533
+ next(suites.pop());
2534
+ };
2535
+
2536
+ /**
2537
+ * Run hooks from the top level down.
2538
+ *
2539
+ * @param {String} name
2540
+ * @param {Function} fn
2541
+ * @api private
2542
+ */
2543
+
2544
+ Runner.prototype.hookUp = function(name, fn){
2545
+ var suites = [this.suite].concat(this.parents()).reverse();
2546
+ this.hooks(name, suites, fn);
2547
+ };
2548
+
2549
+ /**
2550
+ * Run hooks from the bottom up.
2551
+ *
2552
+ * @param {String} name
2553
+ * @param {Function} fn
2554
+ * @api private
2555
+ */
2556
+
2557
+ Runner.prototype.hookDown = function(name, fn){
2558
+ var suites = [this.suite].concat(this.parents());
2559
+ this.hooks(name, suites, fn);
2560
+ };
2561
+
2562
+ /**
2563
+ * Return an array of parent Suites from
2564
+ * closest to furthest.
2565
+ *
2566
+ * @return {Array}
2567
+ * @api private
2568
+ */
2569
+
2570
+ Runner.prototype.parents = function(){
2571
+ var suite = this.suite
2572
+ , suites = [];
2573
+ while (suite = suite.parent) suites.push(suite);
2574
+ return suites;
2575
+ };
2576
+
2577
+ /**
2578
+ * Run the current test and callback `fn(err)`.
2579
+ *
2580
+ * @param {Function} fn
2581
+ * @api private
2582
+ */
2583
+
2584
+ Runner.prototype.runTest = function(fn){
2585
+ var test = this.test
2586
+ , self = this;
2587
+
2588
+ try {
2589
+ test.ctx.test(test);
2590
+ test.on('error', function(err){
2591
+ self.fail(test, err);
2592
+ });
2593
+ test.run(fn);
2594
+ } catch (err) {
2595
+ fn(err);
2596
+ }
2597
+ };
2598
+
2599
+ /**
2600
+ * Run tests in the given `suite` and invoke
2601
+ * the callback `fn()` when complete.
2602
+ *
2603
+ * @param {Suite} suite
2604
+ * @param {Function} fn
2605
+ * @api private
2606
+ */
2607
+
2608
+ Runner.prototype.runTests = function(suite, fn){
2609
+ var self = this
2610
+ , tests = suite.tests
2611
+ , test;
2612
+
2613
+ function next(err) {
2614
+ // if we bail after first err
2615
+ if (self.failures && suite._bail) return fn();
2616
+
2617
+ // next test
2618
+ test = tests.shift();
2619
+
2620
+ // all done
2621
+ if (!test) return fn();
2622
+
2623
+ // grep
2624
+ if (!self._grep.test(test.fullTitle())) return next();
2625
+
2626
+ // pending
2627
+ if (test.pending) {
2628
+ self.emit('pending', test);
2629
+ self.emit('test end', test);
2630
+ return next();
2631
+ }
2632
+
2633
+ // execute test and hook(s)
2634
+ self.emit('test', self.test = test);
2635
+ self.hookDown('beforeEach', function(){
2636
+ self.currentRunnable = self.test;
2637
+ self.runTest(function(err){
2638
+ test = self.test;
2639
+
2640
+ if (err) {
2641
+ self.fail(test, err);
2642
+ self.emit('test end', test);
2643
+ return self.hookUp('afterEach', next);
2644
+ }
2645
+
2646
+ test.passed = true;
2647
+ self.emit('pass', test);
2648
+ self.emit('test end', test);
2649
+ self.hookUp('afterEach', next);
2650
+ });
2651
+ });
2652
+ }
2653
+
2654
+ this.next = next;
2655
+ next();
2656
+ };
2657
+
2658
+ /**
2659
+ * Run the given `suite` and invoke the
2660
+ * callback `fn()` when complete.
2661
+ *
2662
+ * @param {Suite} suite
2663
+ * @param {Function} fn
2664
+ * @api private
2665
+ */
2666
+
2667
+ Runner.prototype.runSuite = function(suite, fn){
2668
+ var self = this
2669
+ , i = 0;
2670
+
2671
+ debug('run suite %s', suite.fullTitle());
2672
+ this.emit('suite', this.suite = suite);
2673
+
2674
+ function next() {
2675
+ var curr = suite.suites[i++];
2676
+ if (!curr) return done();
2677
+ self.runSuite(curr, next);
2678
+ }
2679
+
2680
+ function done() {
2681
+ self.suite = suite;
2682
+ self.hook('afterAll', function(){
2683
+ self.emit('suite end', suite);
2684
+ fn();
2685
+ });
2686
+ }
2687
+
2688
+ this.hook('beforeAll', function(){
2689
+ self.runTests(suite, next);
2690
+ });
2691
+ };
2692
+
2693
+ /**
2694
+ * Handle uncaught exceptions.
2695
+ *
2696
+ * @param {Error} err
2697
+ * @api private
2698
+ */
2699
+
2700
+ Runner.prototype.uncaught = function(err){
2701
+ debug('uncaught exception');
2702
+ var runnable = this.currentRunnable;
2703
+ if (runnable.failed) return;
2704
+ runnable.clearTimeout();
2705
+ err.uncaught = true;
2706
+ this.fail(runnable, err);
2707
+
2708
+ // recover from test
2709
+ if ('test' == runnable.type) {
2710
+ this.emit('test end', runnable);
2711
+ this.hookUp('afterEach', this.next);
2712
+ return;
2713
+ }
2714
+
2715
+ // bail on hooks
2716
+ this.emit('end');
2717
+ };
2718
+
2719
+ /**
2720
+ * Run the root suite and invoke `fn(failures)`
2721
+ * on completion.
2722
+ *
2723
+ * @param {Function} fn
2724
+ * @return {Runner} for chaining
2725
+ * @api public
2726
+ */
2727
+
2728
+ Runner.prototype.run = function(fn){
2729
+ var self = this
2730
+ , fn = fn || function(){};
2731
+
2732
+ debug('start');
2733
+
2734
+ // callback
2735
+ this.on('end', function(){
2736
+ debug('end');
2737
+ process.removeListener('uncaughtException', this.uncaught);
2738
+ fn(self.failures);
2739
+ });
2740
+
2741
+ // run suites
2742
+ this.emit('start');
2743
+ this.runSuite(this.suite, function(){
2744
+ debug('finished running');
2745
+ self.emit('end');
2746
+ });
2747
+
2748
+ // uncaught exception
2749
+ process.on('uncaughtException', function(err){
2750
+ self.uncaught(err);
2751
+ });
2752
+
2753
+ return this;
2754
+ };
2755
+
2756
+ }); // module: runner.js
2757
+
2758
+ require.register("suite.js", function(module, exports, require){
2759
+
2760
+ /**
2761
+ * Module dependencies.
2762
+ */
2763
+
2764
+ var EventEmitter = require('browser/events').EventEmitter
2765
+ , debug = require('browser/debug')('suite')
2766
+ , utils = require('./utils')
2767
+ , Hook = require('./hook');
2768
+
2769
+ /**
2770
+ * Expose `Suite`.
2771
+ */
2772
+
2773
+ exports = module.exports = Suite;
2774
+
2775
+ /**
2776
+ * Create a new `Suite` with the given `title`
2777
+ * and parent `Suite`. When a suite with the
2778
+ * same title is already present, that suite
2779
+ * is returned to provide nicer reporter
2780
+ * and more flexible meta-testing.
2781
+ *
2782
+ * @param {Suite} parent
2783
+ * @param {String} title
2784
+ * @return {Suite}
2785
+ * @api public
2786
+ */
2787
+
2788
+ exports.create = function(parent, title){
2789
+ var suite = new Suite(title, parent.ctx);
2790
+ suite.parent = parent;
2791
+ title = suite.fullTitle();
2792
+ parent.addSuite(suite);
2793
+ return suite;
2794
+ };
2795
+
2796
+ /**
2797
+ * Initialize a new `Suite` with the given
2798
+ * `title` and `ctx`.
2799
+ *
2800
+ * @param {String} title
2801
+ * @param {Context} ctx
2802
+ * @api private
2803
+ */
2804
+
2805
+ function Suite(title, ctx) {
2806
+ this.title = title;
2807
+ this.ctx = ctx;
2808
+ this.suites = [];
2809
+ this.tests = [];
2810
+ this._beforeEach = [];
2811
+ this._beforeAll = [];
2812
+ this._afterEach = [];
2813
+ this._afterAll = [];
2814
+ this.root = !title;
2815
+ this._timeout = 2000;
2816
+ this._bail = false;
2817
+ }
2818
+
2819
+ /**
2820
+ * Inherit from `EventEmitter.prototype`.
2821
+ */
2822
+
2823
+ Suite.prototype = new EventEmitter;
2824
+ Suite.prototype.constructor = Suite;
2825
+
2826
+
2827
+ /**
2828
+ * Return a clone of this `Suite`.
2829
+ *
2830
+ * @return {Suite}
2831
+ * @api private
2832
+ */
2833
+
2834
+ Suite.prototype.clone = function(){
2835
+ var suite = new Suite(this.title);
2836
+ debug('clone');
2837
+ suite.timeout(this.timeout());
2838
+ suite.bail(this.bail());
2839
+ return suite;
2840
+ };
2841
+
2842
+ /**
2843
+ * Set timeout `ms` or short-hand such as "2s".
2844
+ *
2845
+ * @param {Number|String} ms
2846
+ * @return {Suite|Number} for chaining
2847
+ * @api private
2848
+ */
2849
+
2850
+ Suite.prototype.timeout = function(ms){
2851
+ if (0 == arguments.length) return this._timeout;
2852
+ if (String(ms).match(/s$/)) ms = parseFloat(ms) * 1000;
2853
+ debug('timeout %d', ms);
2854
+ this._timeout = parseInt(ms, 10);
2855
+ return this;
2856
+ };
2857
+
2858
+ /**
2859
+ * Sets whether to bail after first error.
2860
+ *
2861
+ * @parma {Boolean} bail
2862
+ * @return {Suite|Number} for chaining
2863
+ * @api private
2864
+ */
2865
+
2866
+ Suite.prototype.bail = function(bail){
2867
+ if (0 == arguments.length) return this._bail;
2868
+ debug('bail %s', bail);
2869
+ this._bail = bail;
2870
+ return this;
2871
+ };
2872
+
2873
+ /**
2874
+ * Run `fn(test[, done])` before running tests.
2875
+ *
2876
+ * @param {Function} fn
2877
+ * @return {Suite} for chaining
2878
+ * @api private
2879
+ */
2880
+
2881
+ Suite.prototype.beforeAll = function(fn){
2882
+ var hook = new Hook('"before all" hook', fn);
2883
+ hook.parent = this;
2884
+ hook.timeout(this.timeout());
2885
+ hook.ctx = this.ctx;
2886
+ this._beforeAll.push(hook);
2887
+ this.emit('beforeAll', hook);
2888
+ return this;
2889
+ };
2890
+
2891
+ /**
2892
+ * Run `fn(test[, done])` after running tests.
2893
+ *
2894
+ * @param {Function} fn
2895
+ * @return {Suite} for chaining
2896
+ * @api private
2897
+ */
2898
+
2899
+ Suite.prototype.afterAll = function(fn){
2900
+ var hook = new Hook('"after all" hook', fn);
2901
+ hook.parent = this;
2902
+ hook.timeout(this.timeout());
2903
+ hook.ctx = this.ctx;
2904
+ this._afterAll.push(hook);
2905
+ this.emit('afterAll', hook);
2906
+ return this;
2907
+ };
2908
+
2909
+ /**
2910
+ * Run `fn(test[, done])` before each test case.
2911
+ *
2912
+ * @param {Function} fn
2913
+ * @return {Suite} for chaining
2914
+ * @api private
2915
+ */
2916
+
2917
+ Suite.prototype.beforeEach = function(fn){
2918
+ var hook = new Hook('"before each" hook', fn);
2919
+ hook.parent = this;
2920
+ hook.timeout(this.timeout());
2921
+ hook.ctx = this.ctx;
2922
+ this._beforeEach.push(hook);
2923
+ this.emit('beforeEach', hook);
2924
+ return this;
2925
+ };
2926
+
2927
+ /**
2928
+ * Run `fn(test[, done])` after each test case.
2929
+ *
2930
+ * @param {Function} fn
2931
+ * @return {Suite} for chaining
2932
+ * @api private
2933
+ */
2934
+
2935
+ Suite.prototype.afterEach = function(fn){
2936
+ var hook = new Hook('"after each" hook', fn);
2937
+ hook.parent = this;
2938
+ hook.timeout(this.timeout());
2939
+ hook.ctx = this.ctx;
2940
+ this._afterEach.push(hook);
2941
+ this.emit('afterEach', hook);
2942
+ return this;
2943
+ };
2944
+
2945
+ /**
2946
+ * Add a test `suite`.
2947
+ *
2948
+ * @param {Suite} suite
2949
+ * @return {Suite} for chaining
2950
+ * @api private
2951
+ */
2952
+
2953
+ Suite.prototype.addSuite = function(suite){
2954
+ suite.parent = this;
2955
+ suite.timeout(this.timeout());
2956
+ suite.bail(this.bail());
2957
+ this.suites.push(suite);
2958
+ this.emit('suite', suite);
2959
+ return this;
2960
+ };
2961
+
2962
+ /**
2963
+ * Add a `test` to this suite.
2964
+ *
2965
+ * @param {Test} test
2966
+ * @return {Suite} for chaining
2967
+ * @api private
2968
+ */
2969
+
2970
+ Suite.prototype.addTest = function(test){
2971
+ test.parent = this;
2972
+ test.timeout(this.timeout());
2973
+ test.ctx = this.ctx;
2974
+ this.tests.push(test);
2975
+ this.emit('test', test);
2976
+ return this;
2977
+ };
2978
+
2979
+ /**
2980
+ * Return the full title generated by recursively
2981
+ * concatenating the parent's full title.
2982
+ *
2983
+ * @return {String}
2984
+ * @api public
2985
+ */
2986
+
2987
+ Suite.prototype.fullTitle = function(){
2988
+ if (this.parent) {
2989
+ var full = this.parent.fullTitle();
2990
+ if (full) return full + ' ' + this.title;
2991
+ }
2992
+ return this.title;
2993
+ };
2994
+
2995
+ /**
2996
+ * Return the total number of tests.
2997
+ *
2998
+ * @return {Number}
2999
+ * @api public
3000
+ */
3001
+
3002
+ Suite.prototype.total = function(){
3003
+ return utils.reduce(this.suites, function(sum, suite){
3004
+ return sum + suite.total();
3005
+ }, 0) + this.tests.length;
3006
+ };
3007
+
3008
+ }); // module: suite.js
3009
+
3010
+ require.register("test.js", function(module, exports, require){
3011
+
3012
+ /**
3013
+ * Module dependencies.
3014
+ */
3015
+
3016
+ var Runnable = require('./runnable');
3017
+
3018
+ /**
3019
+ * Expose `Test`.
3020
+ */
3021
+
3022
+ module.exports = Test;
3023
+
3024
+ /**
3025
+ * Initialize a new `Test` with the given `title` and callback `fn`.
3026
+ *
3027
+ * @param {String} title
3028
+ * @param {Function} fn
3029
+ * @api private
3030
+ */
3031
+
3032
+ function Test(title, fn) {
3033
+ Runnable.call(this, title, fn);
3034
+ this.pending = !fn;
3035
+ this.type = 'test';
3036
+ }
3037
+
3038
+ /**
3039
+ * Inherit from `Runnable.prototype`.
3040
+ */
3041
+
3042
+ Test.prototype = new Runnable;
3043
+ Test.prototype.constructor = Test;
3044
+
3045
+
3046
+ /**
3047
+ * Inspect the context void of private properties.
3048
+ *
3049
+ * @return {String}
3050
+ * @api private
3051
+ */
3052
+
3053
+ Test.prototype.inspect = function(){
3054
+ return JSON.stringify(this, function(key, val){
3055
+ return '_' == key[0]
3056
+ ? undefined
3057
+ : 'parent' == key
3058
+ ? '#<Suite>'
3059
+ : val;
3060
+ }, 2);
3061
+ };
3062
+ }); // module: test.js
3063
+
3064
+ require.register("utils.js", function(module, exports, require){
3065
+
3066
+ /**
3067
+ * Module dependencies.
3068
+ */
3069
+
3070
+ var fs = require('browser/fs')
3071
+ , path = require('browser/path')
3072
+ , join = path.join
3073
+ , debug = require('browser/debug')('watch');
3074
+
3075
+ /**
3076
+ * Ignored directories.
3077
+ */
3078
+
3079
+ var ignore = ['node_modules', '.git'];
3080
+
3081
+ /**
3082
+ * Escape special characters in the given string of html.
3083
+ *
3084
+ * @param {String} html
3085
+ * @return {String}
3086
+ * @api private
3087
+ */
3088
+
3089
+ exports.escape = function(html) {
3090
+ return String(html)
3091
+ .replace(/&/g, '&amp;')
3092
+ .replace(/"/g, '&quot;')
3093
+ .replace(/</g, '&lt;')
3094
+ .replace(/>/g, '&gt;');
3095
+ };
3096
+
3097
+ /**
3098
+ * Array#forEach (<=IE8)
3099
+ *
3100
+ * @param {Array} array
3101
+ * @param {Function} fn
3102
+ * @param {Object} scope
3103
+ * @api private
3104
+ */
3105
+
3106
+ exports.forEach = function(arr, fn, scope) {
3107
+ for (var i = 0, l = arr.length; i < l; i++)
3108
+ fn.call(scope, arr[i], i);
3109
+ };
3110
+
3111
+ /**
3112
+ * Array#indexOf (<=IE8)
3113
+ *
3114
+ * @parma {Array} arr
3115
+ * @param {Object} obj to find index of
3116
+ * @param {Number} start
3117
+ * @api private
3118
+ */
3119
+
3120
+ exports.indexOf = function (arr, obj, start) {
3121
+ for (var i = start || 0, l = arr.length; i < l; i++) {
3122
+ if (arr[i] === obj)
3123
+ return i;
3124
+ }
3125
+ return -1;
3126
+ };
3127
+
3128
+ /**
3129
+ * Array#reduce (<=IE8)
3130
+ *
3131
+ * @param {Array} array
3132
+ * @param {Function} fn
3133
+ * @param {Object} initial value
3134
+ * @param {Object} scope
3135
+ * @api private
3136
+ */
3137
+
3138
+ exports.reduce = function(arr, fn, val, scope) {
3139
+ var rval = val;
3140
+
3141
+ for (var i = 0, l = arr.length; i < l; i++) {
3142
+ rval = fn.call(scope, rval, arr[i], i, arr);
3143
+ }
3144
+
3145
+ return rval;
3146
+ };
3147
+
3148
+ /**
3149
+ * Array#filter (<=IE8)
3150
+ *
3151
+ * @param {Array} array
3152
+ * @param {Function} fn
3153
+ * @param {Object} scope
3154
+ * @api private
3155
+ */
3156
+
3157
+ exports.filter = function(arr, fn, scope) {
3158
+ var ret = [];
3159
+
3160
+ for (var i = 0, l = arr.length; i < l; i++) {
3161
+ var val = arr[i];
3162
+ if (fn.call(scope, val, i, arr))
3163
+ ret.push(val);
3164
+ }
3165
+
3166
+ return ret;
3167
+ };
3168
+
3169
+ /**
3170
+ * Object.keys (<=IE8)
3171
+ *
3172
+ * @param {Object} obj
3173
+ * @return {Array} keys
3174
+ * @api private
3175
+ */
3176
+
3177
+ exports.keys = Object.keys || function(obj) {
3178
+ var keys = []
3179
+ , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
3180
+
3181
+ for (var i in obj) {
3182
+ if (has.call(obj, i)) {
3183
+ keys.push(i);
3184
+ }
3185
+ }
3186
+
3187
+ return keys;
3188
+ };
3189
+
3190
+ /**
3191
+ * Watch the given `files` for changes
3192
+ * and invoke `fn(file)` on modification.
3193
+ *
3194
+ * @param {Array} files
3195
+ * @param {Function} fn
3196
+ * @api private
3197
+ */
3198
+
3199
+ exports.watch = function(files, fn){
3200
+ var options = { interval: 100 };
3201
+ files.forEach(function(file){
3202
+ debug('file %s', file);
3203
+ fs.watchFile(file, options, function(curr, prev){
3204
+ if (prev.mtime < curr.mtime) fn(file);
3205
+ });
3206
+ });
3207
+ };
3208
+
3209
+ /**
3210
+ * Ignored files.
3211
+ */
3212
+
3213
+ function ignored(path){
3214
+ return !~ignore.indexOf(path);
3215
+ }
3216
+
3217
+ /**
3218
+ * Lookup files in the given `dir`.
3219
+ *
3220
+ * @return {Array}
3221
+ * @api public
3222
+ */
3223
+
3224
+ exports.files = function(dir, ret){
3225
+ ret = ret || [];
3226
+
3227
+ fs.readdirSync(dir)
3228
+ .filter(ignored)
3229
+ .forEach(function(path){
3230
+ path = join(dir, path);
3231
+ if (fs.statSync(path).isDirectory()) {
3232
+ exports.files(path, ret);
3233
+ } else if (path.match(/\.(js|coffee)$/)) {
3234
+ ret.push(path);
3235
+ }
3236
+ });
3237
+
3238
+ return ret;
3239
+ };
3240
+ }); // module: utils.js
3241
+
3242
+ /**
3243
+ * Node shims.
3244
+ *
3245
+ * These are meant only to allow
3246
+ * mocha.js to run untouched, not
3247
+ * to allow running node code in
3248
+ * the browser.
3249
+ */
3250
+
3251
+ process = {};
3252
+ process.exit = function(status){};
3253
+ process.stdout = {};
3254
+ global = window;
3255
+
3256
+ /**
3257
+ * next tick implementation.
3258
+ */
3259
+
3260
+ process.nextTick = (function(){
3261
+ // postMessage behaves badly on IE8
3262
+ if (window.ActiveXObject || !window.postMessage) {
3263
+ return function(fn){ fn() };
3264
+ }
3265
+
3266
+ // based on setZeroTimeout by David Baron
3267
+ // - http://dbaron.org/log/20100309-faster-timeouts
3268
+ var timeouts = []
3269
+ , name = 'mocha-zero-timeout'
3270
+
3271
+ return function(fn){
3272
+ timeouts.push(fn);
3273
+ window.postMessage(name, '*');
3274
+ window.addEventListener('message', function(e){
3275
+ if (e.source == window && e.data == name) {
3276
+ if (e.stopPropagation) e.stopPropagation();
3277
+ if (timeouts.length) timeouts.shift()();
3278
+ }
3279
+ }, true);
3280
+ }
3281
+ })();
3282
+
3283
+ /**
3284
+ * Remove uncaughtException listener.
3285
+ */
3286
+
3287
+ process.removeListener = function(e){
3288
+ if ('uncaughtException' == e) {
3289
+ window.onerror = null;
3290
+ }
3291
+ };
3292
+
3293
+ /**
3294
+ * Implements uncaughtException listener.
3295
+ */
3296
+
3297
+ process.on = function(e, fn){
3298
+ if ('uncaughtException' == e) {
3299
+ window.onerror = fn;
3300
+ }
3301
+ };
3302
+
3303
+ /**
3304
+ * Expose mocha.
3305
+ */
3306
+
3307
+ window.mocha = require('mocha');
3308
+
3309
+ // boot
3310
+ ;(function(){
3311
+ var suite = new mocha.Suite('', new mocha.Context)
3312
+ , utils = mocha.utils
3313
+ , Reporter = mocha.reporters.HTML
3314
+
3315
+ $(function(){
3316
+ $('code').each(function(){
3317
+ $(this).html(highlight($(this).text()));
3318
+ });
3319
+ });
3320
+
3321
+ /**
3322
+ * Highlight the given string of `js`.
3323
+ */
3324
+
3325
+ function highlight(js) {
3326
+ return js
3327
+ .replace(/</g, '&lt;')
3328
+ .replace(/>/g, '&gt;')
3329
+ .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
3330
+ .replace(/('.*')/gm, '<span class="string">$1</span>')
3331
+ .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
3332
+ .replace(/(\d+)/gm, '<span class="number">$1</span>')
3333
+ .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
3334
+ .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
3335
+ }
3336
+
3337
+ /**
3338
+ * Parse the given `qs`.
3339
+ */
3340
+
3341
+ function parse(qs) {
3342
+ return utils.reduce(qs.replace('?', '').split('&'), function(obj, pair){
3343
+ var i = pair.indexOf('=')
3344
+ , key = pair.slice(0, i)
3345
+ , val = pair.slice(++i);
3346
+
3347
+ obj[key] = decodeURIComponent(val);
3348
+ return obj;
3349
+ }, {});
3350
+ }
3351
+
3352
+ /**
3353
+ * Setup mocha with the give `ui` name.
3354
+ */
3355
+
3356
+ mocha.setup = function(ui){
3357
+ ui = mocha.interfaces[ui];
3358
+ if (!ui) throw new Error('invalid mocha interface "' + ui + '"');
3359
+ ui(suite);
3360
+ suite.emit('pre-require', window);
3361
+ };
3362
+
3363
+ /**
3364
+ * Run mocha, returning the Runner.
3365
+ */
3366
+
3367
+ mocha.run = function(){
3368
+ suite.emit('run');
3369
+ var runner = new mocha.Runner(suite);
3370
+ var reporter = new Reporter(runner);
3371
+ var query = parse(window.location.search || "");
3372
+ if (query.grep) runner.grep(new RegExp(query.grep));
3373
+ runner.on('end', function(){
3374
+ $('code').each(function(){
3375
+ $(this).html(highlight($(this).text()));
3376
+ });
3377
+ });
3378
+ return runner.run();
3379
+ };
3380
+ })();
3381
+ })();