matcha 0.9.0

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