├── History.md
├── Makefile
├── package.json
├── index.js
├── component.json
├── Readme.md
└── test
├── mocha
├── tests.html
├── mocha.css
└── mocha.js
├── index.html
└── before.js
/History.md:
--------------------------------------------------------------------------------
1 |
2 | 0.1.0 / 2013-02-08
3 | ==================
4 |
5 | * make sure an element has a parent node before attempting to insert before
6 |
7 | 0.0.1 / 2013-02-01
8 | ==================
9 |
10 | * initial
11 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | build: components index.js
3 | @component build --dev
4 |
5 | components: component.json
6 | @component install --dev
7 |
8 | clean:
9 | rm -fr build components template.js
10 |
11 | .PHONY: clean
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "democracyos-before",
3 | "repository": "https://github.com/DemocracyOS/before",
4 | "description": "standalone before",
5 | "version": "0.1.0",
6 | "keywords": ["before"],
7 | "dependencies": {},
8 | "license": "MIT"
9 | }
10 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * insert `b` before `a`.
4 | *
5 | * @param {Element} a
6 | * @param {Element} b
7 | * @return {Element} b
8 | */
9 |
10 | module.exports = function(a, b){
11 | if (a.parentNode) {
12 | return a.parentNode.insertBefore(b, a);
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/component.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "democracyos-before",
3 | "repo": "DemocracyOS/before",
4 | "description": "standalone before",
5 | "version": "0.1.0",
6 | "keywords": ["before"],
7 | "dependencies": {},
8 | "development": {},
9 | "license": "MIT",
10 | "scripts": [
11 | "index.js"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 |
2 | # before
3 |
4 | insert an element before other one
5 |
6 | ## Installation
7 |
8 | $ component install yields/before
9 |
10 | ## API
11 |
12 | ### before(a, b)
13 |
14 | insert `b` before `a`.
15 |
16 | ### Tests
17 |
18 | ```bash
19 | $ git clone https://github.com/yields/before
20 | $ cd before && component install && component build
21 | $ open test/index.html
22 | ```
23 |
24 | ## License
25 |
26 | MIT
27 |
--------------------------------------------------------------------------------
/test/mocha/tests.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Mocha
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | before
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/test/before.js:
--------------------------------------------------------------------------------
1 |
2 | var before = require('before');
3 |
4 | // assert
5 |
6 | function assert(expr, ms){
7 | if (expr) return;
8 | throw new Error(ms || 'does not work!');
9 | }
10 |
11 | describe('before(a, b)', function(){
12 | it('should insert b before a', function(){
13 | var ul = document.createElement('ul');
14 | var a = document.createElement('li');
15 | var b = document.createElement('li');
16 | a.innerText = 'a';
17 | b.innerText = 'b';
18 | ul.appendChild(a);
19 | before(a, b);
20 | assert(a === b.nextSibling);
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/test/mocha/mocha.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | body {
3 | font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
4 | padding: 60px 50px;
5 | }
6 |
7 | #mocha ul, #mocha li {
8 | margin: 0;
9 | padding: 0;
10 | }
11 |
12 | #mocha ul {
13 | list-style: none;
14 | }
15 |
16 | #mocha h1, #mocha h2 {
17 | margin: 0;
18 | }
19 |
20 | #mocha h1 {
21 | margin-top: 15px;
22 | font-size: 1em;
23 | font-weight: 200;
24 | }
25 |
26 | #mocha h1 a {
27 | text-decoration: none;
28 | color: inherit;
29 | }
30 |
31 | #mocha h1 a:hover {
32 | text-decoration: underline;
33 | }
34 |
35 | #mocha .suite .suite h1 {
36 | margin-top: 0;
37 | font-size: .8em;
38 | }
39 |
40 | #mocha h2 {
41 | font-size: 12px;
42 | font-weight: normal;
43 | cursor: pointer;
44 | }
45 |
46 | #mocha .suite {
47 | margin-left: 15px;
48 | }
49 |
50 | #mocha .test {
51 | margin-left: 15px;
52 | }
53 |
54 | #mocha .test:hover h2::after {
55 | position: relative;
56 | top: 0;
57 | right: -10px;
58 | content: '(view source)';
59 | font-size: 12px;
60 | font-family: arial;
61 | color: #888;
62 | }
63 |
64 | #mocha .test.pending:hover h2::after {
65 | content: '(pending)';
66 | font-family: arial;
67 | }
68 |
69 | #mocha .test.pass.medium .duration {
70 | background: #C09853;
71 | }
72 |
73 | #mocha .test.pass.slow .duration {
74 | background: #B94A48;
75 | }
76 |
77 | #mocha .test.pass::before {
78 | content: '✓';
79 | font-size: 12px;
80 | display: block;
81 | float: left;
82 | margin-right: 5px;
83 | color: #00d6b2;
84 | }
85 |
86 | #mocha .test.pass .duration {
87 | font-size: 9px;
88 | margin-left: 5px;
89 | padding: 2px 5px;
90 | color: white;
91 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
92 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
93 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
94 | -webkit-border-radius: 5px;
95 | -moz-border-radius: 5px;
96 | -ms-border-radius: 5px;
97 | -o-border-radius: 5px;
98 | border-radius: 5px;
99 | }
100 |
101 | #mocha .test.pass.fast .duration {
102 | display: none;
103 | }
104 |
105 | #mocha .test.pending {
106 | color: #0b97c4;
107 | }
108 |
109 | #mocha .test.pending::before {
110 | content: '◦';
111 | color: #0b97c4;
112 | }
113 |
114 | #mocha .test.fail {
115 | color: #c00;
116 | }
117 |
118 | #mocha .test.fail pre {
119 | color: black;
120 | }
121 |
122 | #mocha .test.fail::before {
123 | content: '✖';
124 | font-size: 12px;
125 | display: block;
126 | float: left;
127 | margin-right: 5px;
128 | color: #c00;
129 | }
130 |
131 | #mocha .test pre.error {
132 | color: #c00;
133 | }
134 |
135 | #mocha .test pre {
136 | display: inline-block;
137 | font: 12px/1.5 monaco, monospace;
138 | margin: 5px;
139 | padding: 15px;
140 | border: 1px solid #eee;
141 | border-bottom-color: #ddd;
142 | -webkit-border-radius: 3px;
143 | -webkit-box-shadow: 0 1px 3px #eee;
144 | }
145 |
146 | #report.pass .test.fail {
147 | display: none;
148 | }
149 |
150 | #report.fail .test.pass {
151 | display: none;
152 | }
153 |
154 | #error {
155 | color: #c00;
156 | font-size: 1.5 em;
157 | font-weight: 100;
158 | letter-spacing: 1px;
159 | }
160 |
161 | #stats {
162 | position: fixed;
163 | top: 15px;
164 | right: 10px;
165 | font-size: 12px;
166 | margin: 0;
167 | color: #888;
168 | }
169 |
170 | #stats .progress {
171 | float: right;
172 | padding-top: 0;
173 | }
174 |
175 | #stats em {
176 | color: black;
177 | }
178 |
179 | #stats a {
180 | text-decoration: none;
181 | color: inherit;
182 | }
183 |
184 | #stats a:hover {
185 | border-bottom: 1px solid #eee;
186 | }
187 |
188 | #stats li {
189 | display: inline-block;
190 | margin: 0 5px;
191 | list-style: none;
192 | padding-top: 11px;
193 | }
194 |
195 | code .comment { color: #ddd }
196 | code .init { color: #2F6FAD }
197 | code .string { color: #5890AD }
198 | code .keyword { color: #8A6343 }
199 | code .number { color: #2F6FAD }
200 |
--------------------------------------------------------------------------------
/test/mocha/mocha.js:
--------------------------------------------------------------------------------
1 | ;(function(){
2 |
3 |
4 | // CommonJS require()
5 |
6 | function require(p){
7 | var path = require.resolve(p)
8 | , mod = require.modules[path];
9 | if (!mod) throw new Error('failed to require "' + p + '"');
10 | if (!mod.exports) {
11 | mod.exports = {};
12 | mod.call(mod.exports, mod, mod.exports, require.relative(path));
13 | }
14 | return mod.exports;
15 | }
16 |
17 | require.modules = {};
18 |
19 | require.resolve = function (path){
20 | var orig = path
21 | , reg = path + '.js'
22 | , index = path + '/index.js';
23 | return require.modules[reg] && reg
24 | || require.modules[index] && index
25 | || orig;
26 | };
27 |
28 | require.register = function (path, fn){
29 | require.modules[path] = fn;
30 | };
31 |
32 | require.relative = function (parent) {
33 | return function(p){
34 | if ('.' != p.charAt(0)) return require(p);
35 |
36 | var path = parent.split('/')
37 | , segs = p.split('/');
38 | path.pop();
39 |
40 | for (var i = 0; i < segs.length; i++) {
41 | var seg = segs[i];
42 | if ('..' == seg) path.pop();
43 | else if ('.' != seg) path.push(seg);
44 | }
45 |
46 | return require(path.join('/'));
47 | };
48 | };
49 |
50 |
51 | require.register("browser/debug.js", function(module, exports, require){
52 |
53 | module.exports = function(type){
54 | return function(){
55 |
56 | }
57 | };
58 | }); // module: browser/debug.js
59 |
60 | require.register("browser/diff.js", function(module, exports, require){
61 |
62 | }); // module: browser/diff.js
63 |
64 | require.register("browser/events.js", function(module, exports, require){
65 |
66 | /**
67 | * Module exports.
68 | */
69 |
70 | exports.EventEmitter = EventEmitter;
71 |
72 | /**
73 | * Check if `obj` is an array.
74 | */
75 |
76 | function isArray(obj) {
77 | return '[object Array]' == {}.toString.call(obj);
78 | }
79 |
80 | /**
81 | * Event emitter constructor.
82 | *
83 | * @api public
84 | */
85 |
86 | function EventEmitter(){};
87 |
88 | /**
89 | * Adds a listener.
90 | *
91 | * @api public
92 | */
93 |
94 | EventEmitter.prototype.on = function (name, fn) {
95 | if (!this.$events) {
96 | this.$events = {};
97 | }
98 |
99 | if (!this.$events[name]) {
100 | this.$events[name] = fn;
101 | } else if (isArray(this.$events[name])) {
102 | this.$events[name].push(fn);
103 | } else {
104 | this.$events[name] = [this.$events[name], fn];
105 | }
106 |
107 | return this;
108 | };
109 |
110 | EventEmitter.prototype.addListener = EventEmitter.prototype.on;
111 |
112 | /**
113 | * Adds a volatile listener.
114 | *
115 | * @api public
116 | */
117 |
118 | EventEmitter.prototype.once = function (name, fn) {
119 | var self = this;
120 |
121 | function on () {
122 | self.removeListener(name, on);
123 | fn.apply(this, arguments);
124 | };
125 |
126 | on.listener = fn;
127 | this.on(name, on);
128 |
129 | return this;
130 | };
131 |
132 | /**
133 | * Removes a listener.
134 | *
135 | * @api public
136 | */
137 |
138 | EventEmitter.prototype.removeListener = function (name, fn) {
139 | if (this.$events && this.$events[name]) {
140 | var list = this.$events[name];
141 |
142 | if (isArray(list)) {
143 | var pos = -1;
144 |
145 | for (var i = 0, l = list.length; i < l; i++) {
146 | if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
147 | pos = i;
148 | break;
149 | }
150 | }
151 |
152 | if (pos < 0) {
153 | return this;
154 | }
155 |
156 | list.splice(pos, 1);
157 |
158 | if (!list.length) {
159 | delete this.$events[name];
160 | }
161 | } else if (list === fn || (list.listener && list.listener === fn)) {
162 | delete this.$events[name];
163 | }
164 | }
165 |
166 | return this;
167 | };
168 |
169 | /**
170 | * Removes all listeners for an event.
171 | *
172 | * @api public
173 | */
174 |
175 | EventEmitter.prototype.removeAllListeners = function (name) {
176 | if (name === undefined) {
177 | this.$events = {};
178 | return this;
179 | }
180 |
181 | if (this.$events && this.$events[name]) {
182 | this.$events[name] = null;
183 | }
184 |
185 | return this;
186 | };
187 |
188 | /**
189 | * Gets all listeners for a certain event.
190 | *
191 | * @api public
192 | */
193 |
194 | EventEmitter.prototype.listeners = function (name) {
195 | if (!this.$events) {
196 | this.$events = {};
197 | }
198 |
199 | if (!this.$events[name]) {
200 | this.$events[name] = [];
201 | }
202 |
203 | if (!isArray(this.$events[name])) {
204 | this.$events[name] = [this.$events[name]];
205 | }
206 |
207 | return this.$events[name];
208 | };
209 |
210 | /**
211 | * Emits an event.
212 | *
213 | * @api public
214 | */
215 |
216 | EventEmitter.prototype.emit = function (name) {
217 | if (!this.$events) {
218 | return false;
219 | }
220 |
221 | var handler = this.$events[name];
222 |
223 | if (!handler) {
224 | return false;
225 | }
226 |
227 | var args = [].slice.call(arguments, 1);
228 |
229 | if ('function' == typeof handler) {
230 | handler.apply(this, args);
231 | } else if (isArray(handler)) {
232 | var listeners = handler.slice();
233 |
234 | for (var i = 0, l = listeners.length; i < l; i++) {
235 | listeners[i].apply(this, args);
236 | }
237 | } else {
238 | return false;
239 | }
240 |
241 | return true;
242 | };
243 | }); // module: browser/events.js
244 |
245 | require.register("browser/fs.js", function(module, exports, require){
246 |
247 | }); // module: browser/fs.js
248 |
249 | require.register("browser/path.js", function(module, exports, require){
250 |
251 | }); // module: browser/path.js
252 |
253 | require.register("browser/progress.js", function(module, exports, require){
254 |
255 | /**
256 | * Expose `Progress`.
257 | */
258 |
259 | module.exports = Progress;
260 |
261 | /**
262 | * Initialize a new `Progress` indicator.
263 | */
264 |
265 | function Progress() {
266 | this.percent = 0;
267 | this.size(0);
268 | this.fontSize(11);
269 | this.font('helvetica, arial, sans-serif');
270 | }
271 |
272 | /**
273 | * Set progress size to `n`.
274 | *
275 | * @param {Number} n
276 | * @return {Progress} for chaining
277 | * @api public
278 | */
279 |
280 | Progress.prototype.size = function(n){
281 | this._size = n;
282 | return this;
283 | };
284 |
285 | /**
286 | * Set text to `str`.
287 | *
288 | * @param {String} str
289 | * @return {Progress} for chaining
290 | * @api public
291 | */
292 |
293 | Progress.prototype.text = function(str){
294 | this._text = str;
295 | return this;
296 | };
297 |
298 | /**
299 | * Set font size to `n`.
300 | *
301 | * @param {Number} n
302 | * @return {Progress} for chaining
303 | * @api public
304 | */
305 |
306 | Progress.prototype.fontSize = function(n){
307 | this._fontSize = n;
308 | return this;
309 | };
310 |
311 | /**
312 | * Set font `family`.
313 | *
314 | * @param {String} family
315 | * @return {Progress} for chaining
316 | */
317 |
318 | Progress.prototype.font = function(family){
319 | this._font = family;
320 | return this;
321 | };
322 |
323 | /**
324 | * Update percentage to `n`.
325 | *
326 | * @param {Number} n
327 | * @return {Progress} for chaining
328 | */
329 |
330 | Progress.prototype.update = function(n){
331 | this.percent = n;
332 | return this;
333 | };
334 |
335 | /**
336 | * Draw on `ctx`.
337 | *
338 | * @param {CanvasRenderingContext2d} ctx
339 | * @return {Progress} for chaining
340 | */
341 |
342 | Progress.prototype.draw = function(ctx){
343 | var percent = Math.min(this.percent, 100)
344 | , size = this._size
345 | , half = size / 2
346 | , x = half
347 | , y = half
348 | , rad = half - 1
349 | , fontSize = this._fontSize;
350 |
351 | ctx.font = fontSize + 'px ' + this._font;
352 |
353 | var angle = Math.PI * 2 * (percent / 100);
354 | ctx.clearRect(0, 0, size, size);
355 |
356 | // outer circle
357 | ctx.strokeStyle = '#9f9f9f';
358 | ctx.beginPath();
359 | ctx.arc(x, y, rad, 0, angle, false);
360 | ctx.stroke();
361 |
362 | // inner circle
363 | ctx.strokeStyle = '#eee';
364 | ctx.beginPath();
365 | ctx.arc(x, y, rad - 1, 0, angle, true);
366 | ctx.stroke();
367 |
368 | // text
369 | var text = this._text || (percent | 0) + '%'
370 | , w = ctx.measureText(text).width;
371 |
372 | ctx.fillText(
373 | text
374 | , x - w / 2 + 1
375 | , y + fontSize / 2 - 1);
376 |
377 | return this;
378 | };
379 |
380 | }); // module: browser/progress.js
381 |
382 | require.register("browser/tty.js", function(module, exports, require){
383 |
384 | exports.isatty = function(){
385 | return true;
386 | };
387 |
388 | exports.getWindowSize = function(){
389 | return [window.innerHeight, window.innerWidth];
390 | };
391 | }); // module: browser/tty.js
392 |
393 | require.register("context.js", function(module, exports, require){
394 |
395 | /**
396 | * Expose `Context`.
397 | */
398 |
399 | module.exports = Context;
400 |
401 | /**
402 | * Initialize a new `Context`.
403 | *
404 | * @api private
405 | */
406 |
407 | function Context(){}
408 |
409 | /**
410 | * Set or get the context `Runnable` to `runnable`.
411 | *
412 | * @param {Runnable} runnable
413 | * @return {Context}
414 | * @api private
415 | */
416 |
417 | Context.prototype.runnable = function(runnable){
418 | if (0 == arguments.length) return this._runnable;
419 | this.test = this._runnable = runnable;
420 | return this;
421 | };
422 |
423 | /**
424 | * Set test timeout `ms`.
425 | *
426 | * @param {Number} ms
427 | * @return {Context} self
428 | * @api private
429 | */
430 |
431 | Context.prototype.timeout = function(ms){
432 | this.runnable().timeout(ms);
433 | return this;
434 | };
435 |
436 | /**
437 | * Inspect the context void of `._runnable`.
438 | *
439 | * @return {String}
440 | * @api private
441 | */
442 |
443 | Context.prototype.inspect = function(){
444 | return JSON.stringify(this, function(key, val){
445 | if ('_runnable' == key) return;
446 | if ('test' == key) return;
447 | return val;
448 | }, 2);
449 | };
450 |
451 | }); // module: context.js
452 |
453 | require.register("hook.js", function(module, exports, require){
454 |
455 | /**
456 | * Module dependencies.
457 | */
458 |
459 | var Runnable = require('./runnable');
460 |
461 | /**
462 | * Expose `Hook`.
463 | */
464 |
465 | module.exports = Hook;
466 |
467 | /**
468 | * Initialize a new `Hook` with the given `title` and callback `fn`.
469 | *
470 | * @param {String} title
471 | * @param {Function} fn
472 | * @api private
473 | */
474 |
475 | function Hook(title, fn) {
476 | Runnable.call(this, title, fn);
477 | this.type = 'hook';
478 | }
479 |
480 | /**
481 | * Inherit from `Runnable.prototype`.
482 | */
483 |
484 | Hook.prototype = new Runnable;
485 | Hook.prototype.constructor = Hook;
486 |
487 |
488 | /**
489 | * Get or set the test `err`.
490 | *
491 | * @param {Error} err
492 | * @return {Error}
493 | * @api public
494 | */
495 |
496 | Hook.prototype.error = function(err){
497 | if (0 == arguments.length) {
498 | var err = this._error;
499 | this._error = null;
500 | return err;
501 | }
502 |
503 | this._error = err;
504 | };
505 |
506 |
507 | }); // module: hook.js
508 |
509 | require.register("interfaces/bdd.js", function(module, exports, require){
510 |
511 | /**
512 | * Module dependencies.
513 | */
514 |
515 | var Suite = require('../suite')
516 | , Test = require('../test');
517 |
518 | /**
519 | * BDD-style interface:
520 | *
521 | * describe('Array', function(){
522 | * describe('#indexOf()', function(){
523 | * it('should return -1 when not present', function(){
524 | *
525 | * });
526 | *
527 | * it('should return the index when present', function(){
528 | *
529 | * });
530 | * });
531 | * });
532 | *
533 | */
534 |
535 | module.exports = function(suite){
536 | var suites = [suite];
537 |
538 | suite.on('pre-require', function(context, file, mocha){
539 |
540 | /**
541 | * Execute before running tests.
542 | */
543 |
544 | context.before = function(fn){
545 | suites[0].beforeAll(fn);
546 | };
547 |
548 | /**
549 | * Execute after running tests.
550 | */
551 |
552 | context.after = function(fn){
553 | suites[0].afterAll(fn);
554 | };
555 |
556 | /**
557 | * Execute before each test case.
558 | */
559 |
560 | context.beforeEach = function(fn){
561 | suites[0].beforeEach(fn);
562 | };
563 |
564 | /**
565 | * Execute after each test case.
566 | */
567 |
568 | context.afterEach = function(fn){
569 | suites[0].afterEach(fn);
570 | };
571 |
572 | /**
573 | * Describe a "suite" with the given `title`
574 | * and callback `fn` containing nested suites
575 | * and/or tests.
576 | */
577 |
578 | context.describe = context.context = function(title, fn){
579 | var suite = Suite.create(suites[0], title);
580 | suites.unshift(suite);
581 | fn();
582 | suites.shift();
583 | return suite;
584 | };
585 |
586 | /**
587 | * Pending describe.
588 | */
589 |
590 | context.xdescribe =
591 | context.xcontext =
592 | context.describe.skip = function(title, fn){
593 | var suite = Suite.create(suites[0], title);
594 | suite.pending = true;
595 | suites.unshift(suite);
596 | fn();
597 | suites.shift();
598 | };
599 |
600 | /**
601 | * Exclusive suite.
602 | */
603 |
604 | context.describe.only = function(title, fn){
605 | var suite = context.describe(title, fn);
606 | mocha.grep(suite.fullTitle());
607 | };
608 |
609 | /**
610 | * Describe a specification or test-case
611 | * with the given `title` and callback `fn`
612 | * acting as a thunk.
613 | */
614 |
615 | context.it = context.specify = function(title, fn){
616 | var suite = suites[0];
617 | if (suite.pending) var fn = null;
618 | var test = new Test(title, fn);
619 | suite.addTest(test);
620 | return test;
621 | };
622 |
623 | /**
624 | * Exclusive test-case.
625 | */
626 |
627 | context.it.only = function(title, fn){
628 | var test = context.it(title, fn);
629 | mocha.grep(test.fullTitle());
630 | };
631 |
632 | /**
633 | * Pending test case.
634 | */
635 |
636 | context.xit =
637 | context.xspecify =
638 | context.it.skip = function(title){
639 | context.it(title);
640 | };
641 | });
642 | };
643 |
644 | }); // module: interfaces/bdd.js
645 |
646 | require.register("interfaces/exports.js", function(module, exports, require){
647 |
648 | /**
649 | * Module dependencies.
650 | */
651 |
652 | var Suite = require('../suite')
653 | , Test = require('../test');
654 |
655 | /**
656 | * TDD-style interface:
657 | *
658 | * exports.Array = {
659 | * '#indexOf()': {
660 | * 'should return -1 when the value is not present': function(){
661 | *
662 | * },
663 | *
664 | * 'should return the correct index when the value is present': function(){
665 | *
666 | * }
667 | * }
668 | * };
669 | *
670 | */
671 |
672 | module.exports = function(suite){
673 | var suites = [suite];
674 |
675 | suite.on('require', visit);
676 |
677 | function visit(obj) {
678 | var suite;
679 | for (var key in obj) {
680 | if ('function' == typeof obj[key]) {
681 | var fn = obj[key];
682 | switch (key) {
683 | case 'before':
684 | suites[0].beforeAll(fn);
685 | break;
686 | case 'after':
687 | suites[0].afterAll(fn);
688 | break;
689 | case 'beforeEach':
690 | suites[0].beforeEach(fn);
691 | break;
692 | case 'afterEach':
693 | suites[0].afterEach(fn);
694 | break;
695 | default:
696 | suites[0].addTest(new Test(key, fn));
697 | }
698 | } else {
699 | var suite = Suite.create(suites[0], key);
700 | suites.unshift(suite);
701 | visit(obj[key]);
702 | suites.shift();
703 | }
704 | }
705 | }
706 | };
707 | }); // module: interfaces/exports.js
708 |
709 | require.register("interfaces/index.js", function(module, exports, require){
710 |
711 | exports.bdd = require('./bdd');
712 | exports.tdd = require('./tdd');
713 | exports.qunit = require('./qunit');
714 | exports.exports = require('./exports');
715 |
716 | }); // module: interfaces/index.js
717 |
718 | require.register("interfaces/qunit.js", function(module, exports, require){
719 |
720 | /**
721 | * Module dependencies.
722 | */
723 |
724 | var Suite = require('../suite')
725 | , Test = require('../test');
726 |
727 | /**
728 | * QUnit-style interface:
729 | *
730 | * suite('Array');
731 | *
732 | * test('#length', function(){
733 | * var arr = [1,2,3];
734 | * ok(arr.length == 3);
735 | * });
736 | *
737 | * test('#indexOf()', function(){
738 | * var arr = [1,2,3];
739 | * ok(arr.indexOf(1) == 0);
740 | * ok(arr.indexOf(2) == 1);
741 | * ok(arr.indexOf(3) == 2);
742 | * });
743 | *
744 | * suite('String');
745 | *
746 | * test('#length', function(){
747 | * ok('foo'.length == 3);
748 | * });
749 | *
750 | */
751 |
752 | module.exports = function(suite){
753 | var suites = [suite];
754 |
755 | suite.on('pre-require', function(context){
756 |
757 | /**
758 | * Execute before running tests.
759 | */
760 |
761 | context.before = function(fn){
762 | suites[0].beforeAll(fn);
763 | };
764 |
765 | /**
766 | * Execute after running tests.
767 | */
768 |
769 | context.after = function(fn){
770 | suites[0].afterAll(fn);
771 | };
772 |
773 | /**
774 | * Execute before each test case.
775 | */
776 |
777 | context.beforeEach = function(fn){
778 | suites[0].beforeEach(fn);
779 | };
780 |
781 | /**
782 | * Execute after each test case.
783 | */
784 |
785 | context.afterEach = function(fn){
786 | suites[0].afterEach(fn);
787 | };
788 |
789 | /**
790 | * Describe a "suite" with the given `title`.
791 | */
792 |
793 | context.suite = function(title){
794 | if (suites.length > 1) suites.shift();
795 | var suite = Suite.create(suites[0], title);
796 | suites.unshift(suite);
797 | };
798 |
799 | /**
800 | * Describe a specification or test-case
801 | * with the given `title` and callback `fn`
802 | * acting as a thunk.
803 | */
804 |
805 | context.test = function(title, fn){
806 | suites[0].addTest(new Test(title, fn));
807 | };
808 | });
809 | };
810 |
811 | }); // module: interfaces/qunit.js
812 |
813 | require.register("interfaces/tdd.js", function(module, exports, require){
814 |
815 | /**
816 | * Module dependencies.
817 | */
818 |
819 | var Suite = require('../suite')
820 | , Test = require('../test');
821 |
822 | /**
823 | * TDD-style interface:
824 | *
825 | * suite('Array', function(){
826 | * suite('#indexOf()', function(){
827 | * suiteSetup(function(){
828 | *
829 | * });
830 | *
831 | * test('should return -1 when not present', function(){
832 | *
833 | * });
834 | *
835 | * test('should return the index when present', function(){
836 | *
837 | * });
838 | *
839 | * suiteTeardown(function(){
840 | *
841 | * });
842 | * });
843 | * });
844 | *
845 | */
846 |
847 | module.exports = function(suite){
848 | var suites = [suite];
849 |
850 | suite.on('pre-require', function(context, file, mocha){
851 |
852 | /**
853 | * Execute before each test case.
854 | */
855 |
856 | context.setup = function(fn){
857 | suites[0].beforeEach(fn);
858 | };
859 |
860 | /**
861 | * Execute after each test case.
862 | */
863 |
864 | context.teardown = function(fn){
865 | suites[0].afterEach(fn);
866 | };
867 |
868 | /**
869 | * Execute before the suite.
870 | */
871 |
872 | context.suiteSetup = function(fn){
873 | suites[0].beforeAll(fn);
874 | };
875 |
876 | /**
877 | * Execute after the suite.
878 | */
879 |
880 | context.suiteTeardown = function(fn){
881 | suites[0].afterAll(fn);
882 | };
883 |
884 | /**
885 | * Describe a "suite" with the given `title`
886 | * and callback `fn` containing nested suites
887 | * and/or tests.
888 | */
889 |
890 | context.suite = function(title, fn){
891 | var suite = Suite.create(suites[0], title);
892 | suites.unshift(suite);
893 | fn();
894 | suites.shift();
895 | return suite;
896 | };
897 |
898 | /**
899 | * Exclusive test-case.
900 | */
901 |
902 | context.suite.only = function(title, fn){
903 | var suite = context.suite(title, fn);
904 | mocha.grep(suite.fullTitle());
905 | };
906 |
907 | /**
908 | * Describe a specification or test-case
909 | * with the given `title` and callback `fn`
910 | * acting as a thunk.
911 | */
912 |
913 | context.test = function(title, fn){
914 | var test = new Test(title, fn);
915 | suites[0].addTest(test);
916 | return test;
917 | };
918 |
919 | /**
920 | * Exclusive test-case.
921 | */
922 |
923 | context.test.only = function(title, fn){
924 | var test = context.test(title, fn);
925 | mocha.grep(test.fullTitle());
926 | };
927 | });
928 | };
929 |
930 | }); // module: interfaces/tdd.js
931 |
932 | require.register("mocha.js", function(module, exports, require){
933 | /*!
934 | * mocha
935 | * Copyright(c) 2011 TJ Holowaychuk
936 | * MIT Licensed
937 | */
938 |
939 | /**
940 | * Module dependencies.
941 | */
942 |
943 | var path = require('browser/path');
944 |
945 | /**
946 | * Expose `Mocha`.
947 | */
948 |
949 | exports = module.exports = Mocha;
950 |
951 | /**
952 | * Expose internals.
953 | */
954 |
955 | exports.utils = require('./utils');
956 | exports.interfaces = require('./interfaces');
957 | exports.reporters = require('./reporters');
958 | exports.Runnable = require('./runnable');
959 | exports.Context = require('./context');
960 | exports.Runner = require('./runner');
961 | exports.Suite = require('./suite');
962 | exports.Hook = require('./hook');
963 | exports.Test = require('./test');
964 |
965 | /**
966 | * Return image `name` path.
967 | *
968 | * @param {String} name
969 | * @return {String}
970 | * @api private
971 | */
972 |
973 | function image(name) {
974 | return __dirname + '/../images/' + name + '.png';
975 | }
976 |
977 | /**
978 | * Setup mocha with `options`.
979 | *
980 | * Options:
981 | *
982 | * - `ui` name "bdd", "tdd", "exports" etc
983 | * - `reporter` reporter instance, defaults to `mocha.reporters.Dot`
984 | * - `globals` array of accepted globals
985 | * - `timeout` timeout in milliseconds
986 | * - `ignoreLeaks` ignore global leaks
987 | * - `grep` string or regexp to filter tests with
988 | *
989 | * @param {Object} options
990 | * @api public
991 | */
992 |
993 | function Mocha(options) {
994 | options = options || {};
995 | this.files = [];
996 | this.options = options;
997 | this.grep(options.grep);
998 | this.suite = new exports.Suite('', new exports.Context);
999 | this.ui(options.ui);
1000 | this.reporter(options.reporter);
1001 | if (options.timeout) this.suite.timeout(options.timeout);
1002 | }
1003 |
1004 | /**
1005 | * Add test `file`.
1006 | *
1007 | * @param {String} file
1008 | * @api public
1009 | */
1010 |
1011 | Mocha.prototype.addFile = function(file){
1012 | this.files.push(file);
1013 | return this;
1014 | };
1015 |
1016 | /**
1017 | * Set reporter to `name`, defaults to "dot".
1018 | *
1019 | * @param {String} name
1020 | * @api public
1021 | */
1022 |
1023 | Mocha.prototype.reporter = function(name){
1024 | name = name || 'dot';
1025 | this._reporter = require('./reporters/' + name);
1026 | if (!this._reporter) throw new Error('invalid reporter "' + name + '"');
1027 | return this;
1028 | };
1029 |
1030 | /**
1031 | * Set test UI `name`, defaults to "bdd".
1032 | *
1033 | * @param {String} bdd
1034 | * @api public
1035 | */
1036 |
1037 | Mocha.prototype.ui = function(name){
1038 | name = name || 'bdd';
1039 | this._ui = exports.interfaces[name];
1040 | if (!this._ui) throw new Error('invalid interface "' + name + '"');
1041 | this._ui = this._ui(this.suite);
1042 | return this;
1043 | };
1044 |
1045 | /**
1046 | * Load registered files.
1047 | *
1048 | * @api private
1049 | */
1050 |
1051 | Mocha.prototype.loadFiles = function(fn){
1052 | var self = this;
1053 | var suite = this.suite;
1054 | var pending = this.files.length;
1055 | this.files.forEach(function(file){
1056 | file = path.resolve(file);
1057 | suite.emit('pre-require', global, file, self);
1058 | suite.emit('require', require(file), file, self);
1059 | suite.emit('post-require', global, file, self);
1060 | --pending || (fn && fn());
1061 | });
1062 | };
1063 |
1064 | /**
1065 | * Enable growl support.
1066 | *
1067 | * @api private
1068 | */
1069 |
1070 | Mocha.prototype._growl = function(runner, reporter) {
1071 | var notify = require('growl');
1072 |
1073 | runner.on('end', function(){
1074 | var stats = reporter.stats;
1075 | if (stats.failures) {
1076 | var msg = stats.failures + ' of ' + runner.total + ' tests failed';
1077 | notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });
1078 | } else {
1079 | notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
1080 | name: 'mocha'
1081 | , title: 'Passed'
1082 | , image: image('ok')
1083 | });
1084 | }
1085 | });
1086 | };
1087 |
1088 | /**
1089 | * Add regexp to grep for to the options object
1090 | *
1091 | * @param {RegExp} or {String} re
1092 | * @return {Mocha}
1093 | * @api public
1094 | */
1095 |
1096 | Mocha.prototype.grep = function(re){
1097 | this.options.grep = 'string' == typeof re
1098 | ? new RegExp(re)
1099 | : re;
1100 | return this;
1101 | };
1102 |
1103 | /**
1104 | * Invert `.grep()` matches.
1105 | *
1106 | * @return {Mocha}
1107 | * @api public
1108 | */
1109 |
1110 | Mocha.prototype.invert = function(){
1111 | this.options.invert = true;
1112 | return this;
1113 | };
1114 |
1115 | /**
1116 | * Ignore global leaks.
1117 | *
1118 | * @return {Mocha}
1119 | * @api public
1120 | */
1121 |
1122 | Mocha.prototype.ignoreLeaks = function(){
1123 | this.options.ignoreLeaks = true;
1124 | return this;
1125 | };
1126 |
1127 | /**
1128 | * Enable growl support.
1129 | *
1130 | * @return {Mocha}
1131 | * @api public
1132 | */
1133 |
1134 | Mocha.prototype.growl = function(){
1135 | this.options.growl = true;
1136 | return this;
1137 | };
1138 |
1139 | /**
1140 | * Ignore `globals`.
1141 | *
1142 | * @param {Array} globals
1143 | * @return {Mocha}
1144 | * @api public
1145 | */
1146 |
1147 | Mocha.prototype.globals = function(globals){
1148 | this.options.globals = globals;
1149 | return this;
1150 | };
1151 |
1152 | /**
1153 | * Run tests and invoke `fn()` when complete.
1154 | *
1155 | * @param {Function} fn
1156 | * @return {Runner}
1157 | * @api public
1158 | */
1159 |
1160 | Mocha.prototype.run = function(fn){
1161 | this.loadFiles();
1162 | var suite = this.suite;
1163 | var options = this.options;
1164 | var runner = new exports.Runner(suite);
1165 | var reporter = new this._reporter(runner);
1166 | runner.ignoreLeaks = options.ignoreLeaks;
1167 | if (options.grep) runner.grep(options.grep, options.invert);
1168 | if (options.globals) runner.globals(options.globals);
1169 | if (options.growl) this._growl(runner, reporter);
1170 | return runner.run(fn);
1171 | };
1172 |
1173 | }); // module: mocha.js
1174 |
1175 | require.register("reporters/base.js", function(module, exports, require){
1176 |
1177 | /**
1178 | * Module dependencies.
1179 | */
1180 |
1181 | var tty = require('browser/tty')
1182 | , diff = require('browser/diff');
1183 |
1184 | /**
1185 | * Save timer references to avoid Sinon interfering (see GH-237).
1186 | */
1187 |
1188 | var Date = global.Date
1189 | , setTimeout = global.setTimeout
1190 | , setInterval = global.setInterval
1191 | , clearTimeout = global.clearTimeout
1192 | , clearInterval = global.clearInterval;
1193 |
1194 | /**
1195 | * Check if both stdio streams are associated with a tty.
1196 | */
1197 |
1198 | var isatty = tty.isatty(1) && tty.isatty(2);
1199 |
1200 | /**
1201 | * Expose `Base`.
1202 | */
1203 |
1204 | exports = module.exports = Base;
1205 |
1206 | /**
1207 | * Enable coloring by default.
1208 | */
1209 |
1210 | exports.useColors = isatty;
1211 |
1212 | /**
1213 | * Default color map.
1214 | */
1215 |
1216 | exports.colors = {
1217 | 'pass': 90
1218 | , 'fail': 31
1219 | , 'bright pass': 92
1220 | , 'bright fail': 91
1221 | , 'bright yellow': 93
1222 | , 'pending': 36
1223 | , 'suite': 0
1224 | , 'error title': 0
1225 | , 'error message': 31
1226 | , 'error stack': 90
1227 | , 'checkmark': 32
1228 | , 'fast': 90
1229 | , 'medium': 33
1230 | , 'slow': 31
1231 | , 'green': 32
1232 | , 'light': 90
1233 | , 'diff gutter': 90
1234 | , 'diff added': 42
1235 | , 'diff removed': 41
1236 | };
1237 |
1238 | /**
1239 | * Color `str` with the given `type`,
1240 | * allowing colors to be disabled,
1241 | * as well as user-defined color
1242 | * schemes.
1243 | *
1244 | * @param {String} type
1245 | * @param {String} str
1246 | * @return {String}
1247 | * @api private
1248 | */
1249 |
1250 | var color = exports.color = function(type, str) {
1251 | if (!exports.useColors) return str;
1252 | return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
1253 | };
1254 |
1255 | /**
1256 | * Expose term window size, with some
1257 | * defaults for when stderr is not a tty.
1258 | */
1259 |
1260 | exports.window = {
1261 | width: isatty
1262 | ? process.stdout.getWindowSize
1263 | ? process.stdout.getWindowSize(1)[0]
1264 | : tty.getWindowSize()[1]
1265 | : 75
1266 | };
1267 |
1268 | /**
1269 | * Expose some basic cursor interactions
1270 | * that are common among reporters.
1271 | */
1272 |
1273 | exports.cursor = {
1274 | hide: function(){
1275 | process.stdout.write('\u001b[?25l');
1276 | },
1277 |
1278 | show: function(){
1279 | process.stdout.write('\u001b[?25h');
1280 | },
1281 |
1282 | deleteLine: function(){
1283 | process.stdout.write('\u001b[2K');
1284 | },
1285 |
1286 | beginningOfLine: function(){
1287 | process.stdout.write('\u001b[0G');
1288 | },
1289 |
1290 | CR: function(){
1291 | exports.cursor.deleteLine();
1292 | exports.cursor.beginningOfLine();
1293 | }
1294 | };
1295 |
1296 | /**
1297 | * A test is considered slow if it
1298 | * exceeds the following value in milliseconds.
1299 | */
1300 |
1301 | exports.slow = 75;
1302 |
1303 | /**
1304 | * Outut the given `failures` as a list.
1305 | *
1306 | * @param {Array} failures
1307 | * @api public
1308 | */
1309 |
1310 | exports.list = function(failures){
1311 | console.error();
1312 | failures.forEach(function(test, i){
1313 | // format
1314 | var fmt = color('error title', ' %s) %s:\n')
1315 | + color('error message', ' %s')
1316 | + color('error stack', '\n%s\n');
1317 |
1318 | // msg
1319 | var err = test.err
1320 | , message = err.message || ''
1321 | , stack = err.stack || message
1322 | , index = stack.indexOf(message) + message.length
1323 | , msg = stack.slice(0, index)
1324 | , actual = err.actual
1325 | , expected = err.expected;
1326 |
1327 | // actual / expected diff
1328 | if ('string' == typeof actual && 'string' == typeof expected) {
1329 | var len = Math.max(actual.length, expected.length);
1330 |
1331 | if (len < 20) msg = errorDiff(err, 'Chars');
1332 | else msg = errorDiff(err, 'Words');
1333 |
1334 | // linenos
1335 | var lines = msg.split('\n');
1336 | if (lines.length > 4) {
1337 | var width = String(lines.length).length;
1338 | msg = lines.map(function(str, i){
1339 | return pad(++i, width) + ' |' + ' ' + str;
1340 | }).join('\n');
1341 | }
1342 |
1343 | // legend
1344 | msg = '\n'
1345 | + color('diff removed', 'actual')
1346 | + ' '
1347 | + color('diff added', 'expected')
1348 | + '\n\n'
1349 | + msg
1350 | + '\n';
1351 |
1352 | // indent
1353 | msg = msg.replace(/^/gm, ' ');
1354 |
1355 | fmt = color('error title', ' %s) %s:\n%s')
1356 | + color('error stack', '\n%s\n');
1357 | }
1358 |
1359 | // indent stack trace without msg
1360 | stack = stack.slice(index ? index + 1 : index)
1361 | .replace(/^/gm, ' ');
1362 |
1363 | console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
1364 | });
1365 | };
1366 |
1367 | /**
1368 | * Initialize a new `Base` reporter.
1369 | *
1370 | * All other reporters generally
1371 | * inherit from this reporter, providing
1372 | * stats such as test duration, number
1373 | * of tests passed / failed etc.
1374 | *
1375 | * @param {Runner} runner
1376 | * @api public
1377 | */
1378 |
1379 | function Base(runner) {
1380 | var self = this
1381 | , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
1382 | , failures = this.failures = [];
1383 |
1384 | if (!runner) return;
1385 | this.runner = runner;
1386 |
1387 | runner.on('start', function(){
1388 | stats.start = new Date;
1389 | });
1390 |
1391 | runner.on('suite', function(suite){
1392 | stats.suites = stats.suites || 0;
1393 | suite.root || stats.suites++;
1394 | });
1395 |
1396 | runner.on('test end', function(test){
1397 | stats.tests = stats.tests || 0;
1398 | stats.tests++;
1399 | });
1400 |
1401 | runner.on('pass', function(test){
1402 | stats.passes = stats.passes || 0;
1403 |
1404 | var medium = exports.slow / 2;
1405 | test.speed = test.duration > exports.slow
1406 | ? 'slow'
1407 | : test.duration > medium
1408 | ? 'medium'
1409 | : 'fast';
1410 |
1411 | stats.passes++;
1412 | });
1413 |
1414 | runner.on('fail', function(test, err){
1415 | stats.failures = stats.failures || 0;
1416 | stats.failures++;
1417 | test.err = err;
1418 | failures.push(test);
1419 | });
1420 |
1421 | runner.on('end', function(){
1422 | stats.end = new Date;
1423 | stats.duration = new Date - stats.start;
1424 | });
1425 |
1426 | runner.on('pending', function(){
1427 | stats.pending++;
1428 | });
1429 | }
1430 |
1431 | /**
1432 | * Output common epilogue used by many of
1433 | * the bundled reporters.
1434 | *
1435 | * @api public
1436 | */
1437 |
1438 | Base.prototype.epilogue = function(){
1439 | var stats = this.stats
1440 | , fmt
1441 | , tests;
1442 |
1443 | console.log();
1444 |
1445 | function pluralize(n) {
1446 | return 1 == n ? 'test' : 'tests';
1447 | }
1448 |
1449 | // failure
1450 | if (stats.failures) {
1451 | fmt = color('bright fail', ' ✖')
1452 | + color('fail', ' %d of %d %s failed')
1453 | + color('light', ':')
1454 |
1455 | console.error(fmt,
1456 | stats.failures,
1457 | this.runner.total,
1458 | pluralize(this.runner.total));
1459 |
1460 | Base.list(this.failures);
1461 | console.error();
1462 | return;
1463 | }
1464 |
1465 | // pass
1466 | fmt = color('bright pass', ' ✔')
1467 | + color('green', ' %d %s complete')
1468 | + color('light', ' (%dms)');
1469 |
1470 | console.log(fmt,
1471 | stats.tests || 0,
1472 | pluralize(stats.tests),
1473 | stats.duration);
1474 |
1475 | // pending
1476 | if (stats.pending) {
1477 | fmt = color('pending', ' •')
1478 | + color('pending', ' %d %s pending');
1479 |
1480 | console.log(fmt, stats.pending, pluralize(stats.pending));
1481 | }
1482 |
1483 | console.log();
1484 | };
1485 |
1486 | /**
1487 | * Pad the given `str` to `len`.
1488 | *
1489 | * @param {String} str
1490 | * @param {String} len
1491 | * @return {String}
1492 | * @api private
1493 | */
1494 |
1495 | function pad(str, len) {
1496 | str = String(str);
1497 | return Array(len - str.length + 1).join(' ') + str;
1498 | }
1499 |
1500 | /**
1501 | * Return a character diff for `err`.
1502 | *
1503 | * @param {Error} err
1504 | * @return {String}
1505 | * @api private
1506 | */
1507 |
1508 | function errorDiff(err, type) {
1509 | return diff['diff' + type](err.actual, err.expected).map(function(str){
1510 | if (/^(\n+)$/.test(str.value)) str.value = Array(++RegExp.$1.length).join('');
1511 | if (str.added) return colorLines('diff added', str.value);
1512 | if (str.removed) return colorLines('diff removed', str.value);
1513 | return str.value;
1514 | }).join('');
1515 | }
1516 |
1517 | /**
1518 | * Color lines for `str`, using the color `name`.
1519 | *
1520 | * @param {String} name
1521 | * @param {String} str
1522 | * @return {String}
1523 | * @api private
1524 | */
1525 |
1526 | function colorLines(name, str) {
1527 | return str.split('\n').map(function(str){
1528 | return color(name, str);
1529 | }).join('\n');
1530 | }
1531 |
1532 | }); // module: reporters/base.js
1533 |
1534 | require.register("reporters/doc.js", function(module, exports, require){
1535 |
1536 | /**
1537 | * Module dependencies.
1538 | */
1539 |
1540 | var Base = require('./base')
1541 | , utils = require('../utils');
1542 |
1543 | /**
1544 | * Expose `Doc`.
1545 | */
1546 |
1547 | exports = module.exports = Doc;
1548 |
1549 | /**
1550 | * Initialize a new `Doc` reporter.
1551 | *
1552 | * @param {Runner} runner
1553 | * @api public
1554 | */
1555 |
1556 | function Doc(runner) {
1557 | Base.call(this, runner);
1558 |
1559 | var self = this
1560 | , stats = this.stats
1561 | , total = runner.total
1562 | , indents = 2;
1563 |
1564 | function indent() {
1565 | return Array(indents).join(' ');
1566 | }
1567 |
1568 | runner.on('suite', function(suite){
1569 | if (suite.root) return;
1570 | ++indents;
1571 | console.log('%s', indent());
1572 | ++indents;
1573 | console.log('%s%s ', indent(), suite.title);
1574 | console.log('%s', indent());
1575 | });
1576 |
1577 | runner.on('suite end', function(suite){
1578 | if (suite.root) return;
1579 | console.log('%s ', indent());
1580 | --indents;
1581 | console.log('%s ', indent());
1582 | --indents;
1583 | });
1584 |
1585 | runner.on('pass', function(test){
1586 | console.log('%s %s ', indent(), test.title);
1587 | var code = utils.escape(utils.clean(test.fn.toString()));
1588 | console.log('%s %s ', indent(), code);
1589 | });
1590 | }
1591 |
1592 | }); // module: reporters/doc.js
1593 |
1594 | require.register("reporters/dot.js", function(module, exports, require){
1595 |
1596 | /**
1597 | * Module dependencies.
1598 | */
1599 |
1600 | var Base = require('./base')
1601 | , color = Base.color;
1602 |
1603 | /**
1604 | * Expose `Dot`.
1605 | */
1606 |
1607 | exports = module.exports = Dot;
1608 |
1609 | /**
1610 | * Initialize a new `Dot` matrix test reporter.
1611 | *
1612 | * @param {Runner} runner
1613 | * @api public
1614 | */
1615 |
1616 | function Dot(runner) {
1617 | Base.call(this, runner);
1618 |
1619 | var self = this
1620 | , stats = this.stats
1621 | , width = Base.window.width * .75 | 0
1622 | , c = '․'
1623 | , n = 0;
1624 |
1625 | runner.on('start', function(){
1626 | process.stdout.write('\n ');
1627 | });
1628 |
1629 | runner.on('pending', function(test){
1630 | process.stdout.write(color('pending', c));
1631 | });
1632 |
1633 | runner.on('pass', function(test){
1634 | if (++n % width == 0) process.stdout.write('\n ');
1635 | if ('slow' == test.speed) {
1636 | process.stdout.write(color('bright yellow', c));
1637 | } else {
1638 | process.stdout.write(color(test.speed, c));
1639 | }
1640 | });
1641 |
1642 | runner.on('fail', function(test, err){
1643 | if (++n % width == 0) process.stdout.write('\n ');
1644 | process.stdout.write(color('fail', c));
1645 | });
1646 |
1647 | runner.on('end', function(){
1648 | console.log();
1649 | self.epilogue();
1650 | });
1651 | }
1652 |
1653 | /**
1654 | * Inherit from `Base.prototype`.
1655 | */
1656 |
1657 | Dot.prototype = new Base;
1658 | Dot.prototype.constructor = Dot;
1659 |
1660 | }); // module: reporters/dot.js
1661 |
1662 | require.register("reporters/html-cov.js", function(module, exports, require){
1663 |
1664 | /**
1665 | * Module dependencies.
1666 | */
1667 |
1668 | var JSONCov = require('./json-cov')
1669 | , fs = require('browser/fs');
1670 |
1671 | /**
1672 | * Expose `HTMLCov`.
1673 | */
1674 |
1675 | exports = module.exports = HTMLCov;
1676 |
1677 | /**
1678 | * Initialize a new `JsCoverage` reporter.
1679 | *
1680 | * @param {Runner} runner
1681 | * @api public
1682 | */
1683 |
1684 | function HTMLCov(runner) {
1685 | var jade = require('jade')
1686 | , file = __dirname + '/templates/coverage.jade'
1687 | , str = fs.readFileSync(file, 'utf8')
1688 | , fn = jade.compile(str, { filename: file })
1689 | , self = this;
1690 |
1691 | JSONCov.call(this, runner, false);
1692 |
1693 | runner.on('end', function(){
1694 | process.stdout.write(fn({
1695 | cov: self.cov
1696 | , coverageClass: coverageClass
1697 | }));
1698 | });
1699 | }
1700 |
1701 | /**
1702 | * Return coverage class for `n`.
1703 | *
1704 | * @return {String}
1705 | * @api private
1706 | */
1707 |
1708 | function coverageClass(n) {
1709 | if (n >= 75) return 'high';
1710 | if (n >= 50) return 'medium';
1711 | if (n >= 25) return 'low';
1712 | return 'terrible';
1713 | }
1714 | }); // module: reporters/html-cov.js
1715 |
1716 | require.register("reporters/html.js", function(module, exports, require){
1717 |
1718 | /**
1719 | * Module dependencies.
1720 | */
1721 |
1722 | var Base = require('./base')
1723 | , utils = require('../utils')
1724 | , Progress = require('../browser/progress')
1725 | , escape = utils.escape;
1726 |
1727 | /**
1728 | * Save timer references to avoid Sinon interfering (see GH-237).
1729 | */
1730 |
1731 | var Date = global.Date
1732 | , setTimeout = global.setTimeout
1733 | , setInterval = global.setInterval
1734 | , clearTimeout = global.clearTimeout
1735 | , clearInterval = global.clearInterval;
1736 |
1737 | /**
1738 | * Expose `Doc`.
1739 | */
1740 |
1741 | exports = module.exports = HTML;
1742 |
1743 | /**
1744 | * Stats template.
1745 | */
1746 |
1747 | var statsTemplate = ''
1748 | + ' '
1749 | + 'passes: 0 '
1750 | + 'failures: 0 '
1751 | + 'duration: 0 s '
1752 | + ' ';
1753 |
1754 | /**
1755 | * Initialize a new `Doc` reporter.
1756 | *
1757 | * @param {Runner} runner
1758 | * @api public
1759 | */
1760 |
1761 | function HTML(runner) {
1762 | Base.call(this, runner);
1763 |
1764 | var self = this
1765 | , stats = this.stats
1766 | , total = runner.total
1767 | , root = document.getElementById('mocha')
1768 | , stat = fragment(statsTemplate)
1769 | , items = stat.getElementsByTagName('li')
1770 | , passes = items[1].getElementsByTagName('em')[0]
1771 | , passesLink = items[1].getElementsByTagName('a')[0]
1772 | , failures = items[2].getElementsByTagName('em')[0]
1773 | , failuresLink = items[2].getElementsByTagName('a')[0]
1774 | , duration = items[3].getElementsByTagName('em')[0]
1775 | , canvas = stat.getElementsByTagName('canvas')[0]
1776 | , report = fragment('')
1777 | , stack = [report]
1778 | , progress
1779 | , ctx
1780 |
1781 | if (canvas.getContext) {
1782 | var ratio = window.devicePixelRatio || 1;
1783 | canvas.style.width = canvas.width;
1784 | canvas.style.height = canvas.height;
1785 | canvas.width *= ratio;
1786 | canvas.height *= ratio;
1787 | ctx = canvas.getContext('2d');
1788 | ctx.scale(ratio, ratio);
1789 | progress = new Progress;
1790 | }
1791 |
1792 | if (!root) return error('#mocha div missing, add it to your document');
1793 |
1794 | // pass toggle
1795 | on(passesLink, 'click', function () {
1796 | var className = /pass/.test(report.className) ? '' : ' pass';
1797 | report.className = report.className.replace(/fail|pass/g, '') + className;
1798 | });
1799 |
1800 | // failure toggle
1801 | on(failuresLink, 'click', function () {
1802 | var className = /fail/.test(report.className) ? '' : ' fail';
1803 | report.className = report.className.replace(/fail|pass/g, '') + className;
1804 | });
1805 |
1806 | root.appendChild(stat);
1807 | root.appendChild(report);
1808 |
1809 | if (progress) progress.size(40);
1810 |
1811 | runner.on('suite', function(suite){
1812 | if (suite.root) return;
1813 |
1814 | // suite
1815 | var grep = '^' + encodeURIComponent(utils.escapeRegexp(suite.fullTitle()));
1816 | var url = location.protocol + '//' + location.host + location.pathname + '?grep=' + grep;
1817 | var el = fragment(' ', url, escape(suite.title));
1818 |
1819 | // container
1820 | stack[0].appendChild(el);
1821 | stack.unshift(document.createElement('ul'));
1822 | el.appendChild(stack[0]);
1823 | });
1824 |
1825 | runner.on('suite end', function(suite){
1826 | if (suite.root) return;
1827 | stack.shift();
1828 | });
1829 |
1830 | runner.on('fail', function(test, err){
1831 | if ('hook' == test.type || err.uncaught) runner.emit('test end', test);
1832 | });
1833 |
1834 | runner.on('test end', function(test){
1835 | window.scrollTo(0, document.body.scrollHeight);
1836 |
1837 | // TODO: add to stats
1838 | var percent = stats.tests / total * 100 | 0;
1839 | if (progress) progress.update(percent).draw(ctx);
1840 |
1841 | // update stats
1842 | var ms = new Date - stats.start;
1843 | text(passes, stats.passes);
1844 | text(failures, stats.failures);
1845 | text(duration, (ms / 1000).toFixed(2));
1846 |
1847 | // test
1848 | if ('passed' == test.state) {
1849 | var el = fragment('%e%ems ', test.speed, test.title, test.duration);
1850 | } else if (test.pending) {
1851 | var el = fragment('%e ', test.title);
1852 | } else {
1853 | var el = fragment('%e ', test.title);
1854 | var str = test.err.stack || test.err.toString();
1855 |
1856 | // FF / Opera do not add the message
1857 | if (!~str.indexOf(test.err.message)) {
1858 | str = test.err.message + '\n' + str;
1859 | }
1860 |
1861 | // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
1862 | // check for the result of the stringifying.
1863 | if ('[object Error]' == str) str = test.err.message;
1864 |
1865 | // Safari doesn't give you a stack. Let's at least provide a source line.
1866 | if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
1867 | str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
1868 | }
1869 |
1870 | el.appendChild(fragment('%e ', str));
1871 | }
1872 |
1873 | // toggle code
1874 | // TODO: defer
1875 | if (!test.pending) {
1876 | var h2 = el.getElementsByTagName('h2')[0];
1877 |
1878 | on(h2, 'click', function(){
1879 | pre.style.display = 'none' == pre.style.display
1880 | ? 'inline-block'
1881 | : 'none';
1882 | });
1883 |
1884 | var pre = fragment('%e ', utils.clean(test.fn.toString()));
1885 | el.appendChild(pre);
1886 | pre.style.display = 'none';
1887 | }
1888 |
1889 | stack[0].appendChild(el);
1890 | });
1891 | }
1892 |
1893 | /**
1894 | * Display error `msg`.
1895 | */
1896 |
1897 | function error(msg) {
1898 | document.body.appendChild(fragment('%s
', msg));
1899 | }
1900 |
1901 | /**
1902 | * Return a DOM fragment from `html`.
1903 | */
1904 |
1905 | function fragment(html) {
1906 | var args = arguments
1907 | , div = document.createElement('div')
1908 | , i = 1;
1909 |
1910 | div.innerHTML = html.replace(/%([se])/g, function(_, type){
1911 | switch (type) {
1912 | case 's': return String(args[i++]);
1913 | case 'e': return escape(args[i++]);
1914 | }
1915 | });
1916 |
1917 | return div.firstChild;
1918 | }
1919 |
1920 | /**
1921 | * Set `el` text to `str`.
1922 | */
1923 |
1924 | function text(el, str) {
1925 | if (el.textContent) {
1926 | el.textContent = str;
1927 | } else {
1928 | el.innerText = str;
1929 | }
1930 | }
1931 |
1932 | /**
1933 | * Listen on `event` with callback `fn`.
1934 | */
1935 |
1936 | function on(el, event, fn) {
1937 | if (el.addEventListener) {
1938 | el.addEventListener(event, fn, false);
1939 | } else {
1940 | el.attachEvent('on' + event, fn);
1941 | }
1942 | }
1943 |
1944 | }); // module: reporters/html.js
1945 |
1946 | require.register("reporters/index.js", function(module, exports, require){
1947 |
1948 | exports.Base = require('./base');
1949 | exports.Dot = require('./dot');
1950 | exports.Doc = require('./doc');
1951 | exports.TAP = require('./tap');
1952 | exports.JSON = require('./json');
1953 | exports.HTML = require('./html');
1954 | exports.List = require('./list');
1955 | exports.Min = require('./min');
1956 | exports.Spec = require('./spec');
1957 | exports.Nyan = require('./nyan');
1958 | exports.XUnit = require('./xunit');
1959 | exports.Progress = require('./progress');
1960 | exports.Landing = require('./landing');
1961 | exports.JSONCov = require('./json-cov');
1962 | exports.HTMLCov = require('./html-cov');
1963 | exports.Markdown = require('./markdown');
1964 | exports.JSONStream = require('./json-stream');
1965 | exports.Teamcity = require('./teamcity');
1966 |
1967 | }); // module: reporters/index.js
1968 |
1969 | require.register("reporters/json-cov.js", function(module, exports, require){
1970 |
1971 | /**
1972 | * Module dependencies.
1973 | */
1974 |
1975 | var Base = require('./base');
1976 |
1977 | /**
1978 | * Expose `JSONCov`.
1979 | */
1980 |
1981 | exports = module.exports = JSONCov;
1982 |
1983 | /**
1984 | * Initialize a new `JsCoverage` reporter.
1985 | *
1986 | * @param {Runner} runner
1987 | * @param {Boolean} output
1988 | * @api public
1989 | */
1990 |
1991 | function JSONCov(runner, output) {
1992 | var self = this
1993 | , output = 1 == arguments.length ? true : output;
1994 |
1995 | Base.call(this, runner);
1996 |
1997 | var tests = []
1998 | , failures = []
1999 | , passes = [];
2000 |
2001 | runner.on('test end', function(test){
2002 | tests.push(test);
2003 | });
2004 |
2005 | runner.on('pass', function(test){
2006 | passes.push(test);
2007 | });
2008 |
2009 | runner.on('fail', function(test){
2010 | failures.push(test);
2011 | });
2012 |
2013 | runner.on('end', function(){
2014 | var cov = global._$jscoverage || {};
2015 | var result = self.cov = map(cov);
2016 | result.stats = self.stats;
2017 | result.tests = tests.map(clean);
2018 | result.failures = failures.map(clean);
2019 | result.passes = passes.map(clean);
2020 | if (!output) return;
2021 | process.stdout.write(JSON.stringify(result, null, 2 ));
2022 | });
2023 | }
2024 |
2025 | /**
2026 | * Map jscoverage data to a JSON structure
2027 | * suitable for reporting.
2028 | *
2029 | * @param {Object} cov
2030 | * @return {Object}
2031 | * @api private
2032 | */
2033 |
2034 | function map(cov) {
2035 | var ret = {
2036 | instrumentation: 'node-jscoverage'
2037 | , sloc: 0
2038 | , hits: 0
2039 | , misses: 0
2040 | , coverage: 0
2041 | , files: []
2042 | };
2043 |
2044 | for (var filename in cov) {
2045 | var data = coverage(filename, cov[filename]);
2046 | ret.files.push(data);
2047 | ret.hits += data.hits;
2048 | ret.misses += data.misses;
2049 | ret.sloc += data.sloc;
2050 | }
2051 |
2052 | if (ret.sloc > 0) {
2053 | ret.coverage = (ret.hits / ret.sloc) * 100;
2054 | }
2055 |
2056 | return ret;
2057 | };
2058 |
2059 | /**
2060 | * Map jscoverage data for a single source file
2061 | * to a JSON structure suitable for reporting.
2062 | *
2063 | * @param {String} filename name of the source file
2064 | * @param {Object} data jscoverage coverage data
2065 | * @return {Object}
2066 | * @api private
2067 | */
2068 |
2069 | function coverage(filename, data) {
2070 | var ret = {
2071 | filename: filename,
2072 | coverage: 0,
2073 | hits: 0,
2074 | misses: 0,
2075 | sloc: 0,
2076 | source: {}
2077 | };
2078 |
2079 | data.source.forEach(function(line, num){
2080 | num++;
2081 |
2082 | if (data[num] === 0) {
2083 | ret.misses++;
2084 | ret.sloc++;
2085 | } else if (data[num] !== undefined) {
2086 | ret.hits++;
2087 | ret.sloc++;
2088 | }
2089 |
2090 | ret.source[num] = {
2091 | source: line
2092 | , coverage: data[num] === undefined
2093 | ? ''
2094 | : data[num]
2095 | };
2096 | });
2097 |
2098 | ret.coverage = ret.hits / ret.sloc * 100;
2099 |
2100 | return ret;
2101 | }
2102 |
2103 | /**
2104 | * Return a plain-object representation of `test`
2105 | * free of cyclic properties etc.
2106 | *
2107 | * @param {Object} test
2108 | * @return {Object}
2109 | * @api private
2110 | */
2111 |
2112 | function clean(test) {
2113 | return {
2114 | title: test.title
2115 | , fullTitle: test.fullTitle()
2116 | , duration: test.duration
2117 | }
2118 | }
2119 |
2120 | }); // module: reporters/json-cov.js
2121 |
2122 | require.register("reporters/json-stream.js", function(module, exports, require){
2123 |
2124 | /**
2125 | * Module dependencies.
2126 | */
2127 |
2128 | var Base = require('./base')
2129 | , color = Base.color;
2130 |
2131 | /**
2132 | * Expose `List`.
2133 | */
2134 |
2135 | exports = module.exports = List;
2136 |
2137 | /**
2138 | * Initialize a new `List` test reporter.
2139 | *
2140 | * @param {Runner} runner
2141 | * @api public
2142 | */
2143 |
2144 | function List(runner) {
2145 | Base.call(this, runner);
2146 |
2147 | var self = this
2148 | , stats = this.stats
2149 | , total = runner.total;
2150 |
2151 | runner.on('start', function(){
2152 | console.log(JSON.stringify(['start', { total: total }]));
2153 | });
2154 |
2155 | runner.on('pass', function(test){
2156 | console.log(JSON.stringify(['pass', clean(test)]));
2157 | });
2158 |
2159 | runner.on('fail', function(test, err){
2160 | console.log(JSON.stringify(['fail', clean(test)]));
2161 | });
2162 |
2163 | runner.on('end', function(){
2164 | process.stdout.write(JSON.stringify(['end', self.stats]));
2165 | });
2166 | }
2167 |
2168 | /**
2169 | * Return a plain-object representation of `test`
2170 | * free of cyclic properties etc.
2171 | *
2172 | * @param {Object} test
2173 | * @return {Object}
2174 | * @api private
2175 | */
2176 |
2177 | function clean(test) {
2178 | return {
2179 | title: test.title
2180 | , fullTitle: test.fullTitle()
2181 | , duration: test.duration
2182 | }
2183 | }
2184 | }); // module: reporters/json-stream.js
2185 |
2186 | require.register("reporters/json.js", function(module, exports, require){
2187 |
2188 | /**
2189 | * Module dependencies.
2190 | */
2191 |
2192 | var Base = require('./base')
2193 | , cursor = Base.cursor
2194 | , color = Base.color;
2195 |
2196 | /**
2197 | * Expose `JSON`.
2198 | */
2199 |
2200 | exports = module.exports = JSONReporter;
2201 |
2202 | /**
2203 | * Initialize a new `JSON` reporter.
2204 | *
2205 | * @param {Runner} runner
2206 | * @api public
2207 | */
2208 |
2209 | function JSONReporter(runner) {
2210 | var self = this;
2211 | Base.call(this, runner);
2212 |
2213 | var tests = []
2214 | , failures = []
2215 | , passes = [];
2216 |
2217 | runner.on('test end', function(test){
2218 | tests.push(test);
2219 | });
2220 |
2221 | runner.on('pass', function(test){
2222 | passes.push(test);
2223 | });
2224 |
2225 | runner.on('fail', function(test){
2226 | failures.push(test);
2227 | });
2228 |
2229 | runner.on('end', function(){
2230 | var obj = {
2231 | stats: self.stats
2232 | , tests: tests.map(clean)
2233 | , failures: failures.map(clean)
2234 | , passes: passes.map(clean)
2235 | };
2236 |
2237 | process.stdout.write(JSON.stringify(obj, null, 2));
2238 | });
2239 | }
2240 |
2241 | /**
2242 | * Return a plain-object representation of `test`
2243 | * free of cyclic properties etc.
2244 | *
2245 | * @param {Object} test
2246 | * @return {Object}
2247 | * @api private
2248 | */
2249 |
2250 | function clean(test) {
2251 | return {
2252 | title: test.title
2253 | , fullTitle: test.fullTitle()
2254 | , duration: test.duration
2255 | }
2256 | }
2257 | }); // module: reporters/json.js
2258 |
2259 | require.register("reporters/landing.js", function(module, exports, require){
2260 |
2261 | /**
2262 | * Module dependencies.
2263 | */
2264 |
2265 | var Base = require('./base')
2266 | , cursor = Base.cursor
2267 | , color = Base.color;
2268 |
2269 | /**
2270 | * Expose `Landing`.
2271 | */
2272 |
2273 | exports = module.exports = Landing;
2274 |
2275 | /**
2276 | * Airplane color.
2277 | */
2278 |
2279 | Base.colors.plane = 0;
2280 |
2281 | /**
2282 | * Airplane crash color.
2283 | */
2284 |
2285 | Base.colors['plane crash'] = 31;
2286 |
2287 | /**
2288 | * Runway color.
2289 | */
2290 |
2291 | Base.colors.runway = 90;
2292 |
2293 | /**
2294 | * Initialize a new `Landing` reporter.
2295 | *
2296 | * @param {Runner} runner
2297 | * @api public
2298 | */
2299 |
2300 | function Landing(runner) {
2301 | Base.call(this, runner);
2302 |
2303 | var self = this
2304 | , stats = this.stats
2305 | , width = Base.window.width * .75 | 0
2306 | , total = runner.total
2307 | , stream = process.stdout
2308 | , plane = color('plane', '✈')
2309 | , crashed = -1
2310 | , n = 0;
2311 |
2312 | function runway() {
2313 | var buf = Array(width).join('-');
2314 | return ' ' + color('runway', buf);
2315 | }
2316 |
2317 | runner.on('start', function(){
2318 | stream.write('\n ');
2319 | cursor.hide();
2320 | });
2321 |
2322 | runner.on('test end', function(test){
2323 | // check if the plane crashed
2324 | var col = -1 == crashed
2325 | ? width * ++n / total | 0
2326 | : crashed;
2327 |
2328 | // show the crash
2329 | if ('failed' == test.state) {
2330 | plane = color('plane crash', '✈');
2331 | crashed = col;
2332 | }
2333 |
2334 | // render landing strip
2335 | stream.write('\u001b[4F\n\n');
2336 | stream.write(runway());
2337 | stream.write('\n ');
2338 | stream.write(color('runway', Array(col).join('⋅')));
2339 | stream.write(plane)
2340 | stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
2341 | stream.write(runway());
2342 | stream.write('\u001b[0m');
2343 | });
2344 |
2345 | runner.on('end', function(){
2346 | cursor.show();
2347 | console.log();
2348 | self.epilogue();
2349 | });
2350 | }
2351 |
2352 | /**
2353 | * Inherit from `Base.prototype`.
2354 | */
2355 |
2356 | Landing.prototype = new Base;
2357 | Landing.prototype.constructor = Landing;
2358 |
2359 | }); // module: reporters/landing.js
2360 |
2361 | require.register("reporters/list.js", function(module, exports, require){
2362 |
2363 | /**
2364 | * Module dependencies.
2365 | */
2366 |
2367 | var Base = require('./base')
2368 | , cursor = Base.cursor
2369 | , color = Base.color;
2370 |
2371 | /**
2372 | * Expose `List`.
2373 | */
2374 |
2375 | exports = module.exports = List;
2376 |
2377 | /**
2378 | * Initialize a new `List` test reporter.
2379 | *
2380 | * @param {Runner} runner
2381 | * @api public
2382 | */
2383 |
2384 | function List(runner) {
2385 | Base.call(this, runner);
2386 |
2387 | var self = this
2388 | , stats = this.stats
2389 | , n = 0;
2390 |
2391 | runner.on('start', function(){
2392 | console.log();
2393 | });
2394 |
2395 | runner.on('test', function(test){
2396 | process.stdout.write(color('pass', ' ' + test.fullTitle() + ': '));
2397 | });
2398 |
2399 | runner.on('pending', function(test){
2400 | var fmt = color('checkmark', ' -')
2401 | + color('pending', ' %s');
2402 | console.log(fmt, test.fullTitle());
2403 | });
2404 |
2405 | runner.on('pass', function(test){
2406 | var fmt = color('checkmark', ' ✓')
2407 | + color('pass', ' %s: ')
2408 | + color(test.speed, '%dms');
2409 | cursor.CR();
2410 | console.log(fmt, test.fullTitle(), test.duration);
2411 | });
2412 |
2413 | runner.on('fail', function(test, err){
2414 | cursor.CR();
2415 | console.log(color('fail', ' %d) %s'), ++n, test.fullTitle());
2416 | });
2417 |
2418 | runner.on('end', self.epilogue.bind(self));
2419 | }
2420 |
2421 | /**
2422 | * Inherit from `Base.prototype`.
2423 | */
2424 |
2425 | List.prototype = new Base;
2426 | List.prototype.constructor = List;
2427 |
2428 |
2429 | }); // module: reporters/list.js
2430 |
2431 | require.register("reporters/markdown.js", function(module, exports, require){
2432 | /**
2433 | * Module dependencies.
2434 | */
2435 |
2436 | var Base = require('./base')
2437 | , utils = require('../utils');
2438 |
2439 | /**
2440 | * Expose `Markdown`.
2441 | */
2442 |
2443 | exports = module.exports = Markdown;
2444 |
2445 | /**
2446 | * Initialize a new `Markdown` reporter.
2447 | *
2448 | * @param {Runner} runner
2449 | * @api public
2450 | */
2451 |
2452 | function Markdown(runner) {
2453 | Base.call(this, runner);
2454 |
2455 | var self = this
2456 | , stats = this.stats
2457 | , total = runner.total
2458 | , level = 0
2459 | , buf = '';
2460 |
2461 | function title(str) {
2462 | return Array(level).join('#') + ' ' + str;
2463 | }
2464 |
2465 | function indent() {
2466 | return Array(level).join(' ');
2467 | }
2468 |
2469 | function mapTOC(suite, obj) {
2470 | var ret = obj;
2471 | obj = obj[suite.title] = obj[suite.title] || { suite: suite };
2472 | suite.suites.forEach(function(suite){
2473 | mapTOC(suite, obj);
2474 | });
2475 | return ret;
2476 | }
2477 |
2478 | function stringifyTOC(obj, level) {
2479 | ++level;
2480 | var buf = '';
2481 | var link;
2482 | for (var key in obj) {
2483 | if ('suite' == key) continue;
2484 | if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
2485 | if (key) buf += Array(level).join(' ') + link;
2486 | buf += stringifyTOC(obj[key], level);
2487 | }
2488 | --level;
2489 | return buf;
2490 | }
2491 |
2492 | function generateTOC(suite) {
2493 | var obj = mapTOC(suite, {});
2494 | return stringifyTOC(obj, 0);
2495 | }
2496 |
2497 | generateTOC(runner.suite);
2498 |
2499 | runner.on('suite', function(suite){
2500 | ++level;
2501 | var slug = utils.slug(suite.fullTitle());
2502 | buf += ' ' + '\n';
2503 | buf += title(suite.title) + '\n';
2504 | });
2505 |
2506 | runner.on('suite end', function(suite){
2507 | --level;
2508 | });
2509 |
2510 | runner.on('pass', function(test){
2511 | var code = utils.clean(test.fn.toString());
2512 | buf += test.title + '.\n';
2513 | buf += '\n```js\n';
2514 | buf += code + '\n';
2515 | buf += '```\n\n';
2516 | });
2517 |
2518 | runner.on('end', function(){
2519 | console.log('# TOC\n');
2520 | console.log(generateTOC(runner.suite));
2521 | console.log(buf);
2522 | });
2523 | }
2524 | }); // module: reporters/markdown.js
2525 |
2526 | require.register("reporters/min.js", function(module, exports, require){
2527 |
2528 | /**
2529 | * Module dependencies.
2530 | */
2531 |
2532 | var Base = require('./base');
2533 |
2534 | /**
2535 | * Expose `Min`.
2536 | */
2537 |
2538 | exports = module.exports = Min;
2539 |
2540 | /**
2541 | * Initialize a new `Min` minimal test reporter (best used with --watch).
2542 | *
2543 | * @param {Runner} runner
2544 | * @api public
2545 | */
2546 |
2547 | function Min(runner) {
2548 | Base.call(this, runner);
2549 |
2550 | runner.on('start', function(){
2551 | // clear screen
2552 | process.stdout.write('\u001b[2J');
2553 | // set cursor position
2554 | process.stdout.write('\u001b[1;3H');
2555 | });
2556 |
2557 | runner.on('end', this.epilogue.bind(this));
2558 | }
2559 |
2560 | /**
2561 | * Inherit from `Base.prototype`.
2562 | */
2563 |
2564 | Min.prototype = new Base;
2565 | Min.prototype.constructor = Min;
2566 |
2567 | }); // module: reporters/min.js
2568 |
2569 | require.register("reporters/nyan.js", function(module, exports, require){
2570 |
2571 | /**
2572 | * Module dependencies.
2573 | */
2574 |
2575 | var Base = require('./base')
2576 | , color = Base.color;
2577 |
2578 | /**
2579 | * Expose `Dot`.
2580 | */
2581 |
2582 | exports = module.exports = NyanCat;
2583 |
2584 | /**
2585 | * Initialize a new `Dot` matrix test reporter.
2586 | *
2587 | * @param {Runner} runner
2588 | * @api public
2589 | */
2590 |
2591 | function NyanCat(runner) {
2592 | Base.call(this, runner);
2593 |
2594 | var self = this
2595 | , stats = this.stats
2596 | , width = Base.window.width * .75 | 0
2597 | , rainbowColors = this.rainbowColors = self.generateColors()
2598 | , colorIndex = this.colorIndex = 0
2599 | , numerOfLines = this.numberOfLines = 4
2600 | , trajectories = this.trajectories = [[], [], [], []]
2601 | , nyanCatWidth = this.nyanCatWidth = 11
2602 | , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth)
2603 | , scoreboardWidth = this.scoreboardWidth = 5
2604 | , tick = this.tick = 0
2605 | , n = 0;
2606 |
2607 | runner.on('start', function(){
2608 | Base.cursor.hide();
2609 | self.draw('start');
2610 | });
2611 |
2612 | runner.on('pending', function(test){
2613 | self.draw('pending');
2614 | });
2615 |
2616 | runner.on('pass', function(test){
2617 | self.draw('pass');
2618 | });
2619 |
2620 | runner.on('fail', function(test, err){
2621 | self.draw('fail');
2622 | });
2623 |
2624 | runner.on('end', function(){
2625 | Base.cursor.show();
2626 | for (var i = 0; i < self.numberOfLines; i++) write('\n');
2627 | self.epilogue();
2628 | });
2629 | }
2630 |
2631 | /**
2632 | * Draw the nyan cat with runner `status`.
2633 | *
2634 | * @param {String} status
2635 | * @api private
2636 | */
2637 |
2638 | NyanCat.prototype.draw = function(status){
2639 | this.appendRainbow();
2640 | this.drawScoreboard();
2641 | this.drawRainbow();
2642 | this.drawNyanCat(status);
2643 | this.tick = !this.tick;
2644 | };
2645 |
2646 | /**
2647 | * Draw the "scoreboard" showing the number
2648 | * of passes, failures and pending tests.
2649 | *
2650 | * @api private
2651 | */
2652 |
2653 | NyanCat.prototype.drawScoreboard = function(){
2654 | var stats = this.stats;
2655 | var colors = Base.colors;
2656 |
2657 | function draw(color, n) {
2658 | write(' ');
2659 | write('\u001b[' + color + 'm' + n + '\u001b[0m');
2660 | write('\n');
2661 | }
2662 |
2663 | draw(colors.green, stats.passes);
2664 | draw(colors.fail, stats.failures);
2665 | draw(colors.pending, stats.pending);
2666 | write('\n');
2667 |
2668 | this.cursorUp(this.numberOfLines);
2669 | };
2670 |
2671 | /**
2672 | * Append the rainbow.
2673 | *
2674 | * @api private
2675 | */
2676 |
2677 | NyanCat.prototype.appendRainbow = function(){
2678 | var segment = this.tick ? '_' : '-';
2679 | var rainbowified = this.rainbowify(segment);
2680 |
2681 | for (var index = 0; index < this.numberOfLines; index++) {
2682 | var trajectory = this.trajectories[index];
2683 | if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();
2684 | trajectory.push(rainbowified);
2685 | }
2686 | };
2687 |
2688 | /**
2689 | * Draw the rainbow.
2690 | *
2691 | * @api private
2692 | */
2693 |
2694 | NyanCat.prototype.drawRainbow = function(){
2695 | var self = this;
2696 |
2697 | this.trajectories.forEach(function(line, index) {
2698 | write('\u001b[' + self.scoreboardWidth + 'C');
2699 | write(line.join(''));
2700 | write('\n');
2701 | });
2702 |
2703 | this.cursorUp(this.numberOfLines);
2704 | };
2705 |
2706 | /**
2707 | * Draw the nyan cat with `status`.
2708 | *
2709 | * @param {String} status
2710 | * @api private
2711 | */
2712 |
2713 | NyanCat.prototype.drawNyanCat = function(status) {
2714 | var self = this;
2715 | var startWidth = this.scoreboardWidth + this.trajectories[0].length;
2716 |
2717 | [0, 1, 2, 3].forEach(function(index) {
2718 | write('\u001b[' + startWidth + 'C');
2719 |
2720 | switch (index) {
2721 | case 0:
2722 | write('_,------,');
2723 | write('\n');
2724 | break;
2725 | case 1:
2726 | var padding = self.tick ? ' ' : ' ';
2727 | write('_|' + padding + '/\\_/\\ ');
2728 | write('\n');
2729 | break;
2730 | case 2:
2731 | var padding = self.tick ? '_' : '__';
2732 | var tail = self.tick ? '~' : '^';
2733 | var face;
2734 | switch (status) {
2735 | case 'pass':
2736 | face = '( ^ .^)';
2737 | break;
2738 | case 'fail':
2739 | face = '( o .o)';
2740 | break;
2741 | default:
2742 | face = '( - .-)';
2743 | }
2744 | write(tail + '|' + padding + face + ' ');
2745 | write('\n');
2746 | break;
2747 | case 3:
2748 | var padding = self.tick ? ' ' : ' ';
2749 | write(padding + '"" "" ');
2750 | write('\n');
2751 | break;
2752 | }
2753 | });
2754 |
2755 | this.cursorUp(this.numberOfLines);
2756 | };
2757 |
2758 | /**
2759 | * Move cursor up `n`.
2760 | *
2761 | * @param {Number} n
2762 | * @api private
2763 | */
2764 |
2765 | NyanCat.prototype.cursorUp = function(n) {
2766 | write('\u001b[' + n + 'A');
2767 | };
2768 |
2769 | /**
2770 | * Move cursor down `n`.
2771 | *
2772 | * @param {Number} n
2773 | * @api private
2774 | */
2775 |
2776 | NyanCat.prototype.cursorDown = function(n) {
2777 | write('\u001b[' + n + 'B');
2778 | };
2779 |
2780 | /**
2781 | * Generate rainbow colors.
2782 | *
2783 | * @return {Array}
2784 | * @api private
2785 | */
2786 |
2787 | NyanCat.prototype.generateColors = function(){
2788 | var colors = [];
2789 |
2790 | for (var i = 0; i < (6 * 7); i++) {
2791 | var pi3 = Math.floor(Math.PI / 3);
2792 | var n = (i * (1.0 / 6));
2793 | var r = Math.floor(3 * Math.sin(n) + 3);
2794 | var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);
2795 | var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);
2796 | colors.push(36 * r + 6 * g + b + 16);
2797 | }
2798 |
2799 | return colors;
2800 | };
2801 |
2802 | /**
2803 | * Apply rainbow to the given `str`.
2804 | *
2805 | * @param {String} str
2806 | * @return {String}
2807 | * @api private
2808 | */
2809 |
2810 | NyanCat.prototype.rainbowify = function(str){
2811 | var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
2812 | this.colorIndex += 1;
2813 | return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m';
2814 | };
2815 |
2816 | /**
2817 | * Stdout helper.
2818 | */
2819 |
2820 | function write(string) {
2821 | process.stdout.write(string);
2822 | }
2823 |
2824 | /**
2825 | * Inherit from `Base.prototype`.
2826 | */
2827 |
2828 | NyanCat.prototype = new Base;
2829 | NyanCat.prototype.constructor = NyanCat;
2830 |
2831 |
2832 | }); // module: reporters/nyan.js
2833 |
2834 | require.register("reporters/progress.js", function(module, exports, require){
2835 |
2836 | /**
2837 | * Module dependencies.
2838 | */
2839 |
2840 | var Base = require('./base')
2841 | , cursor = Base.cursor
2842 | , color = Base.color;
2843 |
2844 | /**
2845 | * Expose `Progress`.
2846 | */
2847 |
2848 | exports = module.exports = Progress;
2849 |
2850 | /**
2851 | * General progress bar color.
2852 | */
2853 |
2854 | Base.colors.progress = 90;
2855 |
2856 | /**
2857 | * Initialize a new `Progress` bar test reporter.
2858 | *
2859 | * @param {Runner} runner
2860 | * @param {Object} options
2861 | * @api public
2862 | */
2863 |
2864 | function Progress(runner, options) {
2865 | Base.call(this, runner);
2866 |
2867 | var self = this
2868 | , options = options || {}
2869 | , stats = this.stats
2870 | , width = Base.window.width * .50 | 0
2871 | , total = runner.total
2872 | , complete = 0
2873 | , max = Math.max;
2874 |
2875 | // default chars
2876 | options.open = options.open || '[';
2877 | options.complete = options.complete || '▬';
2878 | options.incomplete = options.incomplete || '⋅';
2879 | options.close = options.close || ']';
2880 | options.verbose = false;
2881 |
2882 | // tests started
2883 | runner.on('start', function(){
2884 | console.log();
2885 | cursor.hide();
2886 | });
2887 |
2888 | // tests complete
2889 | runner.on('test end', function(){
2890 | complete++;
2891 | var incomplete = total - complete
2892 | , percent = complete / total
2893 | , n = width * percent | 0
2894 | , i = width - n;
2895 |
2896 | cursor.CR();
2897 | process.stdout.write('\u001b[J');
2898 | process.stdout.write(color('progress', ' ' + options.open));
2899 | process.stdout.write(Array(n).join(options.complete));
2900 | process.stdout.write(Array(i).join(options.incomplete));
2901 | process.stdout.write(color('progress', options.close));
2902 | if (options.verbose) {
2903 | process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
2904 | }
2905 | });
2906 |
2907 | // tests are complete, output some stats
2908 | // and the failures if any
2909 | runner.on('end', function(){
2910 | cursor.show();
2911 | console.log();
2912 | self.epilogue();
2913 | });
2914 | }
2915 |
2916 | /**
2917 | * Inherit from `Base.prototype`.
2918 | */
2919 |
2920 | Progress.prototype = new Base;
2921 | Progress.prototype.constructor = Progress;
2922 |
2923 |
2924 | }); // module: reporters/progress.js
2925 |
2926 | require.register("reporters/spec.js", function(module, exports, require){
2927 |
2928 | /**
2929 | * Module dependencies.
2930 | */
2931 |
2932 | var Base = require('./base')
2933 | , cursor = Base.cursor
2934 | , color = Base.color;
2935 |
2936 | /**
2937 | * Expose `Spec`.
2938 | */
2939 |
2940 | exports = module.exports = Spec;
2941 |
2942 | /**
2943 | * Initialize a new `Spec` test reporter.
2944 | *
2945 | * @param {Runner} runner
2946 | * @api public
2947 | */
2948 |
2949 | function Spec(runner) {
2950 | Base.call(this, runner);
2951 |
2952 | var self = this
2953 | , stats = this.stats
2954 | , indents = 0
2955 | , n = 0;
2956 |
2957 | function indent() {
2958 | return Array(indents).join(' ')
2959 | }
2960 |
2961 | runner.on('start', function(){
2962 | console.log();
2963 | });
2964 |
2965 | runner.on('suite', function(suite){
2966 | ++indents;
2967 | console.log(color('suite', '%s%s'), indent(), suite.title);
2968 | });
2969 |
2970 | runner.on('suite end', function(suite){
2971 | --indents;
2972 | if (1 == indents) console.log();
2973 | });
2974 |
2975 | runner.on('test', function(test){
2976 | process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': '));
2977 | });
2978 |
2979 | runner.on('pending', function(test){
2980 | var fmt = indent() + color('pending', ' - %s');
2981 | console.log(fmt, test.title);
2982 | });
2983 |
2984 | runner.on('pass', function(test){
2985 | if ('fast' == test.speed) {
2986 | var fmt = indent()
2987 | + color('checkmark', ' ✓')
2988 | + color('pass', ' %s ');
2989 | cursor.CR();
2990 | console.log(fmt, test.title);
2991 | } else {
2992 | var fmt = indent()
2993 | + color('checkmark', ' ✓')
2994 | + color('pass', ' %s ')
2995 | + color(test.speed, '(%dms)');
2996 | cursor.CR();
2997 | console.log(fmt, test.title, test.duration);
2998 | }
2999 | });
3000 |
3001 | runner.on('fail', function(test, err){
3002 | cursor.CR();
3003 | console.log(indent() + color('fail', ' %d) %s'), ++n, test.title);
3004 | });
3005 |
3006 | runner.on('end', self.epilogue.bind(self));
3007 | }
3008 |
3009 | /**
3010 | * Inherit from `Base.prototype`.
3011 | */
3012 |
3013 | Spec.prototype = new Base;
3014 | Spec.prototype.constructor = Spec;
3015 |
3016 |
3017 | }); // module: reporters/spec.js
3018 |
3019 | require.register("reporters/tap.js", function(module, exports, require){
3020 |
3021 | /**
3022 | * Module dependencies.
3023 | */
3024 |
3025 | var Base = require('./base')
3026 | , cursor = Base.cursor
3027 | , color = Base.color;
3028 |
3029 | /**
3030 | * Expose `TAP`.
3031 | */
3032 |
3033 | exports = module.exports = TAP;
3034 |
3035 | /**
3036 | * Initialize a new `TAP` reporter.
3037 | *
3038 | * @param {Runner} runner
3039 | * @api public
3040 | */
3041 |
3042 | function TAP(runner) {
3043 | Base.call(this, runner);
3044 |
3045 | var self = this
3046 | , stats = this.stats
3047 | , total = runner.total
3048 | , n = 1;
3049 |
3050 | runner.on('start', function(){
3051 | console.log('%d..%d', 1, total);
3052 | });
3053 |
3054 | runner.on('test end', function(){
3055 | ++n;
3056 | });
3057 |
3058 | runner.on('pending', function(test){
3059 | console.log('ok %d %s # SKIP -', n, title(test));
3060 | });
3061 |
3062 | runner.on('pass', function(test){
3063 | console.log('ok %d %s', n, title(test));
3064 | });
3065 |
3066 | runner.on('fail', function(test, err){
3067 | console.log('not ok %d %s', n, title(test));
3068 | console.log(err.stack.replace(/^/gm, ' '));
3069 | });
3070 | }
3071 |
3072 | /**
3073 | * Return a TAP-safe title of `test`
3074 | *
3075 | * @param {Object} test
3076 | * @return {String}
3077 | * @api private
3078 | */
3079 |
3080 | function title(test) {
3081 | return test.fullTitle().replace(/#/g, '');
3082 | }
3083 |
3084 | }); // module: reporters/tap.js
3085 |
3086 | require.register("reporters/teamcity.js", function(module, exports, require){
3087 |
3088 | /**
3089 | * Module dependencies.
3090 | */
3091 |
3092 | var Base = require('./base');
3093 |
3094 | /**
3095 | * Expose `Teamcity`.
3096 | */
3097 |
3098 | exports = module.exports = Teamcity;
3099 |
3100 | /**
3101 | * Initialize a new `Teamcity` reporter.
3102 | *
3103 | * @param {Runner} runner
3104 | * @api public
3105 | */
3106 |
3107 | function Teamcity(runner) {
3108 | Base.call(this, runner);
3109 | var stats = this.stats;
3110 |
3111 | runner.on('start', function() {
3112 | console.log("##teamcity[testSuiteStarted name='mocha.suite']");
3113 | });
3114 |
3115 | runner.on('test', function(test) {
3116 | console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']");
3117 | });
3118 |
3119 | runner.on('fail', function(test, err) {
3120 | console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']");
3121 | });
3122 |
3123 | runner.on('pending', function(test) {
3124 | console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']");
3125 | });
3126 |
3127 | runner.on('test end', function(test) {
3128 | console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']");
3129 | });
3130 |
3131 | runner.on('end', function() {
3132 | console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']");
3133 | });
3134 | }
3135 |
3136 | /**
3137 | * Escape the given `str`.
3138 | */
3139 |
3140 | function escape(str) {
3141 | return str
3142 | .replace(/\|/g, "||")
3143 | .replace(/\n/g, "|n")
3144 | .replace(/\r/g, "|r")
3145 | .replace(/\[/g, "|[")
3146 | .replace(/\]/g, "|]")
3147 | .replace(/\u0085/g, "|x")
3148 | .replace(/\u2028/g, "|l")
3149 | .replace(/\u2029/g, "|p")
3150 | .replace(/'/g, "|'");
3151 | }
3152 |
3153 | }); // module: reporters/teamcity.js
3154 |
3155 | require.register("reporters/xunit.js", function(module, exports, require){
3156 |
3157 | /**
3158 | * Module dependencies.
3159 | */
3160 |
3161 | var Base = require('./base')
3162 | , utils = require('../utils')
3163 | , escape = utils.escape;
3164 |
3165 | /**
3166 | * Save timer references to avoid Sinon interfering (see GH-237).
3167 | */
3168 |
3169 | var Date = global.Date
3170 | , setTimeout = global.setTimeout
3171 | , setInterval = global.setInterval
3172 | , clearTimeout = global.clearTimeout
3173 | , clearInterval = global.clearInterval;
3174 |
3175 | /**
3176 | * Expose `XUnit`.
3177 | */
3178 |
3179 | exports = module.exports = XUnit;
3180 |
3181 | /**
3182 | * Initialize a new `XUnit` reporter.
3183 | *
3184 | * @param {Runner} runner
3185 | * @api public
3186 | */
3187 |
3188 | function XUnit(runner) {
3189 | Base.call(this, runner);
3190 | var stats = this.stats
3191 | , tests = []
3192 | , self = this;
3193 |
3194 | runner.on('pass', function(test){
3195 | tests.push(test);
3196 | });
3197 |
3198 | runner.on('fail', function(test){
3199 | tests.push(test);
3200 | });
3201 |
3202 | runner.on('end', function(){
3203 | console.log(tag('testsuite', {
3204 | name: 'Mocha Tests'
3205 | , tests: stats.tests
3206 | , failures: stats.failures
3207 | , errors: stats.failures
3208 | , skip: stats.tests - stats.failures - stats.passes
3209 | , timestamp: (new Date).toUTCString()
3210 | , time: stats.duration / 1000
3211 | }, false));
3212 |
3213 | tests.forEach(test);
3214 | console.log('');
3215 | });
3216 | }
3217 |
3218 | /**
3219 | * Inherit from `Base.prototype`.
3220 | */
3221 |
3222 | XUnit.prototype = new Base;
3223 | XUnit.prototype.constructor = XUnit;
3224 |
3225 |
3226 | /**
3227 | * Output tag for the given `test.`
3228 | */
3229 |
3230 | function test(test) {
3231 | var attrs = {
3232 | classname: test.parent.fullTitle()
3233 | , name: test.title
3234 | , time: test.duration / 1000
3235 | };
3236 |
3237 | if ('failed' == test.state) {
3238 | var err = test.err;
3239 | attrs.message = escape(err.message);
3240 | console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
3241 | } else if (test.pending) {
3242 | console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
3243 | } else {
3244 | console.log(tag('testcase', attrs, true) );
3245 | }
3246 | }
3247 |
3248 | /**
3249 | * HTML tag helper.
3250 | */
3251 |
3252 | function tag(name, attrs, close, content) {
3253 | var end = close ? '/>' : '>'
3254 | , pairs = []
3255 | , tag;
3256 |
3257 | for (var key in attrs) {
3258 | pairs.push(key + '="' + escape(attrs[key]) + '"');
3259 | }
3260 |
3261 | tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
3262 | if (content) tag += content + '' + name + end;
3263 | return tag;
3264 | }
3265 |
3266 | /**
3267 | * Return cdata escaped CDATA `str`.
3268 | */
3269 |
3270 | function cdata(str) {
3271 | return '';
3272 | }
3273 |
3274 | }); // module: reporters/xunit.js
3275 |
3276 | require.register("runnable.js", function(module, exports, require){
3277 |
3278 | /**
3279 | * Module dependencies.
3280 | */
3281 |
3282 | var EventEmitter = require('browser/events').EventEmitter
3283 | , debug = require('browser/debug')('mocha:runnable');
3284 |
3285 | /**
3286 | * Save timer references to avoid Sinon interfering (see GH-237).
3287 | */
3288 |
3289 | var Date = global.Date
3290 | , setTimeout = global.setTimeout
3291 | , setInterval = global.setInterval
3292 | , clearTimeout = global.clearTimeout
3293 | , clearInterval = global.clearInterval;
3294 |
3295 | /**
3296 | * Expose `Runnable`.
3297 | */
3298 |
3299 | module.exports = Runnable;
3300 |
3301 | /**
3302 | * Initialize a new `Runnable` with the given `title` and callback `fn`.
3303 | *
3304 | * @param {String} title
3305 | * @param {Function} fn
3306 | * @api private
3307 | */
3308 |
3309 | function Runnable(title, fn) {
3310 | this.title = title;
3311 | this.fn = fn;
3312 | this.async = fn && fn.length;
3313 | this.sync = ! this.async;
3314 | this._timeout = 2000;
3315 | this.timedOut = false;
3316 | }
3317 |
3318 | /**
3319 | * Inherit from `EventEmitter.prototype`.
3320 | */
3321 |
3322 | Runnable.prototype = new EventEmitter;
3323 | Runnable.prototype.constructor = Runnable;
3324 |
3325 |
3326 | /**
3327 | * Set & get timeout `ms`.
3328 | *
3329 | * @param {Number} ms
3330 | * @return {Runnable|Number} ms or self
3331 | * @api private
3332 | */
3333 |
3334 | Runnable.prototype.timeout = function(ms){
3335 | if (0 == arguments.length) return this._timeout;
3336 | debug('timeout %d', ms);
3337 | this._timeout = ms;
3338 | if (this.timer) this.resetTimeout();
3339 | return this;
3340 | };
3341 |
3342 | /**
3343 | * Return the full title generated by recursively
3344 | * concatenating the parent's full title.
3345 | *
3346 | * @return {String}
3347 | * @api public
3348 | */
3349 |
3350 | Runnable.prototype.fullTitle = function(){
3351 | return this.parent.fullTitle() + ' ' + this.title;
3352 | };
3353 |
3354 | /**
3355 | * Clear the timeout.
3356 | *
3357 | * @api private
3358 | */
3359 |
3360 | Runnable.prototype.clearTimeout = function(){
3361 | clearTimeout(this.timer);
3362 | };
3363 |
3364 | /**
3365 | * Inspect the runnable void of private properties.
3366 | *
3367 | * @return {String}
3368 | * @api private
3369 | */
3370 |
3371 | Runnable.prototype.inspect = function(){
3372 | return JSON.stringify(this, function(key, val){
3373 | if ('_' == key[0]) return;
3374 | if ('parent' == key) return '#';
3375 | if ('ctx' == key) return '#';
3376 | return val;
3377 | }, 2);
3378 | };
3379 |
3380 | /**
3381 | * Reset the timeout.
3382 | *
3383 | * @api private
3384 | */
3385 |
3386 | Runnable.prototype.resetTimeout = function(){
3387 | var self = this
3388 | , ms = this.timeout();
3389 |
3390 | this.clearTimeout();
3391 | if (ms) {
3392 | this.timer = setTimeout(function(){
3393 | self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
3394 | self.timedOut = true;
3395 | }, ms);
3396 | }
3397 | };
3398 |
3399 | /**
3400 | * Run the test and invoke `fn(err)`.
3401 | *
3402 | * @param {Function} fn
3403 | * @api private
3404 | */
3405 |
3406 | Runnable.prototype.run = function(fn){
3407 | var self = this
3408 | , ms = this.timeout()
3409 | , start = new Date
3410 | , ctx = this.ctx
3411 | , finished
3412 | , emitted;
3413 |
3414 | if (ctx) ctx.runnable(this);
3415 |
3416 | // timeout
3417 | if (this.async) {
3418 | if (ms) {
3419 | this.timer = setTimeout(function(){
3420 | done(new Error('timeout of ' + ms + 'ms exceeded'));
3421 | self.timedOut = true;
3422 | }, ms);
3423 | }
3424 | }
3425 |
3426 | // called multiple times
3427 | function multiple(err) {
3428 | if (emitted) return;
3429 | emitted = true;
3430 | self.emit('error', err || new Error('done() called multiple times'));
3431 | }
3432 |
3433 | // finished
3434 | function done(err) {
3435 | if (self.timedOut) return;
3436 | if (finished) return multiple(err);
3437 | self.clearTimeout();
3438 | self.duration = new Date - start;
3439 | finished = true;
3440 | fn(err);
3441 | }
3442 |
3443 | // for .resetTimeout()
3444 | this.callback = done;
3445 |
3446 | // async
3447 | if (this.async) {
3448 | try {
3449 | this.fn.call(ctx, function(err){
3450 | if (err instanceof Error) return done(err);
3451 | if (null != err) return done(new Error('done() invoked with non-Error: ' + err));
3452 | done();
3453 | });
3454 | } catch (err) {
3455 | done(err);
3456 | }
3457 | return;
3458 | }
3459 |
3460 | // sync
3461 | try {
3462 | if (!this.pending) this.fn.call(ctx);
3463 | this.duration = new Date - start;
3464 | fn();
3465 | } catch (err) {
3466 | fn(err);
3467 | }
3468 | };
3469 |
3470 | }); // module: runnable.js
3471 |
3472 | require.register("runner.js", function(module, exports, require){
3473 |
3474 | /**
3475 | * Module dependencies.
3476 | */
3477 |
3478 | var EventEmitter = require('browser/events').EventEmitter
3479 | , debug = require('browser/debug')('mocha:runner')
3480 | , Test = require('./test')
3481 | , utils = require('./utils')
3482 | , filter = utils.filter
3483 | , keys = utils.keys
3484 | , noop = function(){};
3485 |
3486 | /**
3487 | * Expose `Runner`.
3488 | */
3489 |
3490 | module.exports = Runner;
3491 |
3492 | /**
3493 | * Initialize a `Runner` for the given `suite`.
3494 | *
3495 | * Events:
3496 | *
3497 | * - `start` execution started
3498 | * - `end` execution complete
3499 | * - `suite` (suite) test suite execution started
3500 | * - `suite end` (suite) all tests (and sub-suites) have finished
3501 | * - `test` (test) test execution started
3502 | * - `test end` (test) test completed
3503 | * - `hook` (hook) hook execution started
3504 | * - `hook end` (hook) hook complete
3505 | * - `pass` (test) test passed
3506 | * - `fail` (test, err) test failed
3507 | *
3508 | * @api public
3509 | */
3510 |
3511 | function Runner(suite) {
3512 | var self = this;
3513 | this._globals = [];
3514 | this.suite = suite;
3515 | this.total = suite.total();
3516 | this.failures = 0;
3517 | this.on('test end', function(test){ self.checkGlobals(test); });
3518 | this.on('hook end', function(hook){ self.checkGlobals(hook); });
3519 | this.grep(/.*/);
3520 | this.globals(utils.keys(global).concat(['errno']));
3521 | }
3522 |
3523 | /**
3524 | * Inherit from `EventEmitter.prototype`.
3525 | */
3526 |
3527 | Runner.prototype = new EventEmitter;
3528 | Runner.prototype.constructor = Runner;
3529 |
3530 |
3531 | /**
3532 | * Run tests with full titles matching `re`. Updates runner.total
3533 | * with number of tests matched.
3534 | *
3535 | * @param {RegExp} re
3536 | * @param {Boolean} invert
3537 | * @return {Runner} for chaining
3538 | * @api public
3539 | */
3540 |
3541 | Runner.prototype.grep = function(re, invert){
3542 | debug('grep %s', re);
3543 | this._grep = re;
3544 | this._invert = invert;
3545 | this.total = this.grepTotal(this.suite);
3546 | return this;
3547 | };
3548 |
3549 | /**
3550 | * Returns the number of tests matching the grep search for the
3551 | * given suite.
3552 | *
3553 | * @param {Suite} suite
3554 | * @return {Number}
3555 | * @api public
3556 | */
3557 |
3558 | Runner.prototype.grepTotal = function(suite) {
3559 | var self = this;
3560 | var total = 0;
3561 |
3562 | suite.eachTest(function(test){
3563 | var match = self._grep.test(test.fullTitle());
3564 | if (self._invert) match = !match;
3565 | if (match) total++;
3566 | });
3567 |
3568 | return total;
3569 | };
3570 |
3571 | /**
3572 | * Allow the given `arr` of globals.
3573 | *
3574 | * @param {Array} arr
3575 | * @return {Runner} for chaining
3576 | * @api public
3577 | */
3578 |
3579 | Runner.prototype.globals = function(arr){
3580 | if (0 == arguments.length) return this._globals;
3581 | debug('globals %j', arr);
3582 | utils.forEach(arr, function(arr){
3583 | this._globals.push(arr);
3584 | }, this);
3585 | return this;
3586 | };
3587 |
3588 | /**
3589 | * Check for global variable leaks.
3590 | *
3591 | * @api private
3592 | */
3593 |
3594 | Runner.prototype.checkGlobals = function(test){
3595 | if (this.ignoreLeaks) return;
3596 | var leaks = filterLeaks(this._globals);
3597 |
3598 | this._globals = this._globals.concat(leaks);
3599 |
3600 | if (leaks.length > 1) {
3601 | this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
3602 | } else if (leaks.length) {
3603 | this.fail(test, new Error('global leak detected: ' + leaks[0]));
3604 | }
3605 | };
3606 |
3607 | /**
3608 | * Fail the given `test`.
3609 | *
3610 | * @param {Test} test
3611 | * @param {Error} err
3612 | * @api private
3613 | */
3614 |
3615 | Runner.prototype.fail = function(test, err){
3616 | ++this.failures;
3617 | test.state = 'failed';
3618 | if ('string' == typeof err) {
3619 | err = new Error('the string "' + err + '" was thrown, throw an Error :)');
3620 | }
3621 | this.emit('fail', test, err);
3622 | };
3623 |
3624 | /**
3625 | * Fail the given `hook` with `err`.
3626 | *
3627 | * Hook failures (currently) hard-end due
3628 | * to that fact that a failing hook will
3629 | * surely cause subsequent tests to fail,
3630 | * causing jumbled reporting.
3631 | *
3632 | * @param {Hook} hook
3633 | * @param {Error} err
3634 | * @api private
3635 | */
3636 |
3637 | Runner.prototype.failHook = function(hook, err){
3638 | this.fail(hook, err);
3639 | this.emit('end');
3640 | };
3641 |
3642 | /**
3643 | * Run hook `name` callbacks and then invoke `fn()`.
3644 | *
3645 | * @param {String} name
3646 | * @param {Function} function
3647 | * @api private
3648 | */
3649 |
3650 | Runner.prototype.hook = function(name, fn){
3651 | var suite = this.suite
3652 | , hooks = suite['_' + name]
3653 | , ms = suite._timeout
3654 | , self = this
3655 | , timer;
3656 |
3657 | function next(i) {
3658 | var hook = hooks[i];
3659 | if (!hook) return fn();
3660 | self.currentRunnable = hook;
3661 |
3662 | self.emit('hook', hook);
3663 |
3664 | hook.on('error', function(err){
3665 | self.failHook(hook, err);
3666 | });
3667 |
3668 | hook.run(function(err){
3669 | hook.removeAllListeners('error');
3670 | var testError = hook.error();
3671 | if (testError) self.fail(self.test, testError);
3672 | if (err) return self.failHook(hook, err);
3673 | self.emit('hook end', hook);
3674 | next(++i);
3675 | });
3676 | }
3677 |
3678 | process.nextTick(function(){
3679 | next(0);
3680 | });
3681 | };
3682 |
3683 | /**
3684 | * Run hook `name` for the given array of `suites`
3685 | * in order, and callback `fn(err)`.
3686 | *
3687 | * @param {String} name
3688 | * @param {Array} suites
3689 | * @param {Function} fn
3690 | * @api private
3691 | */
3692 |
3693 | Runner.prototype.hooks = function(name, suites, fn){
3694 | var self = this
3695 | , orig = this.suite;
3696 |
3697 | function next(suite) {
3698 | self.suite = suite;
3699 |
3700 | if (!suite) {
3701 | self.suite = orig;
3702 | return fn();
3703 | }
3704 |
3705 | self.hook(name, function(err){
3706 | if (err) {
3707 | self.suite = orig;
3708 | return fn(err);
3709 | }
3710 |
3711 | next(suites.pop());
3712 | });
3713 | }
3714 |
3715 | next(suites.pop());
3716 | };
3717 |
3718 | /**
3719 | * Run hooks from the top level down.
3720 | *
3721 | * @param {String} name
3722 | * @param {Function} fn
3723 | * @api private
3724 | */
3725 |
3726 | Runner.prototype.hookUp = function(name, fn){
3727 | var suites = [this.suite].concat(this.parents()).reverse();
3728 | this.hooks(name, suites, fn);
3729 | };
3730 |
3731 | /**
3732 | * Run hooks from the bottom up.
3733 | *
3734 | * @param {String} name
3735 | * @param {Function} fn
3736 | * @api private
3737 | */
3738 |
3739 | Runner.prototype.hookDown = function(name, fn){
3740 | var suites = [this.suite].concat(this.parents());
3741 | this.hooks(name, suites, fn);
3742 | };
3743 |
3744 | /**
3745 | * Return an array of parent Suites from
3746 | * closest to furthest.
3747 | *
3748 | * @return {Array}
3749 | * @api private
3750 | */
3751 |
3752 | Runner.prototype.parents = function(){
3753 | var suite = this.suite
3754 | , suites = [];
3755 | while (suite = suite.parent) suites.push(suite);
3756 | return suites;
3757 | };
3758 |
3759 | /**
3760 | * Run the current test and callback `fn(err)`.
3761 | *
3762 | * @param {Function} fn
3763 | * @api private
3764 | */
3765 |
3766 | Runner.prototype.runTest = function(fn){
3767 | var test = this.test
3768 | , self = this;
3769 |
3770 | try {
3771 | test.on('error', function(err){
3772 | self.fail(test, err);
3773 | });
3774 | test.run(fn);
3775 | } catch (err) {
3776 | fn(err);
3777 | }
3778 | };
3779 |
3780 | /**
3781 | * Run tests in the given `suite` and invoke
3782 | * the callback `fn()` when complete.
3783 | *
3784 | * @param {Suite} suite
3785 | * @param {Function} fn
3786 | * @api private
3787 | */
3788 |
3789 | Runner.prototype.runTests = function(suite, fn){
3790 | var self = this
3791 | , tests = suite.tests
3792 | , test;
3793 |
3794 | function next(err) {
3795 | // if we bail after first err
3796 | if (self.failures && suite._bail) return fn();
3797 |
3798 | // next test
3799 | test = tests.shift();
3800 |
3801 | // all done
3802 | if (!test) return fn();
3803 |
3804 | // grep
3805 | var match = self._grep.test(test.fullTitle());
3806 | if (self._invert) match = !match;
3807 | if (!match) return next();
3808 |
3809 | // pending
3810 | if (test.pending) {
3811 | self.emit('pending', test);
3812 | self.emit('test end', test);
3813 | return next();
3814 | }
3815 |
3816 | // execute test and hook(s)
3817 | self.emit('test', self.test = test);
3818 | self.hookDown('beforeEach', function(){
3819 | self.currentRunnable = self.test;
3820 | self.runTest(function(err){
3821 | test = self.test;
3822 |
3823 | if (err) {
3824 | self.fail(test, err);
3825 | self.emit('test end', test);
3826 | return self.hookUp('afterEach', next);
3827 | }
3828 |
3829 | test.state = 'passed';
3830 | self.emit('pass', test);
3831 | self.emit('test end', test);
3832 | self.hookUp('afterEach', next);
3833 | });
3834 | });
3835 | }
3836 |
3837 | this.next = next;
3838 | next();
3839 | };
3840 |
3841 | /**
3842 | * Run the given `suite` and invoke the
3843 | * callback `fn()` when complete.
3844 | *
3845 | * @param {Suite} suite
3846 | * @param {Function} fn
3847 | * @api private
3848 | */
3849 |
3850 | Runner.prototype.runSuite = function(suite, fn){
3851 | var total = this.grepTotal(suite)
3852 | , self = this
3853 | , i = 0;
3854 |
3855 | debug('run suite %s', suite.fullTitle());
3856 |
3857 | if (!total) return fn();
3858 |
3859 | this.emit('suite', this.suite = suite);
3860 |
3861 | function next() {
3862 | var curr = suite.suites[i++];
3863 | if (!curr) return done();
3864 | self.runSuite(curr, next);
3865 | }
3866 |
3867 | function done() {
3868 | self.suite = suite;
3869 | self.hook('afterAll', function(){
3870 | self.emit('suite end', suite);
3871 | fn();
3872 | });
3873 | }
3874 |
3875 | this.hook('beforeAll', function(){
3876 | self.runTests(suite, next);
3877 | });
3878 | };
3879 |
3880 | /**
3881 | * Handle uncaught exceptions.
3882 | *
3883 | * @param {Error} err
3884 | * @api private
3885 | */
3886 |
3887 | Runner.prototype.uncaught = function(err){
3888 | debug('uncaught exception %s', err.message);
3889 | var runnable = this.currentRunnable;
3890 | if (!runnable || 'failed' == runnable.state) return;
3891 | runnable.clearTimeout();
3892 | err.uncaught = true;
3893 | this.fail(runnable, err);
3894 |
3895 | // recover from test
3896 | if ('test' == runnable.type) {
3897 | this.emit('test end', runnable);
3898 | this.hookUp('afterEach', this.next);
3899 | return;
3900 | }
3901 |
3902 | // bail on hooks
3903 | this.emit('end');
3904 | };
3905 |
3906 | /**
3907 | * Run the root suite and invoke `fn(failures)`
3908 | * on completion.
3909 | *
3910 | * @param {Function} fn
3911 | * @return {Runner} for chaining
3912 | * @api public
3913 | */
3914 |
3915 | Runner.prototype.run = function(fn){
3916 | var self = this
3917 | , fn = fn || function(){};
3918 |
3919 | debug('start');
3920 |
3921 | // uncaught callback
3922 | function uncaught(err) {
3923 | self.uncaught(err);
3924 | }
3925 |
3926 | // callback
3927 | this.on('end', function(){
3928 | debug('end');
3929 | process.removeListener('uncaughtException', uncaught);
3930 | fn(self.failures);
3931 | });
3932 |
3933 | // run suites
3934 | this.emit('start');
3935 | this.runSuite(this.suite, function(){
3936 | debug('finished running');
3937 | self.emit('end');
3938 | });
3939 |
3940 | // uncaught exception
3941 | process.on('uncaughtException', uncaught);
3942 |
3943 | return this;
3944 | };
3945 |
3946 | /**
3947 | * Filter leaks with the given globals flagged as `ok`.
3948 | *
3949 | * @param {Array} ok
3950 | * @return {Array}
3951 | * @api private
3952 | */
3953 |
3954 | function filterLeaks(ok) {
3955 | return filter(keys(global), function(key){
3956 | var matched = filter(ok, function(ok){
3957 | if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
3958 | return key == ok;
3959 | });
3960 | return matched.length == 0 && (!global.navigator || 'onerror' !== key);
3961 | });
3962 | }
3963 | }); // module: runner.js
3964 |
3965 | require.register("suite.js", function(module, exports, require){
3966 |
3967 | /**
3968 | * Module dependencies.
3969 | */
3970 |
3971 | var EventEmitter = require('browser/events').EventEmitter
3972 | , debug = require('browser/debug')('mocha:suite')
3973 | , utils = require('./utils')
3974 | , Hook = require('./hook');
3975 |
3976 | /**
3977 | * Expose `Suite`.
3978 | */
3979 |
3980 | exports = module.exports = Suite;
3981 |
3982 | /**
3983 | * Create a new `Suite` with the given `title`
3984 | * and parent `Suite`. When a suite with the
3985 | * same title is already present, that suite
3986 | * is returned to provide nicer reporter
3987 | * and more flexible meta-testing.
3988 | *
3989 | * @param {Suite} parent
3990 | * @param {String} title
3991 | * @return {Suite}
3992 | * @api public
3993 | */
3994 |
3995 | exports.create = function(parent, title){
3996 | var suite = new Suite(title, parent.ctx);
3997 | suite.parent = parent;
3998 | if (parent.pending) suite.pending = true;
3999 | title = suite.fullTitle();
4000 | parent.addSuite(suite);
4001 | return suite;
4002 | };
4003 |
4004 | /**
4005 | * Initialize a new `Suite` with the given
4006 | * `title` and `ctx`.
4007 | *
4008 | * @param {String} title
4009 | * @param {Context} ctx
4010 | * @api private
4011 | */
4012 |
4013 | function Suite(title, ctx) {
4014 | this.title = title;
4015 | this.ctx = ctx;
4016 | this.suites = [];
4017 | this.tests = [];
4018 | this.pending = false;
4019 | this._beforeEach = [];
4020 | this._beforeAll = [];
4021 | this._afterEach = [];
4022 | this._afterAll = [];
4023 | this.root = !title;
4024 | this._timeout = 2000;
4025 | this._bail = false;
4026 | }
4027 |
4028 | /**
4029 | * Inherit from `EventEmitter.prototype`.
4030 | */
4031 |
4032 | Suite.prototype = new EventEmitter;
4033 | Suite.prototype.constructor = Suite;
4034 |
4035 |
4036 | /**
4037 | * Return a clone of this `Suite`.
4038 | *
4039 | * @return {Suite}
4040 | * @api private
4041 | */
4042 |
4043 | Suite.prototype.clone = function(){
4044 | var suite = new Suite(this.title);
4045 | debug('clone');
4046 | suite.ctx = this.ctx;
4047 | suite.timeout(this.timeout());
4048 | suite.bail(this.bail());
4049 | return suite;
4050 | };
4051 |
4052 | /**
4053 | * Set timeout `ms` or short-hand such as "2s".
4054 | *
4055 | * @param {Number|String} ms
4056 | * @return {Suite|Number} for chaining
4057 | * @api private
4058 | */
4059 |
4060 | Suite.prototype.timeout = function(ms){
4061 | if (0 == arguments.length) return this._timeout;
4062 | if (String(ms).match(/s$/)) ms = parseFloat(ms) * 1000;
4063 | debug('timeout %d', ms);
4064 | this._timeout = parseInt(ms, 10);
4065 | return this;
4066 | };
4067 |
4068 | /**
4069 | * Sets whether to bail after first error.
4070 | *
4071 | * @parma {Boolean} bail
4072 | * @return {Suite|Number} for chaining
4073 | * @api private
4074 | */
4075 |
4076 | Suite.prototype.bail = function(bail){
4077 | if (0 == arguments.length) return this._bail;
4078 | debug('bail %s', bail);
4079 | this._bail = bail;
4080 | return this;
4081 | };
4082 |
4083 | /**
4084 | * Run `fn(test[, done])` before running tests.
4085 | *
4086 | * @param {Function} fn
4087 | * @return {Suite} for chaining
4088 | * @api private
4089 | */
4090 |
4091 | Suite.prototype.beforeAll = function(fn){
4092 | if (this.pending) return this;
4093 | var hook = new Hook('"before all" hook', fn);
4094 | hook.parent = this;
4095 | hook.timeout(this.timeout());
4096 | hook.ctx = this.ctx;
4097 | this._beforeAll.push(hook);
4098 | this.emit('beforeAll', hook);
4099 | return this;
4100 | };
4101 |
4102 | /**
4103 | * Run `fn(test[, done])` after running tests.
4104 | *
4105 | * @param {Function} fn
4106 | * @return {Suite} for chaining
4107 | * @api private
4108 | */
4109 |
4110 | Suite.prototype.afterAll = function(fn){
4111 | if (this.pending) return this;
4112 | var hook = new Hook('"after all" hook', fn);
4113 | hook.parent = this;
4114 | hook.timeout(this.timeout());
4115 | hook.ctx = this.ctx;
4116 | this._afterAll.push(hook);
4117 | this.emit('afterAll', hook);
4118 | return this;
4119 | };
4120 |
4121 | /**
4122 | * Run `fn(test[, done])` before each test case.
4123 | *
4124 | * @param {Function} fn
4125 | * @return {Suite} for chaining
4126 | * @api private
4127 | */
4128 |
4129 | Suite.prototype.beforeEach = function(fn){
4130 | if (this.pending) return this;
4131 | var hook = new Hook('"before each" hook', fn);
4132 | hook.parent = this;
4133 | hook.timeout(this.timeout());
4134 | hook.ctx = this.ctx;
4135 | this._beforeEach.push(hook);
4136 | this.emit('beforeEach', hook);
4137 | return this;
4138 | };
4139 |
4140 | /**
4141 | * Run `fn(test[, done])` after each test case.
4142 | *
4143 | * @param {Function} fn
4144 | * @return {Suite} for chaining
4145 | * @api private
4146 | */
4147 |
4148 | Suite.prototype.afterEach = function(fn){
4149 | if (this.pending) return this;
4150 | var hook = new Hook('"after each" hook', fn);
4151 | hook.parent = this;
4152 | hook.timeout(this.timeout());
4153 | hook.ctx = this.ctx;
4154 | this._afterEach.push(hook);
4155 | this.emit('afterEach', hook);
4156 | return this;
4157 | };
4158 |
4159 | /**
4160 | * Add a test `suite`.
4161 | *
4162 | * @param {Suite} suite
4163 | * @return {Suite} for chaining
4164 | * @api private
4165 | */
4166 |
4167 | Suite.prototype.addSuite = function(suite){
4168 | suite.parent = this;
4169 | suite.timeout(this.timeout());
4170 | suite.bail(this.bail());
4171 | this.suites.push(suite);
4172 | this.emit('suite', suite);
4173 | return this;
4174 | };
4175 |
4176 | /**
4177 | * Add a `test` to this suite.
4178 | *
4179 | * @param {Test} test
4180 | * @return {Suite} for chaining
4181 | * @api private
4182 | */
4183 |
4184 | Suite.prototype.addTest = function(test){
4185 | test.parent = this;
4186 | test.timeout(this.timeout());
4187 | test.ctx = this.ctx;
4188 | this.tests.push(test);
4189 | this.emit('test', test);
4190 | return this;
4191 | };
4192 |
4193 | /**
4194 | * Return the full title generated by recursively
4195 | * concatenating the parent's full title.
4196 | *
4197 | * @return {String}
4198 | * @api public
4199 | */
4200 |
4201 | Suite.prototype.fullTitle = function(){
4202 | if (this.parent) {
4203 | var full = this.parent.fullTitle();
4204 | if (full) return full + ' ' + this.title;
4205 | }
4206 | return this.title;
4207 | };
4208 |
4209 | /**
4210 | * Return the total number of tests.
4211 | *
4212 | * @return {Number}
4213 | * @api public
4214 | */
4215 |
4216 | Suite.prototype.total = function(){
4217 | return utils.reduce(this.suites, function(sum, suite){
4218 | return sum + suite.total();
4219 | }, 0) + this.tests.length;
4220 | };
4221 |
4222 | /**
4223 | * Iterates through each suite recursively to find
4224 | * all tests. Applies a function in the format
4225 | * `fn(test)`.
4226 | *
4227 | * @param {Function} fn
4228 | * @return {Suite}
4229 | * @api private
4230 | */
4231 |
4232 | Suite.prototype.eachTest = function(fn){
4233 | utils.forEach(this.tests, fn);
4234 | utils.forEach(this.suites, function(suite){
4235 | suite.eachTest(fn);
4236 | });
4237 | return this;
4238 | };
4239 |
4240 | }); // module: suite.js
4241 |
4242 | require.register("test.js", function(module, exports, require){
4243 |
4244 | /**
4245 | * Module dependencies.
4246 | */
4247 |
4248 | var Runnable = require('./runnable');
4249 |
4250 | /**
4251 | * Expose `Test`.
4252 | */
4253 |
4254 | module.exports = Test;
4255 |
4256 | /**
4257 | * Initialize a new `Test` with the given `title` and callback `fn`.
4258 | *
4259 | * @param {String} title
4260 | * @param {Function} fn
4261 | * @api private
4262 | */
4263 |
4264 | function Test(title, fn) {
4265 | Runnable.call(this, title, fn);
4266 | this.pending = !fn;
4267 | this.type = 'test';
4268 | }
4269 |
4270 | /**
4271 | * Inherit from `Runnable.prototype`.
4272 | */
4273 |
4274 | Test.prototype = new Runnable;
4275 | Test.prototype.constructor = Test;
4276 |
4277 |
4278 | }); // module: test.js
4279 |
4280 | require.register("utils.js", function(module, exports, require){
4281 |
4282 | /**
4283 | * Module dependencies.
4284 | */
4285 |
4286 | var fs = require('browser/fs')
4287 | , path = require('browser/path')
4288 | , join = path.join
4289 | , debug = require('browser/debug')('mocha:watch');
4290 |
4291 | /**
4292 | * Ignored directories.
4293 | */
4294 |
4295 | var ignore = ['node_modules', '.git'];
4296 |
4297 | /**
4298 | * Escape special characters in the given string of html.
4299 | *
4300 | * @param {String} html
4301 | * @return {String}
4302 | * @api private
4303 | */
4304 |
4305 | exports.escape = function(html) {
4306 | return String(html)
4307 | .replace(/&/g, '&')
4308 | .replace(/"/g, '"')
4309 | .replace(//g, '>');
4311 | };
4312 |
4313 | /**
4314 | * Array#forEach (<=IE8)
4315 | *
4316 | * @param {Array} array
4317 | * @param {Function} fn
4318 | * @param {Object} scope
4319 | * @api private
4320 | */
4321 |
4322 | exports.forEach = function(arr, fn, scope) {
4323 | for (var i = 0, l = arr.length; i < l; i++)
4324 | fn.call(scope, arr[i], i);
4325 | };
4326 |
4327 | /**
4328 | * Array#indexOf (<=IE8)
4329 | *
4330 | * @parma {Array} arr
4331 | * @param {Object} obj to find index of
4332 | * @param {Number} start
4333 | * @api private
4334 | */
4335 |
4336 | exports.indexOf = function (arr, obj, start) {
4337 | for (var i = start || 0, l = arr.length; i < l; i++) {
4338 | if (arr[i] === obj)
4339 | return i;
4340 | }
4341 | return -1;
4342 | };
4343 |
4344 | /**
4345 | * Array#reduce (<=IE8)
4346 | *
4347 | * @param {Array} array
4348 | * @param {Function} fn
4349 | * @param {Object} initial value
4350 | * @param {Object} scope
4351 | * @api private
4352 | */
4353 |
4354 | exports.reduce = function(arr, fn, val, scope) {
4355 | var rval = val;
4356 |
4357 | for (var i = 0, l = arr.length; i < l; i++) {
4358 | rval = fn.call(scope, rval, arr[i], i, arr);
4359 | }
4360 |
4361 | return rval;
4362 | };
4363 |
4364 | /**
4365 | * Array#filter (<=IE8)
4366 | *
4367 | * @param {Array} array
4368 | * @param {Function} fn
4369 | * @param {Object} scope
4370 | * @api private
4371 | */
4372 |
4373 | exports.filter = function(arr, fn, scope) {
4374 | var ret = [];
4375 |
4376 | for (var i = 0, l = arr.length; i < l; i++) {
4377 | var val = arr[i];
4378 | if (fn.call(scope, val, i, arr))
4379 | ret.push(val);
4380 | }
4381 |
4382 | return ret;
4383 | };
4384 |
4385 | /**
4386 | * Object.keys (<=IE8)
4387 | *
4388 | * @param {Object} obj
4389 | * @return {Array} keys
4390 | * @api private
4391 | */
4392 |
4393 | exports.keys = Object.keys || function(obj) {
4394 | var keys = []
4395 | , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
4396 |
4397 | for (var key in obj) {
4398 | if (has.call(obj, key)) {
4399 | keys.push(key);
4400 | }
4401 | }
4402 |
4403 | return keys;
4404 | };
4405 |
4406 | /**
4407 | * Watch the given `files` for changes
4408 | * and invoke `fn(file)` on modification.
4409 | *
4410 | * @param {Array} files
4411 | * @param {Function} fn
4412 | * @api private
4413 | */
4414 |
4415 | exports.watch = function(files, fn){
4416 | var options = { interval: 100 };
4417 | files.forEach(function(file){
4418 | debug('file %s', file);
4419 | fs.watchFile(file, options, function(curr, prev){
4420 | if (prev.mtime < curr.mtime) fn(file);
4421 | });
4422 | });
4423 | };
4424 |
4425 | /**
4426 | * Ignored files.
4427 | */
4428 |
4429 | function ignored(path){
4430 | return !~ignore.indexOf(path);
4431 | }
4432 |
4433 | /**
4434 | * Lookup files in the given `dir`.
4435 | *
4436 | * @return {Array}
4437 | * @api private
4438 | */
4439 |
4440 | exports.files = function(dir, ret){
4441 | ret = ret || [];
4442 |
4443 | fs.readdirSync(dir)
4444 | .filter(ignored)
4445 | .forEach(function(path){
4446 | path = join(dir, path);
4447 | if (fs.statSync(path).isDirectory()) {
4448 | exports.files(path, ret);
4449 | } else if (path.match(/\.(js|coffee)$/)) {
4450 | ret.push(path);
4451 | }
4452 | });
4453 |
4454 | return ret;
4455 | };
4456 |
4457 | /**
4458 | * Compute a slug from the given `str`.
4459 | *
4460 | * @param {String} str
4461 | * @return {String}
4462 | * @api private
4463 | */
4464 |
4465 | exports.slug = function(str){
4466 | return str
4467 | .toLowerCase()
4468 | .replace(/ +/g, '-')
4469 | .replace(/[^-\w]/g, '');
4470 | };
4471 |
4472 | /**
4473 | * Strip the function definition from `str`,
4474 | * and re-indent for pre whitespace.
4475 | */
4476 |
4477 | exports.clean = function(str) {
4478 | str = str
4479 | .replace(/^function *\(.*\) *{/, '')
4480 | .replace(/\s+\}$/, '');
4481 |
4482 | var spaces = str.match(/^\n?( *)/)[1].length
4483 | , re = new RegExp('^ {' + spaces + '}', 'gm');
4484 |
4485 | str = str.replace(re, '');
4486 |
4487 | return exports.trim(str);
4488 | };
4489 |
4490 | /**
4491 | * Escape regular expression characters in `str`.
4492 | *
4493 | * @param {String} str
4494 | * @return {String}
4495 | * @api private
4496 | */
4497 |
4498 | exports.escapeRegexp = function(str){
4499 | return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
4500 | };
4501 |
4502 | /**
4503 | * Trim the given `str`.
4504 | *
4505 | * @param {String} str
4506 | * @return {String}
4507 | * @api private
4508 | */
4509 |
4510 | exports.trim = function(str){
4511 | return str.replace(/^\s+|\s+$/g, '');
4512 | };
4513 | }); // module: utils.js
4514 | /**
4515 | * Node shims.
4516 | *
4517 | * These are meant only to allow
4518 | * mocha.js to run untouched, not
4519 | * to allow running node code in
4520 | * the browser.
4521 | */
4522 |
4523 | process = {};
4524 | process.exit = function(status){};
4525 | process.stdout = {};
4526 | global = window;
4527 |
4528 | /**
4529 | * next tick implementation.
4530 | */
4531 |
4532 | process.nextTick = (function(){
4533 | // postMessage behaves badly on IE8
4534 | if (window.ActiveXObject || !window.postMessage) {
4535 | return function(fn){ fn() };
4536 | }
4537 |
4538 | // based on setZeroTimeout by David Baron
4539 | // - http://dbaron.org/log/20100309-faster-timeouts
4540 | var timeouts = []
4541 | , name = 'mocha-zero-timeout'
4542 |
4543 | window.addEventListener('message', function(e){
4544 | if (e.source == window && e.data == name) {
4545 | if (e.stopPropagation) e.stopPropagation();
4546 | if (timeouts.length) timeouts.shift()();
4547 | }
4548 | }, true);
4549 |
4550 | return function(fn){
4551 | timeouts.push(fn);
4552 | window.postMessage(name, '*');
4553 | }
4554 | })();
4555 |
4556 | /**
4557 | * Remove uncaughtException listener.
4558 | */
4559 |
4560 | process.removeListener = function(e){
4561 | if ('uncaughtException' == e) {
4562 | window.onerror = null;
4563 | }
4564 | };
4565 |
4566 | /**
4567 | * Implements uncaughtException listener.
4568 | */
4569 |
4570 | process.on = function(e, fn){
4571 | if ('uncaughtException' == e) {
4572 | window.onerror = fn;
4573 | }
4574 | };
4575 |
4576 | /**
4577 | * Expose mocha.
4578 | */
4579 |
4580 | window.mocha = require('mocha');
4581 |
4582 | // boot
4583 | ;(function(){
4584 | var utils = mocha.utils
4585 | , options = {}
4586 |
4587 | // TODO: use new Mocha here... not mocha.grep etc
4588 |
4589 | mocha.suite = new mocha.Suite('', new mocha.Context());
4590 |
4591 | /**
4592 | * Highlight the given string of `js`.
4593 | */
4594 |
4595 | function highlight(js) {
4596 | return js
4597 | .replace(//g, '>')
4599 | .replace(/\/\/(.*)/gm, '')
4600 | .replace(/('.*?')/gm, '$1 ')
4601 | .replace(/(\d+\.\d+)/gm, '$1 ')
4602 | .replace(/(\d+)/gm, '$1 ')
4603 | .replace(/\bnew *(\w+)/gm, 'new $1 ')
4604 | .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1 ')
4605 | }
4606 |
4607 | /**
4608 | * Highlight code contents.
4609 | */
4610 |
4611 | function highlightCode() {
4612 | var code = document.getElementsByTagName('code');
4613 | for (var i = 0, len = code.length; i < len; ++i) {
4614 | code[i].innerHTML = highlight(code[i].innerHTML);
4615 | }
4616 | }
4617 |
4618 | /**
4619 | * Parse the given `qs`.
4620 | */
4621 |
4622 | function parse(qs) {
4623 | return utils.reduce(qs.replace('?', '').split('&'), function(obj, pair){
4624 | var i = pair.indexOf('=')
4625 | , key = pair.slice(0, i)
4626 | , val = pair.slice(++i);
4627 |
4628 | obj[key] = decodeURIComponent(val);
4629 | return obj;
4630 | }, {});
4631 | }
4632 |
4633 | /**
4634 | * Grep.
4635 | */
4636 |
4637 | mocha.grep = function(str){
4638 | options.grep = new RegExp(utils.escapeRegexp(str));
4639 | };
4640 |
4641 | /**
4642 | * Setup mocha with the given setting options.
4643 | */
4644 |
4645 | mocha.setup = function(opts){
4646 | if ('string' === typeof opts) options.ui = opts;
4647 | else options = opts;
4648 |
4649 | ui = mocha.interfaces[options.ui];
4650 | if (!ui) throw new Error('invalid mocha interface "' + ui + '"');
4651 | if (options.timeout) mocha.suite.timeout(options.timeout);
4652 | ui(mocha.suite);
4653 | mocha.suite.emit('pre-require', window, null, mocha);
4654 | };
4655 |
4656 | /**
4657 | * Run mocha, returning the Runner.
4658 | */
4659 |
4660 | mocha.run = function(fn){
4661 | mocha.suite.emit('run');
4662 | var runner = new mocha.Runner(mocha.suite);
4663 | var Reporter = options.reporter || mocha.reporters.HTML;
4664 | var reporter = new Reporter(runner);
4665 | var query = parse(window.location.search || "");
4666 | if (query.grep) runner.grep(new RegExp(query.grep));
4667 | if (options.grep) runner.grep(options.grep);
4668 | if (options.ignoreLeaks) runner.ignoreLeaks = true;
4669 | if (options.globals) runner.globals(options.globals);
4670 | runner.globals(['location']);
4671 | runner.on('end', highlightCode);
4672 | return runner.run(fn);
4673 | };
4674 | })();
4675 | })();
--------------------------------------------------------------------------------