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.
- data/MIT-LICENSE +22 -0
- data/Rakefile +38 -0
- data/Readme.md +78 -0
- data/app/assets/javascripts/mocha_rails/application.js +4 -0
- data/app/assets/javascripts/mocha_rails/mocha-rails.js +5 -0
- data/app/assets/stylesheets/mocha_rails/application.css +13 -0
- data/app/controllers/mocha_rails/application_controller.rb +4 -0
- data/app/controllers/mocha_rails/tests_controller.rb +6 -0
- data/app/helpers/mocha_rails/application_helper.rb +4 -0
- data/app/views/mocha_rails/tests/index.html.erb +13 -0
- data/config/initializers/mocha_rails.rb +4 -0
- data/config/routes.rb +3 -0
- data/lib/mocha_rails/engine.rb +5 -0
- data/lib/mocha_rails/version.rb +3 -0
- data/lib/mocha_rails.rb +4 -0
- data/lib/tasks/mocha_rails_tasks.rake +4 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config/application.rb +62 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +31 -0
- data/test/dummy/config/environments/production.rb +64 -0
- data/test/dummy/config/environments/test.rb +35 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +10 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/log/test.log +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/navigation_test.rb +9 -0
- data/test/mocha_rails_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- data/vendor/assets/javascripts/expect.js +1202 -0
- data/vendor/assets/javascripts/mocha.css +133 -0
- data/vendor/assets/javascripts/mocha.js +3381 -0
- 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, '&')
|
3092
|
+
.replace(/"/g, '"')
|
3093
|
+
.replace(/</g, '<')
|
3094
|
+
.replace(/>/g, '>');
|
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, '<')
|
3328
|
+
.replace(/>/g, '>')
|
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
|
+
})();
|