Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: appengine/config_service/ui/bower_components/async/deps/nodeunit.js

Issue 2923973003: Added base template for config ui. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*!
2 * Nodeunit
3 * https://github.com/caolan/nodeunit
4 * Copyright (c) 2010 Caolan McMahon
5 * MIT Licensed
6 *
7 * json2.js
8 * http://www.JSON.org/json2.js
9 * Public Domain.
10 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
11 */
12 nodeunit = (function(){
13 /*
14 http://www.JSON.org/json2.js
15 2010-11-17
16
17 Public Domain.
18
19 NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
20
21 See http://www.JSON.org/js.html
22
23
24 This code should be minified before deployment.
25 See http://javascript.crockford.com/jsmin.html
26
27 USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
28 NOT CONTROL.
29
30
31 This file creates a global JSON object containing two methods: stringify
32 and parse.
33
34 JSON.stringify(value, replacer, space)
35 value any JavaScript value, usually an object or array.
36
37 replacer an optional parameter that determines how object
38 values are stringified for objects. It can be a
39 function or an array of strings.
40
41 space an optional parameter that specifies the indentation
42 of nested structures. If it is omitted, the text will
43 be packed without extra whitespace. If it is a number,
44 it will specify the number of spaces to indent at each
45 level. If it is a string (such as '\t' or ' '),
46 it contains the characters used to indent at each level.
47
48 This method produces a JSON text from a JavaScript value.
49
50 When an object value is found, if the object contains a toJSON
51 method, its toJSON method will be called and the result will be
52 stringified. A toJSON method does not serialize: it returns the
53 value represented by the name/value pair that should be serialized,
54 or undefined if nothing should be serialized. The toJSON method
55 will be passed the key associated with the value, and this will be
56 bound to the value
57
58 For example, this would serialize Dates as ISO strings.
59
60 Date.prototype.toJSON = function (key) {
61 function f(n) {
62 // Format integers to have at least two digits.
63 return n < 10 ? '0' + n : n;
64 }
65
66 return this.getUTCFullYear() + '-' +
67 f(this.getUTCMonth() + 1) + '-' +
68 f(this.getUTCDate()) + 'T' +
69 f(this.getUTCHours()) + ':' +
70 f(this.getUTCMinutes()) + ':' +
71 f(this.getUTCSeconds()) + 'Z';
72 };
73
74 You can provide an optional replacer method. It will be passed the
75 key and value of each member, with this bound to the containing
76 object. The value that is returned from your method will be
77 serialized. If your method returns undefined, then the member will
78 be excluded from the serialization.
79
80 If the replacer parameter is an array of strings, then it will be
81 used to select the members to be serialized. It filters the results
82 such that only members with keys listed in the replacer array are
83 stringified.
84
85 Values that do not have JSON representations, such as undefined or
86 functions, will not be serialized. Such values in objects will be
87 dropped; in arrays they will be replaced with null. You can use
88 a replacer function to replace those with JSON values.
89 JSON.stringify(undefined) returns undefined.
90
91 The optional space parameter produces a stringification of the
92 value that is filled with line breaks and indentation to make it
93 easier to read.
94
95 If the space parameter is a non-empty string, then that string will
96 be used for indentation. If the space parameter is a number, then
97 the indentation will be that many spaces.
98
99 Example:
100
101 text = JSON.stringify(['e', {pluribus: 'unum'}]);
102 // text is '["e",{"pluribus":"unum"}]'
103
104
105 text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
106 // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
107
108 text = JSON.stringify([new Date()], function (key, value) {
109 return this[key] instanceof Date ?
110 'Date(' + this[key] + ')' : value;
111 });
112 // text is '["Date(---current time---)"]'
113
114
115 JSON.parse(text, reviver)
116 This method parses a JSON text to produce an object or array.
117 It can throw a SyntaxError exception.
118
119 The optional reviver parameter is a function that can filter and
120 transform the results. It receives each of the keys and values,
121 and its return value is used instead of the original value.
122 If it returns what it received, then the structure is not modified.
123 If it returns undefined then the member is deleted.
124
125 Example:
126
127 // Parse the text. Values that look like ISO date strings will
128 // be converted to Date objects.
129
130 myData = JSON.parse(text, function (key, value) {
131 var a;
132 if (typeof value === 'string') {
133 a =
134 /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
135 if (a) {
136 return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
137 +a[5], +a[6]));
138 }
139 }
140 return value;
141 });
142
143 myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
144 var d;
145 if (typeof value === 'string' &&
146 value.slice(0, 5) === 'Date(' &&
147 value.slice(-1) === ')') {
148 d = new Date(value.slice(5, -1));
149 if (d) {
150 return d;
151 }
152 }
153 return value;
154 });
155
156
157 This is a reference implementation. You are free to copy, modify, or
158 redistribute.
159 */
160
161 /*jslint evil: true, strict: false, regexp: false */
162
163 /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
164 call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
165 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
166 lastIndex, length, parse, prototype, push, replace, slice, stringify,
167 test, toJSON, toString, valueOf
168 */
169
170
171 // Create a JSON object only if one does not already exist. We create the
172 // methods in a closure to avoid creating global variables.
173
174 var JSON = {};
175
176 (function () {
177 "use strict";
178
179 function f(n) {
180 // Format integers to have at least two digits.
181 return n < 10 ? '0' + n : n;
182 }
183
184 if (typeof Date.prototype.toJSON !== 'function') {
185
186 Date.prototype.toJSON = function (key) {
187
188 return isFinite(this.valueOf()) ?
189 this.getUTCFullYear() + '-' +
190 f(this.getUTCMonth() + 1) + '-' +
191 f(this.getUTCDate()) + 'T' +
192 f(this.getUTCHours()) + ':' +
193 f(this.getUTCMinutes()) + ':' +
194 f(this.getUTCSeconds()) + 'Z' : null;
195 };
196
197 String.prototype.toJSON =
198 Number.prototype.toJSON =
199 Boolean.prototype.toJSON = function (key) {
200 return this.valueOf();
201 };
202 }
203
204 var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u 202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
205 escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b 5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
206 gap,
207 indent,
208 meta = { // table of character substitutions
209 '\b': '\\b',
210 '\t': '\\t',
211 '\n': '\\n',
212 '\f': '\\f',
213 '\r': '\\r',
214 '"' : '\\"',
215 '\\': '\\\\'
216 },
217 rep;
218
219
220 function quote(string) {
221
222 // If the string contains no control characters, no quote characters, and no
223 // backslash characters, then we can safely slap some quotes around it.
224 // Otherwise we must also replace the offending characters with safe escape
225 // sequences.
226
227 escapable.lastIndex = 0;
228 return escapable.test(string) ?
229 '"' + string.replace(escapable, function (a) {
230 var c = meta[a];
231 return typeof c === 'string' ? c :
232 '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
233 }) + '"' :
234 '"' + string + '"';
235 }
236
237
238 function str(key, holder) {
239
240 // Produce a string from holder[key].
241
242 var i, // The loop counter.
243 k, // The member key.
244 v, // The member value.
245 length,
246 mind = gap,
247 partial,
248 value = holder[key];
249
250 // If the value has a toJSON method, call it to obtain a replacement value.
251
252 if (value && typeof value === 'object' &&
253 typeof value.toJSON === 'function') {
254 value = value.toJSON(key);
255 }
256
257 // If we were called with a replacer function, then call the replacer to
258 // obtain a replacement value.
259
260 if (typeof rep === 'function') {
261 value = rep.call(holder, key, value);
262 }
263
264 // What happens next depends on the value's type.
265
266 switch (typeof value) {
267 case 'string':
268 return quote(value);
269
270 case 'number':
271
272 // JSON numbers must be finite. Encode non-finite numbers as null.
273
274 return isFinite(value) ? String(value) : 'null';
275
276 case 'boolean':
277 case 'null':
278
279 // If the value is a boolean or null, convert it to a string. Note:
280 // typeof null does not produce 'null'. The case is included here in
281 // the remote chance that this gets fixed someday.
282
283 return String(value);
284
285 // If the type is 'object', we might be dealing with an object or an array or
286 // null.
287
288 case 'object':
289
290 // Due to a specification blunder in ECMAScript, typeof null is 'object',
291 // so watch out for that case.
292
293 if (!value) {
294 return 'null';
295 }
296
297 // Make an array to hold the partial results of stringifying this object value.
298
299 gap += indent;
300 partial = [];
301
302 // Is the value an array?
303
304 if (Object.prototype.toString.apply(value) === '[object Array]') {
305
306 // The value is an array. Stringify every element. Use null as a placeholder
307 // for non-JSON values.
308
309 length = value.length;
310 for (i = 0; i < length; i += 1) {
311 partial[i] = str(i, value) || 'null';
312 }
313
314 // Join all of the elements together, separated with commas, and wrap them in
315 // brackets.
316
317 v = partial.length === 0 ? '[]' :
318 gap ? '[\n' + gap +
319 partial.join(',\n' + gap) + '\n' +
320 mind + ']' :
321 '[' + partial.join(',') + ']';
322 gap = mind;
323 return v;
324 }
325
326 // If the replacer is an array, use it to select the members to be stringified.
327
328 if (rep && typeof rep === 'object') {
329 length = rep.length;
330 for (i = 0; i < length; i += 1) {
331 k = rep[i];
332 if (typeof k === 'string') {
333 v = str(k, value);
334 if (v) {
335 partial.push(quote(k) + (gap ? ': ' : ':') + v);
336 }
337 }
338 }
339 } else {
340
341 // Otherwise, iterate through all of the keys in the object.
342
343 for (k in value) {
344 if (Object.hasOwnProperty.call(value, k)) {
345 v = str(k, value);
346 if (v) {
347 partial.push(quote(k) + (gap ? ': ' : ':') + v);
348 }
349 }
350 }
351 }
352
353 // Join all of the member texts together, separated with commas,
354 // and wrap them in braces.
355
356 v = partial.length === 0 ? '{}' :
357 gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
358 mind + '}' : '{' + partial.join(',') + '}';
359 gap = mind;
360 return v;
361 }
362 }
363
364 // If the JSON object does not yet have a stringify method, give it one.
365
366 if (typeof JSON.stringify !== 'function') {
367 JSON.stringify = function (value, replacer, space) {
368
369 // The stringify method takes a value and an optional replacer, and an optional
370 // space parameter, and returns a JSON text. The replacer can be a function
371 // that can replace values, or an array of strings that will select the keys.
372 // A default replacer method can be provided. Use of the space parameter can
373 // produce text that is more easily readable.
374
375 var i;
376 gap = '';
377 indent = '';
378
379 // If the space parameter is a number, make an indent string containing that
380 // many spaces.
381
382 if (typeof space === 'number') {
383 for (i = 0; i < space; i += 1) {
384 indent += ' ';
385 }
386
387 // If the space parameter is a string, it will be used as the indent string.
388
389 } else if (typeof space === 'string') {
390 indent = space;
391 }
392
393 // If there is a replacer, it must be a function or an array.
394 // Otherwise, throw an error.
395
396 rep = replacer;
397 if (replacer && typeof replacer !== 'function' &&
398 (typeof replacer !== 'object' ||
399 typeof replacer.length !== 'number')) {
400 throw new Error('JSON.stringify');
401 }
402
403 // Make a fake root object containing our value under the key of ''.
404 // Return the result of stringifying the value.
405
406 return str('', {'': value});
407 };
408 }
409
410
411 // If the JSON object does not yet have a parse method, give it one.
412
413 if (typeof JSON.parse !== 'function') {
414 JSON.parse = function (text, reviver) {
415
416 // The parse method takes a text and an optional reviver function, and returns
417 // a JavaScript value if the text is a valid JSON text.
418
419 var j;
420
421 function walk(holder, key) {
422
423 // The walk method is used to recursively walk the resulting structure so
424 // that modifications can be made.
425
426 var k, v, value = holder[key];
427 if (value && typeof value === 'object') {
428 for (k in value) {
429 if (Object.hasOwnProperty.call(value, k)) {
430 v = walk(value, k);
431 if (v !== undefined) {
432 value[k] = v;
433 } else {
434 delete value[k];
435 }
436 }
437 }
438 }
439 return reviver.call(holder, key, value);
440 }
441
442
443 // Parsing happens in four stages. In the first stage, we replace certain
444 // Unicode characters with escape sequences. JavaScript handles many characters
445 // incorrectly, either silently deleting them, or treating them as line endings.
446
447 text = String(text);
448 cx.lastIndex = 0;
449 if (cx.test(text)) {
450 text = text.replace(cx, function (a) {
451 return '\\u' +
452 ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
453 });
454 }
455
456 // In the second stage, we run the text against regular expressions that look
457 // for non-JSON patterns. We are especially concerned with '()' and 'new'
458 // because they can cause invocation, and '=' because it can cause mutation.
459 // But just to be safe, we want to reject all unexpected forms.
460
461 // We split the second stage into 4 regexp operations in order to work around
462 // crippling inefficiencies in IE's and Safari's regexp engines. First we
463 // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
464 // replace all simple value tokens with ']' characters. Third, we delete all
465 // open brackets that follow a colon or comma or that begin the text. Finally,
466 // we look to see that the remaining characters are only whitespace or ']' or
467 // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
468
469 if (/^[\],:{}\s]*$/
470 .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
471 .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']' )
472 .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
473
474 // In the third stage we use the eval function to compile the text into a
475 // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
476 // in JavaScript: it can begin a block or an object literal. We wrap the text
477 // in parens to eliminate the ambiguity.
478
479 j = eval('(' + text + ')');
480
481 // In the optional fourth stage, we recursively walk the new structure, passing
482 // each name/value pair to a reviver function for possible transformation.
483
484 return typeof reviver === 'function' ?
485 walk({'': j}, '') : j;
486 }
487
488 // If the text is not JSON parseable, then a SyntaxError is thrown.
489
490 throw new SyntaxError('JSON.parse');
491 };
492 }
493 }());
494 var assert = this.assert = {};
495 var types = {};
496 var core = {};
497 var nodeunit = {};
498 var reporter = {};
499 /*global setTimeout: false, console: false */
500 (function () {
501
502 var async = {};
503
504 // global on the server, window in the browser
505 var root = this,
506 previous_async = root.async;
507
508 if (typeof module !== 'undefined' && module.exports) {
509 module.exports = async;
510 }
511 else {
512 root.async = async;
513 }
514
515 async.noConflict = function () {
516 root.async = previous_async;
517 return async;
518 };
519
520 //// cross-browser compatiblity functions ////
521
522 var _forEach = function (arr, iterator) {
523 if (arr.forEach) {
524 return arr.forEach(iterator);
525 }
526 for (var i = 0; i < arr.length; i += 1) {
527 iterator(arr[i], i, arr);
528 }
529 };
530
531 var _map = function (arr, iterator) {
532 if (arr.map) {
533 return arr.map(iterator);
534 }
535 var results = [];
536 _forEach(arr, function (x, i, a) {
537 results.push(iterator(x, i, a));
538 });
539 return results;
540 };
541
542 var _reduce = function (arr, iterator, memo) {
543 if (arr.reduce) {
544 return arr.reduce(iterator, memo);
545 }
546 _forEach(arr, function (x, i, a) {
547 memo = iterator(memo, x, i, a);
548 });
549 return memo;
550 };
551
552 var _keys = function (obj) {
553 if (Object.keys) {
554 return Object.keys(obj);
555 }
556 var keys = [];
557 for (var k in obj) {
558 if (obj.hasOwnProperty(k)) {
559 keys.push(k);
560 }
561 }
562 return keys;
563 };
564
565 var _indexOf = function (arr, item) {
566 if (arr.indexOf) {
567 return arr.indexOf(item);
568 }
569 for (var i = 0; i < arr.length; i += 1) {
570 if (arr[i] === item) {
571 return i;
572 }
573 }
574 return -1;
575 };
576
577 //// exported async module functions ////
578
579 //// nextTick implementation with browser-compatible fallback ////
580 if (typeof setImmediate === 'function') {
581 async.nextTick = function (fn) {
582 setImmediate(fn);
583 };
584 }
585 else if (typeof process !== 'undefined' && process.nextTick) {
586 async.nextTick = process.nextTick;
587 }
588 else {
589 async.nextTick = function (fn) {
590 setTimeout(fn, 0);
591 };
592 }
593
594 async.forEach = function (arr, iterator, callback) {
595 if (!arr.length) {
596 return callback();
597 }
598 var completed = 0;
599 _forEach(arr, function (x) {
600 iterator(x, function (err) {
601 if (err) {
602 callback(err);
603 callback = function () {};
604 }
605 else {
606 completed += 1;
607 if (completed === arr.length) {
608 callback();
609 }
610 }
611 });
612 });
613 };
614
615 async.forEachSeries = function (arr, iterator, callback) {
616 if (!arr.length) {
617 return callback();
618 }
619 var completed = 0;
620 var iterate = function () {
621 iterator(arr[completed], function (err) {
622 if (err) {
623 callback(err);
624 callback = function () {};
625 }
626 else {
627 completed += 1;
628 if (completed === arr.length) {
629 callback();
630 }
631 else {
632 iterate();
633 }
634 }
635 });
636 };
637 iterate();
638 };
639
640
641 var doParallel = function (fn) {
642 return function () {
643 var args = Array.prototype.slice.call(arguments);
644 return fn.apply(null, [async.forEach].concat(args));
645 };
646 };
647 var doSeries = function (fn) {
648 return function () {
649 var args = Array.prototype.slice.call(arguments);
650 return fn.apply(null, [async.forEachSeries].concat(args));
651 };
652 };
653
654
655 var _asyncMap = function (eachfn, arr, iterator, callback) {
656 var results = [];
657 arr = _map(arr, function (x, i) {
658 return {index: i, value: x};
659 });
660 eachfn(arr, function (x, callback) {
661 iterator(x.value, function (err, v) {
662 results[x.index] = v;
663 callback(err);
664 });
665 }, function (err) {
666 callback(err, results);
667 });
668 };
669 async.map = doParallel(_asyncMap);
670 async.mapSeries = doSeries(_asyncMap);
671
672
673 // reduce only has a series version, as doing reduce in parallel won't
674 // work in many situations.
675 async.reduce = function (arr, memo, iterator, callback) {
676 async.forEachSeries(arr, function (x, callback) {
677 iterator(memo, x, function (err, v) {
678 memo = v;
679 callback(err);
680 });
681 }, function (err) {
682 callback(err, memo);
683 });
684 };
685 // inject alias
686 async.inject = async.reduce;
687 // foldl alias
688 async.foldl = async.reduce;
689
690 async.reduceRight = function (arr, memo, iterator, callback) {
691 var reversed = _map(arr, function (x) {
692 return x;
693 }).reverse();
694 async.reduce(reversed, memo, iterator, callback);
695 };
696 // foldr alias
697 async.foldr = async.reduceRight;
698
699 var _filter = function (eachfn, arr, iterator, callback) {
700 var results = [];
701 arr = _map(arr, function (x, i) {
702 return {index: i, value: x};
703 });
704 eachfn(arr, function (x, callback) {
705 iterator(x.value, function (v) {
706 if (v) {
707 results.push(x);
708 }
709 callback();
710 });
711 }, function (err) {
712 callback(_map(results.sort(function (a, b) {
713 return a.index - b.index;
714 }), function (x) {
715 return x.value;
716 }));
717 });
718 };
719 async.filter = doParallel(_filter);
720 async.filterSeries = doSeries(_filter);
721 // select alias
722 async.select = async.filter;
723 async.selectSeries = async.filterSeries;
724
725 var _reject = function (eachfn, arr, iterator, callback) {
726 var results = [];
727 arr = _map(arr, function (x, i) {
728 return {index: i, value: x};
729 });
730 eachfn(arr, function (x, callback) {
731 iterator(x.value, function (v) {
732 if (!v) {
733 results.push(x);
734 }
735 callback();
736 });
737 }, function (err) {
738 callback(_map(results.sort(function (a, b) {
739 return a.index - b.index;
740 }), function (x) {
741 return x.value;
742 }));
743 });
744 };
745 async.reject = doParallel(_reject);
746 async.rejectSeries = doSeries(_reject);
747
748 var _detect = function (eachfn, arr, iterator, main_callback) {
749 eachfn(arr, function (x, callback) {
750 iterator(x, function (result) {
751 if (result) {
752 main_callback(x);
753 }
754 else {
755 callback();
756 }
757 });
758 }, function (err) {
759 main_callback();
760 });
761 };
762 async.detect = doParallel(_detect);
763 async.detectSeries = doSeries(_detect);
764
765 async.some = function (arr, iterator, main_callback) {
766 async.forEach(arr, function (x, callback) {
767 iterator(x, function (v) {
768 if (v) {
769 main_callback(true);
770 main_callback = function () {};
771 }
772 callback();
773 });
774 }, function (err) {
775 main_callback(false);
776 });
777 };
778 // any alias
779 async.any = async.some;
780
781 async.every = function (arr, iterator, main_callback) {
782 async.forEach(arr, function (x, callback) {
783 iterator(x, function (v) {
784 if (!v) {
785 main_callback(false);
786 main_callback = function () {};
787 }
788 callback();
789 });
790 }, function (err) {
791 main_callback(true);
792 });
793 };
794 // all alias
795 async.all = async.every;
796
797 async.sortBy = function (arr, iterator, callback) {
798 async.map(arr, function (x, callback) {
799 iterator(x, function (err, criteria) {
800 if (err) {
801 callback(err);
802 }
803 else {
804 callback(null, {value: x, criteria: criteria});
805 }
806 });
807 }, function (err, results) {
808 if (err) {
809 return callback(err);
810 }
811 else {
812 var fn = function (left, right) {
813 var a = left.criteria, b = right.criteria;
814 return a < b ? -1 : a > b ? 1 : 0;
815 };
816 callback(null, _map(results.sort(fn), function (x) {
817 return x.value;
818 }));
819 }
820 });
821 };
822
823 async.auto = function (tasks, callback) {
824 callback = callback || function () {};
825 var keys = _keys(tasks);
826 if (!keys.length) {
827 return callback(null);
828 }
829
830 var completed = [];
831
832 var listeners = [];
833 var addListener = function (fn) {
834 listeners.unshift(fn);
835 };
836 var removeListener = function (fn) {
837 for (var i = 0; i < listeners.length; i += 1) {
838 if (listeners[i] === fn) {
839 listeners.splice(i, 1);
840 return;
841 }
842 }
843 };
844 var taskComplete = function () {
845 _forEach(listeners, function (fn) {
846 fn();
847 });
848 };
849
850 addListener(function () {
851 if (completed.length === keys.length) {
852 callback(null);
853 }
854 });
855
856 _forEach(keys, function (k) {
857 var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
858 var taskCallback = function (err) {
859 if (err) {
860 callback(err);
861 // stop subsequent errors hitting callback multiple times
862 callback = function () {};
863 }
864 else {
865 completed.push(k);
866 taskComplete();
867 }
868 };
869 var requires = task.slice(0, Math.abs(task.length - 1)) || [];
870 var ready = function () {
871 return _reduce(requires, function (a, x) {
872 return (a && _indexOf(completed, x) !== -1);
873 }, true);
874 };
875 if (ready()) {
876 task[task.length - 1](taskCallback);
877 }
878 else {
879 var listener = function () {
880 if (ready()) {
881 removeListener(listener);
882 task[task.length - 1](taskCallback);
883 }
884 };
885 addListener(listener);
886 }
887 });
888 };
889
890 async.waterfall = function (tasks, callback) {
891 if (!tasks.length) {
892 return callback();
893 }
894 callback = callback || function () {};
895 var wrapIterator = function (iterator) {
896 return function (err) {
897 if (err) {
898 callback(err);
899 callback = function () {};
900 }
901 else {
902 var args = Array.prototype.slice.call(arguments, 1);
903 var next = iterator.next();
904 if (next) {
905 args.push(wrapIterator(next));
906 }
907 else {
908 args.push(callback);
909 }
910 async.nextTick(function () {
911 iterator.apply(null, args);
912 });
913 }
914 };
915 };
916 wrapIterator(async.iterator(tasks))();
917 };
918
919 async.parallel = function (tasks, callback) {
920 callback = callback || function () {};
921 if (tasks.constructor === Array) {
922 async.map(tasks, function (fn, callback) {
923 if (fn) {
924 fn(function (err) {
925 var args = Array.prototype.slice.call(arguments, 1);
926 if (args.length <= 1) {
927 args = args[0];
928 }
929 callback.call(null, err, args || null);
930 });
931 }
932 }, callback);
933 }
934 else {
935 var results = {};
936 async.forEach(_keys(tasks), function (k, callback) {
937 tasks[k](function (err) {
938 var args = Array.prototype.slice.call(arguments, 1);
939 if (args.length <= 1) {
940 args = args[0];
941 }
942 results[k] = args;
943 callback(err);
944 });
945 }, function (err) {
946 callback(err, results);
947 });
948 }
949 };
950
951 async.series = function (tasks, callback) {
952 callback = callback || function () {};
953 if (tasks.constructor === Array) {
954 async.mapSeries(tasks, function (fn, callback) {
955 if (fn) {
956 fn(function (err) {
957 var args = Array.prototype.slice.call(arguments, 1);
958 if (args.length <= 1) {
959 args = args[0];
960 }
961 callback.call(null, err, args || null);
962 });
963 }
964 }, callback);
965 }
966 else {
967 var results = {};
968 async.forEachSeries(_keys(tasks), function (k, callback) {
969 tasks[k](function (err) {
970 var args = Array.prototype.slice.call(arguments, 1);
971 if (args.length <= 1) {
972 args = args[0];
973 }
974 results[k] = args;
975 callback(err);
976 });
977 }, function (err) {
978 callback(err, results);
979 });
980 }
981 };
982
983 async.iterator = function (tasks) {
984 var makeCallback = function (index) {
985 var fn = function () {
986 if (tasks.length) {
987 tasks[index].apply(null, arguments);
988 }
989 return fn.next();
990 };
991 fn.next = function () {
992 return (index < tasks.length - 1) ? makeCallback(index + 1): nul l;
993 };
994 return fn;
995 };
996 return makeCallback(0);
997 };
998
999 async.apply = function (fn) {
1000 var args = Array.prototype.slice.call(arguments, 1);
1001 return function () {
1002 return fn.apply(
1003 null, args.concat(Array.prototype.slice.call(arguments))
1004 );
1005 };
1006 };
1007
1008 var _concat = function (eachfn, arr, fn, callback) {
1009 var r = [];
1010 eachfn(arr, function (x, cb) {
1011 fn(x, function (err, y) {
1012 r = r.concat(y || []);
1013 cb(err);
1014 });
1015 }, function (err) {
1016 callback(err, r);
1017 });
1018 };
1019 async.concat = doParallel(_concat);
1020 async.concatSeries = doSeries(_concat);
1021
1022 async.whilst = function (test, iterator, callback) {
1023 if (test()) {
1024 iterator(function (err) {
1025 if (err) {
1026 return callback(err);
1027 }
1028 async.whilst(test, iterator, callback);
1029 });
1030 }
1031 else {
1032 callback();
1033 }
1034 };
1035
1036 async.until = function (test, iterator, callback) {
1037 if (!test()) {
1038 iterator(function (err) {
1039 if (err) {
1040 return callback(err);
1041 }
1042 async.until(test, iterator, callback);
1043 });
1044 }
1045 else {
1046 callback();
1047 }
1048 };
1049
1050 async.queue = function (worker, concurrency) {
1051 var workers = 0;
1052 var tasks = [];
1053 var q = {
1054 concurrency: concurrency,
1055 push: function (data, callback) {
1056 tasks.push({data: data, callback: callback});
1057 async.nextTick(q.process);
1058 },
1059 process: function () {
1060 if (workers < q.concurrency && tasks.length) {
1061 var task = tasks.splice(0, 1)[0];
1062 workers += 1;
1063 worker(task.data, function () {
1064 workers -= 1;
1065 if (task.callback) {
1066 task.callback.apply(task, arguments);
1067 }
1068 q.process();
1069 });
1070 }
1071 },
1072 length: function () {
1073 return tasks.length;
1074 }
1075 };
1076 return q;
1077 };
1078
1079 var _console_fn = function (name) {
1080 return function (fn) {
1081 var args = Array.prototype.slice.call(arguments, 1);
1082 fn.apply(null, args.concat([function (err) {
1083 var args = Array.prototype.slice.call(arguments, 1);
1084 if (typeof console !== 'undefined') {
1085 if (err) {
1086 if (console.error) {
1087 console.error(err);
1088 }
1089 }
1090 else if (console[name]) {
1091 _forEach(args, function (x) {
1092 console[name](x);
1093 });
1094 }
1095 }
1096 }]));
1097 };
1098 };
1099 async.log = _console_fn('log');
1100 async.dir = _console_fn('dir');
1101 /*async.info = _console_fn('info');
1102 async.warn = _console_fn('warn');
1103 async.error = _console_fn('error');*/
1104
1105 async.memoize = function (fn, hasher) {
1106 var memo = {};
1107 hasher = hasher || function (x) {
1108 return x;
1109 };
1110 return function () {
1111 var args = Array.prototype.slice.call(arguments);
1112 var callback = args.pop();
1113 var key = hasher.apply(null, args);
1114 if (key in memo) {
1115 callback.apply(null, memo[key]);
1116 }
1117 else {
1118 fn.apply(null, args.concat([function () {
1119 memo[key] = arguments;
1120 callback.apply(null, arguments);
1121 }]));
1122 }
1123 };
1124 };
1125
1126 }());
1127 (function(exports){
1128 /**
1129 * This file is based on the node.js assert module, but with some small
1130 * changes for browser-compatibility
1131 * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
1132 */
1133
1134
1135 /**
1136 * Added for browser compatibility
1137 */
1138
1139 var _keys = function(obj){
1140 if(Object.keys) return Object.keys(obj);
1141 if (typeof obj != 'object' && typeof obj != 'function') {
1142 throw new TypeError('-');
1143 }
1144 var keys = [];
1145 for(var k in obj){
1146 if(obj.hasOwnProperty(k)) keys.push(k);
1147 }
1148 return keys;
1149 };
1150
1151
1152
1153 // http://wiki.commonjs.org/wiki/Unit_Testing/1.0
1154 //
1155 // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
1156 //
1157 // Originally from narwhal.js (http://narwhaljs.org)
1158 // Copyright (c) 2009 Thomas Robinson <280north.com>
1159 //
1160 // Permission is hereby granted, free of charge, to any person obtaining a copy
1161 // of this software and associated documentation files (the 'Software'), to
1162 // deal in the Software without restriction, including without limitation the
1163 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1164 // sell copies of the Software, and to permit persons to whom the Software is
1165 // furnished to do so, subject to the following conditions:
1166 //
1167 // The above copyright notice and this permission notice shall be included in
1168 // all copies or substantial portions of the Software.
1169 //
1170 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1171 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1172 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1173 // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1174 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1175 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1176
1177
1178 var pSlice = Array.prototype.slice;
1179
1180 // 1. The assert module provides functions that throw
1181 // AssertionError's when particular conditions are not met. The
1182 // assert module must conform to the following interface.
1183
1184 var assert = exports;
1185
1186 // 2. The AssertionError is defined in assert.
1187 // new assert.AssertionError({message: message, actual: actual, expected: expect ed})
1188
1189 assert.AssertionError = function AssertionError (options) {
1190 this.name = "AssertionError";
1191 this.message = options.message;
1192 this.actual = options.actual;
1193 this.expected = options.expected;
1194 this.operator = options.operator;
1195 var stackStartFunction = options.stackStartFunction || fail;
1196
1197 if (Error.captureStackTrace) {
1198 Error.captureStackTrace(this, stackStartFunction);
1199 }
1200 };
1201 // code from util.inherits in node
1202 assert.AssertionError.super_ = Error;
1203
1204
1205 // EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call
1206 // TODO: test what effect this may have
1207 var ctor = function () { this.constructor = assert.AssertionError; };
1208 ctor.prototype = Error.prototype;
1209 assert.AssertionError.prototype = new ctor();
1210
1211
1212 assert.AssertionError.prototype.toString = function() {
1213 if (this.message) {
1214 return [this.name+":", this.message].join(' ');
1215 } else {
1216 return [ this.name+":"
1217 , typeof this.expected !== 'undefined' ? JSON.stringify(this.expected ) : 'undefined'
1218 , this.operator
1219 , typeof this.actual !== 'undefined' ? JSON.stringify(this.actual) : 'undefined'
1220 ].join(" ");
1221 }
1222 };
1223
1224 // assert.AssertionError instanceof Error
1225
1226 assert.AssertionError.__proto__ = Error.prototype;
1227
1228 // At present only the three keys mentioned above are used and
1229 // understood by the spec. Implementations or sub modules can pass
1230 // other keys to the AssertionError's constructor - they will be
1231 // ignored.
1232
1233 // 3. All of the following functions must throw an AssertionError
1234 // when a corresponding condition is not met, with a message that
1235 // may be undefined if not provided. All assertion methods provide
1236 // both the actual and expected values to the assertion error for
1237 // display purposes.
1238
1239 function fail(actual, expected, message, operator, stackStartFunction) {
1240 throw new assert.AssertionError({
1241 message: message,
1242 actual: actual,
1243 expected: expected,
1244 operator: operator,
1245 stackStartFunction: stackStartFunction
1246 });
1247 }
1248
1249 // EXTENSION! allows for well behaved errors defined elsewhere.
1250 assert.fail = fail;
1251
1252 // 4. Pure assertion tests whether a value is truthy, as determined
1253 // by !!guard.
1254 // assert.ok(guard, message_opt);
1255 // This statement is equivalent to assert.equal(true, guard,
1256 // message_opt);. To test strictly for the value true, use
1257 // assert.strictEqual(true, guard, message_opt);.
1258
1259 assert.ok = function ok(value, message) {
1260 if (!!!value) fail(value, true, message, "==", assert.ok);
1261 };
1262
1263 // 5. The equality assertion tests shallow, coercive equality with
1264 // ==.
1265 // assert.equal(actual, expected, message_opt);
1266
1267 assert.equal = function equal(actual, expected, message) {
1268 if (actual != expected) fail(actual, expected, message, "==", assert.equal);
1269 };
1270
1271 // 6. The non-equality assertion tests for whether two objects are not equal
1272 // with != assert.notEqual(actual, expected, message_opt);
1273
1274 assert.notEqual = function notEqual(actual, expected, message) {
1275 if (actual == expected) {
1276 fail(actual, expected, message, "!=", assert.notEqual);
1277 }
1278 };
1279
1280 // 7. The equivalence assertion tests a deep equality relation.
1281 // assert.deepEqual(actual, expected, message_opt);
1282
1283 assert.deepEqual = function deepEqual(actual, expected, message) {
1284 if (!_deepEqual(actual, expected)) {
1285 fail(actual, expected, message, "deepEqual", assert.deepEqual);
1286 }
1287 };
1288
1289 var Buffer = null;
1290 if (typeof require !== 'undefined' && typeof process !== 'undefined') {
1291 try {
1292 Buffer = require('buffer').Buffer;
1293 }
1294 catch (e) {
1295 // May be a CommonJS environment other than Node.js
1296 Buffer = null;
1297 }
1298 }
1299
1300 function _deepEqual(actual, expected) {
1301 // 7.1. All identical values are equivalent, as determined by ===.
1302 if (actual === expected) {
1303 return true;
1304 // 7.2. If the expected value is a Date object, the actual value is
1305 // equivalent if it is also a Date object that refers to the same time.
1306 } else if (actual instanceof Date && expected instanceof Date) {
1307 return actual.getTime() === expected.getTime();
1308
1309 // 7.2.1 If the expcted value is a RegExp object, the actual value is
1310 // equivalent if it is also a RegExp object that refers to the same source and options
1311 } else if (actual instanceof RegExp && expected instanceof RegExp) {
1312 return actual.source === expected.source &&
1313 actual.global === expected.global &&
1314 actual.ignoreCase === expected.ignoreCase &&
1315 actual.multiline === expected.multiline;
1316
1317 } else if (Buffer && actual instanceof Buffer && expected instanceof Buffer) {
1318 return (function() {
1319 var i, len;
1320
1321 for (i = 0, len = expected.length; i < len; i++) {
1322 if (actual[i] !== expected[i]) {
1323 return false;
1324 }
1325 }
1326 return actual.length === expected.length;
1327 })();
1328 // 7.3. Other pairs that do not both pass typeof value == "object",
1329 // equivalence is determined by ==.
1330 } else if (typeof actual != 'object' && typeof expected != 'object') {
1331 return actual == expected;
1332
1333 // 7.4. For all other Object pairs, including Array objects, equivalence is
1334 // determined by having the same number of owned properties (as verified
1335 // with Object.prototype.hasOwnProperty.call), the same set of keys
1336 // (although not necessarily the same order), equivalent values for every
1337 // corresponding key, and an identical "prototype" property. Note: this
1338 // accounts for both named and indexed properties on Arrays.
1339 } else {
1340 return objEquiv(actual, expected);
1341 }
1342 }
1343
1344 function isUndefinedOrNull (value) {
1345 return value === null || value === undefined;
1346 }
1347
1348 function isArguments (object) {
1349 return Object.prototype.toString.call(object) == '[object Arguments]';
1350 }
1351
1352 function objEquiv (a, b) {
1353 if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
1354 return false;
1355 // an identical "prototype" property.
1356 if (a.prototype !== b.prototype) return false;
1357 //~~~I've managed to break Object.keys through screwy arguments passing.
1358 // Converting to array solves the problem.
1359 if (isArguments(a)) {
1360 if (!isArguments(b)) {
1361 return false;
1362 }
1363 a = pSlice.call(a);
1364 b = pSlice.call(b);
1365 return _deepEqual(a, b);
1366 }
1367 try{
1368 var ka = _keys(a),
1369 kb = _keys(b),
1370 key, i;
1371 } catch (e) {//happens when one is a string literal and the other isn't
1372 return false;
1373 }
1374 // having the same number of owned properties (keys incorporates hasOwnPropert y)
1375 if (ka.length != kb.length)
1376 return false;
1377 //the same set of keys (although not necessarily the same order),
1378 ka.sort();
1379 kb.sort();
1380 //~~~cheap key test
1381 for (i = ka.length - 1; i >= 0; i--) {
1382 if (ka[i] != kb[i])
1383 return false;
1384 }
1385 //equivalent values for every corresponding key, and
1386 //~~~possibly expensive deep test
1387 for (i = ka.length - 1; i >= 0; i--) {
1388 key = ka[i];
1389 if (!_deepEqual(a[key], b[key] ))
1390 return false;
1391 }
1392 return true;
1393 }
1394
1395 // 8. The non-equivalence assertion tests for any deep inequality.
1396 // assert.notDeepEqual(actual, expected, message_opt);
1397
1398 assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
1399 if (_deepEqual(actual, expected)) {
1400 fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual);
1401 }
1402 };
1403
1404 // 9. The strict equality assertion tests strict equality, as determined by ===.
1405 // assert.strictEqual(actual, expected, message_opt);
1406
1407 assert.strictEqual = function strictEqual(actual, expected, message) {
1408 if (actual !== expected) {
1409 fail(actual, expected, message, "===", assert.strictEqual);
1410 }
1411 };
1412
1413 // 10. The strict non-equality assertion tests for strict inequality, as determi ned by !==.
1414 // assert.notStrictEqual(actual, expected, message_opt);
1415
1416 assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
1417 if (actual === expected) {
1418 fail(actual, expected, message, "!==", assert.notStrictEqual);
1419 }
1420 };
1421
1422 function expectedException(actual, expected) {
1423 if (!actual || !expected) {
1424 return false;
1425 }
1426
1427 if (expected instanceof RegExp) {
1428 return expected.test(actual.message || actual);
1429 } else if (actual instanceof expected) {
1430 return true;
1431 } else if (expected.call({}, actual) === true) {
1432 return true;
1433 }
1434
1435 return false;
1436 }
1437
1438 function _throws(shouldThrow, block, expected, message) {
1439 var actual;
1440
1441 if (typeof expected === 'string') {
1442 message = expected;
1443 expected = null;
1444 }
1445
1446 try {
1447 block();
1448 } catch (e) {
1449 actual = e;
1450 }
1451
1452 message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
1453 (message ? ' ' + message : '.');
1454
1455 if (shouldThrow && !actual) {
1456 fail('Missing expected exception' + message);
1457 }
1458
1459 if (!shouldThrow && expectedException(actual, expected)) {
1460 fail('Got unwanted exception' + message);
1461 }
1462
1463 if ((shouldThrow && actual && expected &&
1464 !expectedException(actual, expected)) || (!shouldThrow && actual)) {
1465 throw actual;
1466 }
1467 }
1468
1469 // 11. Expected to throw an error:
1470 // assert.throws(block, Error_opt, message_opt);
1471
1472 assert.throws = function(block, /*optional*/error, /*optional*/message) {
1473 _throws.apply(this, [true].concat(pSlice.call(arguments)));
1474 };
1475
1476 // EXTENSION! This is annoying to write outside this module.
1477 assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
1478 _throws.apply(this, [false].concat(pSlice.call(arguments)));
1479 };
1480
1481 assert.ifError = function (err) { if (err) {throw err;}};
1482 })(assert);
1483 (function(exports){
1484 /*!
1485 * Nodeunit
1486 * Copyright (c) 2010 Caolan McMahon
1487 * MIT Licensed
1488 *
1489 * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
1490 * Only code on that line will be removed, it's mostly to avoid requiring code
1491 * that is node specific
1492 */
1493
1494 /**
1495 * Module dependencies
1496 */
1497
1498
1499
1500 /**
1501 * Creates assertion objects representing the result of an assert call.
1502 * Accepts an object or AssertionError as its argument.
1503 *
1504 * @param {object} obj
1505 * @api public
1506 */
1507
1508 exports.assertion = function (obj) {
1509 return {
1510 method: obj.method || '',
1511 message: obj.message || (obj.error && obj.error.message) || '',
1512 error: obj.error,
1513 passed: function () {
1514 return !this.error;
1515 },
1516 failed: function () {
1517 return Boolean(this.error);
1518 }
1519 };
1520 };
1521
1522 /**
1523 * Creates an assertion list object representing a group of assertions.
1524 * Accepts an array of assertion objects.
1525 *
1526 * @param {Array} arr
1527 * @param {Number} duration
1528 * @api public
1529 */
1530
1531 exports.assertionList = function (arr, duration) {
1532 var that = arr || [];
1533 that.failures = function () {
1534 var failures = 0;
1535 for (var i = 0; i < this.length; i += 1) {
1536 if (this[i].failed()) {
1537 failures += 1;
1538 }
1539 }
1540 return failures;
1541 };
1542 that.passes = function () {
1543 return that.length - that.failures();
1544 };
1545 that.duration = duration || 0;
1546 return that;
1547 };
1548
1549 /**
1550 * Create a wrapper function for assert module methods. Executes a callback
1551 * after it's complete with an assertion object representing the result.
1552 *
1553 * @param {Function} callback
1554 * @api private
1555 */
1556
1557 var assertWrapper = function (callback) {
1558 return function (new_method, assert_method, arity) {
1559 return function () {
1560 var message = arguments[arity - 1];
1561 var a = exports.assertion({method: new_method, message: message});
1562 try {
1563 assert[assert_method].apply(null, arguments);
1564 }
1565 catch (e) {
1566 a.error = e;
1567 }
1568 callback(a);
1569 };
1570 };
1571 };
1572
1573 /**
1574 * Creates the 'test' object that gets passed to every test function.
1575 * Accepts the name of the test function as its first argument, followed by
1576 * the start time in ms, the options object and a callback function.
1577 *
1578 * @param {String} name
1579 * @param {Number} start
1580 * @param {Object} options
1581 * @param {Function} callback
1582 * @api public
1583 */
1584
1585 exports.test = function (name, start, options, callback) {
1586 var expecting;
1587 var a_list = [];
1588
1589 var wrapAssert = assertWrapper(function (a) {
1590 a_list.push(a);
1591 if (options.log) {
1592 async.nextTick(function () {
1593 options.log(a);
1594 });
1595 }
1596 });
1597
1598 var test = {
1599 done: function (err) {
1600 if (expecting !== undefined && expecting !== a_list.length) {
1601 var e = new Error(
1602 'Expected ' + expecting + ' assertions, ' +
1603 a_list.length + ' ran'
1604 );
1605 var a1 = exports.assertion({method: 'expect', error: e});
1606 a_list.push(a1);
1607 if (options.log) {
1608 async.nextTick(function () {
1609 options.log(a1);
1610 });
1611 }
1612 }
1613 if (err) {
1614 var a2 = exports.assertion({error: err});
1615 a_list.push(a2);
1616 if (options.log) {
1617 async.nextTick(function () {
1618 options.log(a2);
1619 });
1620 }
1621 }
1622 var end = new Date().getTime();
1623 async.nextTick(function () {
1624 var assertion_list = exports.assertionList(a_list, end - start);
1625 options.testDone(name, assertion_list);
1626 callback(null, a_list);
1627 });
1628 },
1629 ok: wrapAssert('ok', 'ok', 2),
1630 same: wrapAssert('same', 'deepEqual', 3),
1631 equals: wrapAssert('equals', 'equal', 3),
1632 expect: function (num) {
1633 expecting = num;
1634 },
1635 _assertion_list: a_list
1636 };
1637 // add all functions from the assert module
1638 for (var k in assert) {
1639 if (assert.hasOwnProperty(k)) {
1640 test[k] = wrapAssert(k, k, assert[k].length);
1641 }
1642 }
1643 return test;
1644 };
1645
1646 /**
1647 * Ensures an options object has all callbacks, adding empty callback functions
1648 * if any are missing.
1649 *
1650 * @param {Object} opt
1651 * @return {Object}
1652 * @api public
1653 */
1654
1655 exports.options = function (opt) {
1656 var optionalCallback = function (name) {
1657 opt[name] = opt[name] || function () {};
1658 };
1659
1660 optionalCallback('moduleStart');
1661 optionalCallback('moduleDone');
1662 optionalCallback('testStart');
1663 optionalCallback('testReady');
1664 optionalCallback('testDone');
1665 //optionalCallback('log');
1666
1667 // 'done' callback is not optional.
1668
1669 return opt;
1670 };
1671 })(types);
1672 (function(exports){
1673 /*!
1674 * Nodeunit
1675 * Copyright (c) 2010 Caolan McMahon
1676 * MIT Licensed
1677 *
1678 * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
1679 * Only code on that line will be removed, it's mostly to avoid requiring code
1680 * that is node specific
1681 */
1682
1683 /**
1684 * Module dependencies
1685 */
1686
1687
1688
1689 /**
1690 * Added for browser compatibility
1691 */
1692
1693 var _keys = function (obj) {
1694 if (Object.keys) {
1695 return Object.keys(obj);
1696 }
1697 var keys = [];
1698 for (var k in obj) {
1699 if (obj.hasOwnProperty(k)) {
1700 keys.push(k);
1701 }
1702 }
1703 return keys;
1704 };
1705
1706
1707 var _copy = function (obj) {
1708 var nobj = {};
1709 var keys = _keys(obj);
1710 for (var i = 0; i < keys.length; i += 1) {
1711 nobj[keys[i]] = obj[keys[i]];
1712 }
1713 return nobj;
1714 };
1715
1716
1717 /**
1718 * Runs a test function (fn) from a loaded module. After the test function
1719 * calls test.done(), the callback is executed with an assertionList as its
1720 * second argument.
1721 *
1722 * @param {String} name
1723 * @param {Function} fn
1724 * @param {Object} opt
1725 * @param {Function} callback
1726 * @api public
1727 */
1728
1729 exports.runTest = function (name, fn, opt, callback) {
1730 var options = types.options(opt);
1731
1732 options.testStart(name);
1733 var start = new Date().getTime();
1734 var test = types.test(name, start, options, callback);
1735
1736 options.testReady(test);
1737 try {
1738 fn(test);
1739 }
1740 catch (e) {
1741 test.done(e);
1742 }
1743 };
1744
1745 /**
1746 * Takes an object containing test functions or other test suites as properties
1747 * and runs each in series. After all tests have completed, the callback is
1748 * called with a list of all assertions as the second argument.
1749 *
1750 * If a name is passed to this function it is prepended to all test and suite
1751 * names that run within it.
1752 *
1753 * @param {String} name
1754 * @param {Object} suite
1755 * @param {Object} opt
1756 * @param {Function} callback
1757 * @api public
1758 */
1759
1760 exports.runSuite = function (name, suite, opt, callback) {
1761 suite = wrapGroup(suite);
1762 var keys = _keys(suite);
1763
1764 async.concatSeries(keys, function (k, cb) {
1765 var prop = suite[k], _name;
1766
1767 _name = name ? [].concat(name, k) : [k];
1768 _name.toString = function () {
1769 // fallback for old one
1770 return this.join(' - ');
1771 };
1772
1773 if (typeof prop === 'function') {
1774 var in_name = false,
1775 in_specific_test = (_name.toString() === opt.testFullSpec) ? tru e : false;
1776 for (var i = 0; i < _name.length; i += 1) {
1777 if (_name[i] === opt.testspec) {
1778 in_name = true;
1779 }
1780 }
1781
1782 if ((!opt.testFullSpec || in_specific_test) && (!opt.testspec || in_ name)) {
1783 if (opt.moduleStart) {
1784 opt.moduleStart();
1785 }
1786 exports.runTest(_name, suite[k], opt, cb);
1787 }
1788 else {
1789 return cb();
1790 }
1791 }
1792 else {
1793 exports.runSuite(_name, suite[k], opt, cb);
1794 }
1795 }, callback);
1796 };
1797
1798 /**
1799 * Run each exported test function or test suite from a loaded module.
1800 *
1801 * @param {String} name
1802 * @param {Object} mod
1803 * @param {Object} opt
1804 * @param {Function} callback
1805 * @api public
1806 */
1807
1808 exports.runModule = function (name, mod, opt, callback) {
1809 var options = _copy(types.options(opt));
1810
1811 var _run = false;
1812 var _moduleStart = options.moduleStart;
1813
1814 mod = wrapGroup(mod);
1815
1816 function run_once() {
1817 if (!_run) {
1818 _run = true;
1819 _moduleStart(name);
1820 }
1821 }
1822 options.moduleStart = run_once;
1823
1824 var start = new Date().getTime();
1825
1826 exports.runSuite(null, mod, options, function (err, a_list) {
1827 var end = new Date().getTime();
1828 var assertion_list = types.assertionList(a_list, end - start);
1829 options.moduleDone(name, assertion_list);
1830 if (nodeunit.complete) {
1831 nodeunit.complete(name, assertion_list);
1832 }
1833 callback(null, a_list);
1834 });
1835 };
1836
1837 /**
1838 * Treats an object literal as a list of modules keyed by name. Runs each
1839 * module and finished with calling 'done'. You can think of this as a browser
1840 * safe alternative to runFiles in the nodeunit module.
1841 *
1842 * @param {Object} modules
1843 * @param {Object} opt
1844 * @api public
1845 */
1846
1847 // TODO: add proper unit tests for this function
1848 exports.runModules = function (modules, opt) {
1849 var all_assertions = [];
1850 var options = types.options(opt);
1851 var start = new Date().getTime();
1852
1853 async.concatSeries(_keys(modules), function (k, cb) {
1854 exports.runModule(k, modules[k], options, cb);
1855 },
1856 function (err, all_assertions) {
1857 var end = new Date().getTime();
1858 options.done(types.assertionList(all_assertions, end - start));
1859 });
1860 };
1861
1862
1863 /**
1864 * Wraps a test function with setUp and tearDown functions.
1865 * Used by testCase.
1866 *
1867 * @param {Function} setUp
1868 * @param {Function} tearDown
1869 * @param {Function} fn
1870 * @api private
1871 */
1872
1873 var wrapTest = function (setUp, tearDown, fn) {
1874 return function (test) {
1875 var context = {};
1876 if (tearDown) {
1877 var done = test.done;
1878 test.done = function (err) {
1879 try {
1880 tearDown.call(context, function (err2) {
1881 if (err && err2) {
1882 test._assertion_list.push(
1883 types.assertion({error: err})
1884 );
1885 return done(err2);
1886 }
1887 done(err || err2);
1888 });
1889 }
1890 catch (e) {
1891 done(e);
1892 }
1893 };
1894 }
1895 if (setUp) {
1896 setUp.call(context, function (err) {
1897 if (err) {
1898 return test.done(err);
1899 }
1900 fn.call(context, test);
1901 });
1902 }
1903 else {
1904 fn.call(context, test);
1905 }
1906 };
1907 };
1908
1909
1910 /**
1911 * Returns a serial callback from two functions.
1912 *
1913 * @param {Function} funcFirst
1914 * @param {Function} funcSecond
1915 * @api private
1916 */
1917
1918 var getSerialCallback = function (fns) {
1919 if (!fns.length) {
1920 return null;
1921 }
1922 return function (callback) {
1923 var that = this;
1924 var bound_fns = [];
1925 for (var i = 0, len = fns.length; i < len; i++) {
1926 (function (j) {
1927 bound_fns.push(function () {
1928 return fns[j].apply(that, arguments);
1929 });
1930 })(i);
1931 }
1932 return async.series(bound_fns, callback);
1933 };
1934 };
1935
1936
1937 /**
1938 * Wraps a group of tests with setUp and tearDown functions.
1939 * Used by testCase.
1940 *
1941 * @param {Object} group
1942 * @param {Array} setUps - parent setUp functions
1943 * @param {Array} tearDowns - parent tearDown functions
1944 * @api private
1945 */
1946
1947 var wrapGroup = function (group, setUps, tearDowns) {
1948 var tests = {};
1949
1950 var setUps = setUps ? setUps.slice(): [];
1951 var tearDowns = tearDowns ? tearDowns.slice(): [];
1952
1953 if (group.setUp) {
1954 setUps.push(group.setUp);
1955 delete group.setUp;
1956 }
1957 if (group.tearDown) {
1958 tearDowns.unshift(group.tearDown);
1959 delete group.tearDown;
1960 }
1961
1962 var keys = _keys(group);
1963
1964 for (var i = 0; i < keys.length; i += 1) {
1965 var k = keys[i];
1966 if (typeof group[k] === 'function') {
1967 tests[k] = wrapTest(
1968 getSerialCallback(setUps),
1969 getSerialCallback(tearDowns),
1970 group[k]
1971 );
1972 }
1973 else if (typeof group[k] === 'object') {
1974 tests[k] = wrapGroup(group[k], setUps, tearDowns);
1975 }
1976 }
1977 return tests;
1978 };
1979
1980
1981 /**
1982 * Backwards compatibility for test suites using old testCase API
1983 */
1984
1985 exports.testCase = function (suite) {
1986 return suite;
1987 };
1988 })(core);
1989 (function(exports){
1990 /*!
1991 * Nodeunit
1992 * Copyright (c) 2010 Caolan McMahon
1993 * MIT Licensed
1994 *
1995 * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
1996 * Only code on that line will be removed, its mostly to avoid requiring code
1997 * that is node specific
1998 */
1999
2000
2001 /**
2002 * NOTE: this test runner is not listed in index.js because it cannot be
2003 * used with the command-line tool, only inside the browser.
2004 */
2005
2006
2007 /**
2008 * Reporter info string
2009 */
2010
2011 exports.info = "Browser-based test reporter";
2012
2013
2014 /**
2015 * Run all tests within each module, reporting the results
2016 *
2017 * @param {Array} files
2018 * @api public
2019 */
2020
2021 exports.run = function (modules, options, callback) {
2022 var start = new Date().getTime(), div;
2023 options = options || {};
2024 div = options.div || document.body;
2025
2026 function setText(el, txt) {
2027 if ('innerText' in el) {
2028 el.innerText = txt;
2029 }
2030 else if ('textContent' in el){
2031 el.textContent = txt;
2032 }
2033 }
2034
2035 function getOrCreate(tag, id) {
2036 var el = document.getElementById(id);
2037 if (!el) {
2038 el = document.createElement(tag);
2039 el.id = id;
2040 div.appendChild(el);
2041 }
2042 return el;
2043 };
2044
2045 var header = getOrCreate('h1', 'nodeunit-header');
2046 var banner = getOrCreate('h2', 'nodeunit-banner');
2047 var userAgent = getOrCreate('h2', 'nodeunit-userAgent');
2048 var tests = getOrCreate('ol', 'nodeunit-tests');
2049 var result = getOrCreate('p', 'nodeunit-testresult');
2050
2051 setText(userAgent, navigator.userAgent);
2052
2053 nodeunit.runModules(modules, {
2054 moduleStart: function (name) {
2055 /*var mheading = document.createElement('h2');
2056 mheading.innerText = name;
2057 results.appendChild(mheading);
2058 module = document.createElement('ol');
2059 results.appendChild(module);*/
2060 },
2061 testDone: function (name, assertions) {
2062 var test = document.createElement('li');
2063 var strong = document.createElement('strong');
2064 strong.innerHTML = name + ' <b style="color: black;">(' +
2065 '<b class="fail">' + assertions.failures() + '</b>, ' +
2066 '<b class="pass">' + assertions.passes() + '</b>, ' +
2067 assertions.length +
2068 ')</b>';
2069 test.className = assertions.failures() ? 'fail': 'pass';
2070 test.appendChild(strong);
2071
2072 var aList = document.createElement('ol');
2073 aList.style.display = 'none';
2074 test.onclick = function () {
2075 var d = aList.style.display;
2076 aList.style.display = (d == 'none') ? 'block': 'none';
2077 };
2078 for (var i=0; i<assertions.length; i++) {
2079 var li = document.createElement('li');
2080 var a = assertions[i];
2081 if (a.failed()) {
2082 li.innerHTML = (a.message || a.method || 'no message') +
2083 '<pre>' + (a.error.stack || a.error) + '</pre>';
2084 li.className = 'fail';
2085 }
2086 else {
2087 li.innerHTML = a.message || a.method || 'no message';
2088 li.className = 'pass';
2089 }
2090 aList.appendChild(li);
2091 }
2092 test.appendChild(aList);
2093 tests.appendChild(test);
2094 },
2095 done: function (assertions) {
2096 var end = new Date().getTime();
2097 var duration = end - start;
2098
2099 var failures = assertions.failures();
2100 banner.className = failures ? 'fail': 'pass';
2101
2102 result.innerHTML = 'Tests completed in ' + duration +
2103 ' milliseconds.<br/><span class="passed">' +
2104 assertions.passes() + '</span> assertions of ' +
2105 '<span class="all">' + assertions.length + '<span> passed, ' +
2106 assertions.failures() + ' failed.';
2107
2108 if (callback) callback(assertions.failures() ? new Error('We have go t test failures.') : undefined);
2109 }
2110 });
2111 };
2112 })(reporter);
2113 nodeunit = core;
2114 nodeunit.assert = assert;
2115 nodeunit.reporter = reporter;
2116 nodeunit.run = reporter.run;
2117 return nodeunit; })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698