Name: js-handler/node_modules/nodeunit/examples/browser/nodeunit.js
| 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-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, |
| 205: | escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\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 process === 'undefined' || !(process.nextTick)) { |
| 581: | async.nextTick = function (fn) { |
| 582: | setTimeout(fn, 0); |
| 583: | }; |
| 584: | } |
| 585: | else { |
| 586: | async.nextTick = process.nextTick; |
| 587: | } |
| 588: | |
| 589: | async.forEach = function (arr, iterator, callback) { |
| 590: | if (!arr.length) { |
| 591: | return callback(); |
| 592: | } |
| 593: | var completed = 0; |
| 594: | _forEach(arr, function (x) { |
| 595: | iterator(x, function (err) { |
| 596: | if (err) { |
| 597: | callback(err); |
| 598: | callback = function () {}; |
| 599: | } |
| 600: | else { |
| 601: | completed += 1; |
| 602: | if (completed === arr.length) { |
| 603: | callback(); |
| 604: | } |
| 605: | } |
| 606: | }); |
| 607: | }); |
| 608: | }; |
| 609: | |
| 610: | async.forEachSeries = function (arr, iterator, callback) { |
| 611: | if (!arr.length) { |
| 612: | return callback(); |
| 613: | } |
| 614: | var completed = 0; |
| 615: | var iterate = function () { |
| 616: | iterator(arr[completed], function (err) { |
| 617: | if (err) { |
| 618: | callback(err); |
| 619: | callback = function () {}; |
| 620: | } |
| 621: | else { |
| 622: | completed += 1; |
| 623: | if (completed === arr.length) { |
| 624: | callback(); |
| 625: | } |
| 626: | else { |
| 627: | iterate(); |
| 628: | } |
| 629: | } |
| 630: | }); |
| 631: | }; |
| 632: | iterate(); |
| 633: | }; |
| 634: | |
| 635: | |
| 636: | var doParallel = function (fn) { |
| 637: | return function () { |
| 638: | var args = Array.prototype.slice.call(arguments); |
| 639: | return fn.apply(null, [async.forEach].concat(args)); |
| 640: | }; |
| 641: | }; |
| 642: | var doSeries = function (fn) { |
| 643: | return function () { |
| 644: | var args = Array.prototype.slice.call(arguments); |
| 645: | return fn.apply(null, [async.forEachSeries].concat(args)); |
| 646: | }; |
| 647: | }; |
| 648: | |
| 649: | |
| 650: | var _asyncMap = function (eachfn, arr, iterator, callback) { |
| 651: | var results = []; |
| 652: | arr = _map(arr, function (x, i) { |
| 653: | return {index: i, value: x}; |
| 654: | }); |
| 655: | eachfn(arr, function (x, callback) { |
| 656: | iterator(x.value, function (err, v) { |
| 657: | results[x.index] = v; |
| 658: | callback(err); |
| 659: | }); |
| 660: | }, function (err) { |
| 661: | callback(err, results); |
| 662: | }); |
| 663: | }; |
| 664: | async.map = doParallel(_asyncMap); |
| 665: | async.mapSeries = doSeries(_asyncMap); |
| 666: | |
| 667: | |
| 668: | // reduce only has a series version, as doing reduce in parallel won't |
| 669: | // work in many situations. |
| 670: | async.reduce = function (arr, memo, iterator, callback) { |
| 671: | async.forEachSeries(arr, function (x, callback) { |
| 672: | iterator(memo, x, function (err, v) { |
| 673: | memo = v; |
| 674: | callback(err); |
| 675: | }); |
| 676: | }, function (err) { |
| 677: | callback(err, memo); |
| 678: | }); |
| 679: | }; |
| 680: | // inject alias |
| 681: | async.inject = async.reduce; |
| 682: | // foldl alias |
| 683: | async.foldl = async.reduce; |
| 684: | |
| 685: | async.reduceRight = function (arr, memo, iterator, callback) { |
| 686: | var reversed = _map(arr, function (x) { |
| 687: | return x; |
| 688: | }).reverse(); |
| 689: | async.reduce(reversed, memo, iterator, callback); |
| 690: | }; |
| 691: | // foldr alias |
| 692: | async.foldr = async.reduceRight; |
| 693: | |
| 694: | var _filter = function (eachfn, arr, iterator, callback) { |
| 695: | var results = []; |
| 696: | arr = _map(arr, function (x, i) { |
| 697: | return {index: i, value: x}; |
| 698: | }); |
| 699: | eachfn(arr, function (x, callback) { |
| 700: | iterator(x.value, function (v) { |
| 701: | if (v) { |
| 702: | results.push(x); |
| 703: | } |
| 704: | callback(); |
| 705: | }); |
| 706: | }, function (err) { |
| 707: | callback(_map(results.sort(function (a, b) { |
| 708: | return a.index - b.index; |
| 709: | }), function (x) { |
| 710: | return x.value; |
| 711: | })); |
| 712: | }); |
| 713: | }; |
| 714: | async.filter = doParallel(_filter); |
| 715: | async.filterSeries = doSeries(_filter); |
| 716: | // select alias |
| 717: | async.select = async.filter; |
| 718: | async.selectSeries = async.filterSeries; |
| 719: | |
| 720: | var _reject = function (eachfn, arr, iterator, callback) { |
| 721: | var results = []; |
| 722: | arr = _map(arr, function (x, i) { |
| 723: | return {index: i, value: x}; |
| 724: | }); |
| 725: | eachfn(arr, function (x, callback) { |
| 726: | iterator(x.value, function (v) { |
| 727: | if (!v) { |
| 728: | results.push(x); |
| 729: | } |
| 730: | callback(); |
| 731: | }); |
| 732: | }, function (err) { |
| 733: | callback(_map(results.sort(function (a, b) { |
| 734: | return a.index - b.index; |
| 735: | }), function (x) { |
| 736: | return x.value; |
| 737: | })); |
| 738: | }); |
| 739: | }; |
| 740: | async.reject = doParallel(_reject); |
| 741: | async.rejectSeries = doSeries(_reject); |
| 742: | |
| 743: | var _detect = function (eachfn, arr, iterator, main_callback) { |
| 744: | eachfn(arr, function (x, callback) { |
| 745: | iterator(x, function (result) { |
| 746: | if (result) { |
| 747: | main_callback(x); |
| 748: | } |
| 749: | else { |
| 750: | callback(); |
| 751: | } |
| 752: | }); |
| 753: | }, function (err) { |
| 754: | main_callback(); |
| 755: | }); |
| 756: | }; |
| 757: | async.detect = doParallel(_detect); |
| 758: | async.detectSeries = doSeries(_detect); |
| 759: | |
| 760: | async.some = function (arr, iterator, main_callback) { |
| 761: | async.forEach(arr, function (x, callback) { |
| 762: | iterator(x, function (v) { |
| 763: | if (v) { |
| 764: | main_callback(true); |
| 765: | main_callback = function () {}; |
| 766: | } |
| 767: | callback(); |
| 768: | }); |
| 769: | }, function (err) { |
| 770: | main_callback(false); |
| 771: | }); |
| 772: | }; |
| 773: | // any alias |
| 774: | async.any = async.some; |
| 775: | |
| 776: | async.every = function (arr, iterator, main_callback) { |
| 777: | async.forEach(arr, function (x, callback) { |
| 778: | iterator(x, function (v) { |
| 779: | if (!v) { |
| 780: | main_callback(false); |
| 781: | main_callback = function () {}; |
| 782: | } |
| 783: | callback(); |
| 784: | }); |
| 785: | }, function (err) { |
| 786: | main_callback(true); |
| 787: | }); |
| 788: | }; |
| 789: | // all alias |
| 790: | async.all = async.every; |
| 791: | |
| 792: | async.sortBy = function (arr, iterator, callback) { |
| 793: | async.map(arr, function (x, callback) { |
| 794: | iterator(x, function (err, criteria) { |
| 795: | if (err) { |
| 796: | callback(err); |
| 797: | } |
| 798: | else { |
| 799: | callback(null, {value: x, criteria: criteria}); |
| 800: | } |
| 801: | }); |
| 802: | }, function (err, results) { |
| 803: | if (err) { |
| 804: | return callback(err); |
| 805: | } |
| 806: | else { |
| 807: | var fn = function (left, right) { |
| 808: | var a = left.criteria, b = right.criteria; |
| 809: | return a < b ? -1 : a > b ? 1 : 0; |
| 810: | }; |
| 811: | callback(null, _map(results.sort(fn), function (x) { |
| 812: | return x.value; |
| 813: | })); |
| 814: | } |
| 815: | }); |
| 816: | }; |
| 817: | |
| 818: | async.auto = function (tasks, callback) { |
| 819: | callback = callback || function () {}; |
| 820: | var keys = _keys(tasks); |
| 821: | if (!keys.length) { |
| 822: | return callback(null); |
| 823: | } |
| 824: | |
| 825: | var completed = []; |
| 826: | |
| 827: | var listeners = []; |
| 828: | var addListener = function (fn) { |
| 829: | listeners.unshift(fn); |
| 830: | }; |
| 831: | var removeListener = function (fn) { |
| 832: | for (var i = 0; i < listeners.length; i += 1) { |
| 833: | if (listeners[i] === fn) { |
| 834: | listeners.splice(i, 1); |
| 835: | return; |
| 836: | } |
| 837: | } |
| 838: | }; |
| 839: | var taskComplete = function () { |
| 840: | _forEach(listeners, function (fn) { |
| 841: | fn(); |
| 842: | }); |
| 843: | }; |
| 844: | |
| 845: | addListener(function () { |
| 846: | if (completed.length === keys.length) { |
| 847: | callback(null); |
| 848: | } |
| 849: | }); |
| 850: | |
| 851: | _forEach(keys, function (k) { |
| 852: | var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; |
| 853: | var taskCallback = function (err) { |
| 854: | if (err) { |
| 855: | callback(err); |
| 856: | // stop subsequent errors hitting callback multiple times |
| 857: | callback = function () {}; |
| 858: | } |
| 859: | else { |
| 860: | completed.push(k); |
| 861: | taskComplete(); |
| 862: | } |
| 863: | }; |
| 864: | var requires = task.slice(0, Math.abs(task.length - 1)) || []; |
| 865: | var ready = function () { |
| 866: | return _reduce(requires, function (a, x) { |
| 867: | return (a && _indexOf(completed, x) !== -1); |
| 868: | }, true); |
| 869: | }; |
| 870: | if (ready()) { |
| 871: | task[task.length - 1](taskCallback); |
| 872: | } |
| 873: | else { |
| 874: | var listener = function () { |
| 875: | if (ready()) { |
| 876: | removeListener(listener); |
| 877: | task[task.length - 1](taskCallback); |
| 878: | } |
| 879: | }; |
| 880: | addListener(listener); |
| 881: | } |
| 882: | }); |
| 883: | }; |
| 884: | |
| 885: | async.waterfall = function (tasks, callback) { |
| 886: | if (!tasks.length) { |
| 887: | return callback(); |
| 888: | } |
| 889: | callback = callback || function () {}; |
| 890: | var wrapIterator = function (iterator) { |
| 891: | return function (err) { |
| 892: | if (err) { |
| 893: | callback(err); |
| 894: | callback = function () {}; |
| 895: | } |
| 896: | else { |
| 897: | var args = Array.prototype.slice.call(arguments, 1); |
| 898: | var next = iterator.next(); |
| 899: | if (next) { |
| 900: | args.push(wrapIterator(next)); |
| 901: | } |
| 902: | else { |
| 903: | args.push(callback); |
| 904: | } |
| 905: | async.nextTick(function () { |
| 906: | iterator.apply(null, args); |
| 907: | }); |
| 908: | } |
| 909: | }; |
| 910: | }; |
| 911: | wrapIterator(async.iterator(tasks))(); |
| 912: | }; |
| 913: | |
| 914: | async.parallel = function (tasks, callback) { |
| 915: | callback = callback || function () {}; |
| 916: | if (tasks.constructor === Array) { |
| 917: | async.map(tasks, function (fn, callback) { |
| 918: | if (fn) { |
| 919: | fn(function (err) { |
| 920: | var args = Array.prototype.slice.call(arguments, 1); |
| 921: | if (args.length <= 1) { |
| 922: | args = args[0]; |
| 923: | } |
| 924: | callback.call(null, err, args || null); |
| 925: | }); |
| 926: | } |
| 927: | }, callback); |
| 928: | } |
| 929: | else { |
| 930: | var results = {}; |
| 931: | async.forEach(_keys(tasks), function (k, callback) { |
| 932: | tasks[k](function (err) { |
| 933: | var args = Array.prototype.slice.call(arguments, 1); |
| 934: | if (args.length <= 1) { |
| 935: | args = args[0]; |
| 936: | } |
| 937: | results[k] = args; |
| 938: | callback(err); |
| 939: | }); |
| 940: | }, function (err) { |
| 941: | callback(err, results); |
| 942: | }); |
| 943: | } |
| 944: | }; |
| 945: | |
| 946: | async.series = function (tasks, callback) { |
| 947: | callback = callback || function () {}; |
| 948: | if (tasks.constructor === Array) { |
| 949: | async.mapSeries(tasks, function (fn, callback) { |
| 950: | if (fn) { |
| 951: | fn(function (err) { |
| 952: | var args = Array.prototype.slice.call(arguments, 1); |
| 953: | if (args.length <= 1) { |
| 954: | args = args[0]; |
| 955: | } |
| 956: | callback.call(null, err, args || null); |
| 957: | }); |
| 958: | } |
| 959: | }, callback); |
| 960: | } |
| 961: | else { |
| 962: | var results = {}; |
| 963: | async.forEachSeries(_keys(tasks), function (k, callback) { |
| 964: | tasks[k](function (err) { |
| 965: | var args = Array.prototype.slice.call(arguments, 1); |
| 966: | if (args.length <= 1) { |
| 967: | args = args[0]; |
| 968: | } |
| 969: | results[k] = args; |
| 970: | callback(err); |
| 971: | }); |
| 972: | }, function (err) { |
| 973: | callback(err, results); |
| 974: | }); |
| 975: | } |
| 976: | }; |
| 977: | |
| 978: | async.iterator = function (tasks) { |
| 979: | var makeCallback = function (index) { |
| 980: | var fn = function () { |
| 981: | if (tasks.length) { |
| 982: | tasks[index].apply(null, arguments); |
| 983: | } |
| 984: | return fn.next(); |
| 985: | }; |
| 986: | fn.next = function () { |
| 987: | return (index < tasks.length - 1) ? makeCallback(index + 1): null; |
| 988: | }; |
| 989: | return fn; |
| 990: | }; |
| 991: | return makeCallback(0); |
| 992: | }; |
| 993: | |
| 994: | async.apply = function (fn) { |
| 995: | var args = Array.prototype.slice.call(arguments, 1); |
| 996: | return function () { |
| 997: | return fn.apply( |
| 998: | null, args.concat(Array.prototype.slice.call(arguments)) |
| 999: | ); |
| 1000: | }; |
| 1001: | }; |
| 1002: | |
| 1003: | var _concat = function (eachfn, arr, fn, callback) { |
| 1004: | var r = []; |
| 1005: | eachfn(arr, function (x, cb) { |
| 1006: | fn(x, function (err, y) { |
| 1007: | r = r.concat(y || []); |
| 1008: | cb(err); |
| 1009: | }); |
| 1010: | }, function (err) { |
| 1011: | callback(err, r); |
| 1012: | }); |
| 1013: | }; |
| 1014: | async.concat = doParallel(_concat); |
| 1015: | async.concatSeries = doSeries(_concat); |
| 1016: | |
| 1017: | async.whilst = function (test, iterator, callback) { |
| 1018: | if (test()) { |
| 1019: | iterator(function (err) { |
| 1020: | if (err) { |
| 1021: | return callback(err); |
| 1022: | } |
| 1023: | async.whilst(test, iterator, callback); |
| 1024: | }); |
| 1025: | } |
| 1026: | else { |
| 1027: | callback(); |
| 1028: | } |
| 1029: | }; |
| 1030: | |
| 1031: | async.until = function (test, iterator, callback) { |
| 1032: | if (!test()) { |
| 1033: | iterator(function (err) { |
| 1034: | if (err) { |
| 1035: | return callback(err); |
| 1036: | } |
| 1037: | async.until(test, iterator, callback); |
| 1038: | }); |
| 1039: | } |
| 1040: | else { |
| 1041: | callback(); |
| 1042: | } |
| 1043: | }; |
| 1044: | |
| 1045: | async.queue = function (worker, concurrency) { |
| 1046: | var workers = 0; |
| 1047: | var tasks = []; |
| 1048: | var q = { |
| 1049: | concurrency: concurrency, |
| 1050: | push: function (data, callback) { |
| 1051: | tasks.push({data: data, callback: callback}); |
| 1052: | async.nextTick(q.process); |
| 1053: | }, |
| 1054: | process: function () { |
| 1055: | if (workers < q.concurrency && tasks.length) { |
| 1056: | var task = tasks.splice(0, 1)[0]; |
| 1057: | workers += 1; |
| 1058: | worker(task.data, function () { |
| 1059: | workers -= 1; |
| 1060: | if (task.callback) { |
| 1061: | task.callback.apply(task, arguments); |
| 1062: | } |
| 1063: | q.process(); |
| 1064: | }); |
| 1065: | } |
| 1066: | }, |
| 1067: | length: function () { |
| 1068: | return tasks.length; |
| 1069: | } |
| 1070: | }; |
| 1071: | return q; |
| 1072: | }; |
| 1073: | |
| 1074: | var _console_fn = function (name) { |
| 1075: | return function (fn) { |
| 1076: | var args = Array.prototype.slice.call(arguments, 1); |
| 1077: | fn.apply(null, args.concat([function (err) { |
| 1078: | var args = Array.prototype.slice.call(arguments, 1); |
| 1079: | if (typeof console !== 'undefined') { |
| 1080: | if (err) { |
| 1081: | if (console.error) { |
| 1082: | console.error(err); |
| 1083: | } |
| 1084: | } |
| 1085: | else if (console[name]) { |
| 1086: | _forEach(args, function (x) { |
| 1087: | console[name](x); |
| 1088: | }); |
| 1089: | } |
| 1090: | } |
| 1091: | }])); |
| 1092: | }; |
| 1093: | }; |
| 1094: | async.log = _console_fn('log'); |
| 1095: | async.dir = _console_fn('dir'); |
| 1096: | /*async.info = _console_fn('info'); |
| 1097: | async.warn = _console_fn('warn'); |
| 1098: | async.error = _console_fn('error');*/ |
| 1099: | |
| 1100: | async.memoize = function (fn, hasher) { |
| 1101: | var memo = {}; |
| 1102: | hasher = hasher || function (x) { |
| 1103: | return x; |
| 1104: | }; |
| 1105: | return function () { |
| 1106: | var args = Array.prototype.slice.call(arguments); |
| 1107: | var callback = args.pop(); |
| 1108: | var key = hasher.apply(null, args); |
| 1109: | if (key in memo) { |
| 1110: | callback.apply(null, memo[key]); |
| 1111: | } |
| 1112: | else { |
| 1113: | fn.apply(null, args.concat([function () { |
| 1114: | memo[key] = arguments; |
| 1115: | callback.apply(null, arguments); |
| 1116: | }])); |
| 1117: | } |
| 1118: | }; |
| 1119: | }; |
| 1120: | |
| 1121: | }()); |
| 1122: | (function(exports){ |
| 1123: | /** |
| 1124: | * This file is based on the node.js assert module, but with some small |
| 1125: | * changes for browser-compatibility |
| 1126: | * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! |
| 1127: | */ |
| 1128: | |
| 1129: | |
| 1130: | /** |
| 1131: | * Added for browser compatibility |
| 1132: | */ |
| 1133: | |
| 1134: | var _keys = function(obj){ |
| 1135: | if(Object.keys) return Object.keys(obj); |
| 1136: | if (typeof obj != 'object' && typeof obj != 'function') { |
| 1137: | throw new TypeError('-'); |
| 1138: | } |
| 1139: | var keys = []; |
| 1140: | for(var k in obj){ |
| 1141: | if(obj.hasOwnProperty(k)) keys.push(k); |
| 1142: | } |
| 1143: | return keys; |
| 1144: | }; |
| 1145: | |
| 1146: | |
| 1147: | |
| 1148: | // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 |
| 1149: | // |
| 1150: | // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! |
| 1151: | // |
| 1152: | // Originally from narwhal.js (http://narwhaljs.org) |
| 1153: | // Copyright (c) 2009 Thomas Robinson <280north.com> |
| 1154: | // |
| 1155: | // Permission is hereby granted, free of charge, to any person obtaining a copy |
| 1156: | // of this software and associated documentation files (the 'Software'), to |
| 1157: | // deal in the Software without restriction, including without limitation the |
| 1158: | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| 1159: | // sell copies of the Software, and to permit persons to whom the Software is |
| 1160: | // furnished to do so, subject to the following conditions: |
| 1161: | // |
| 1162: | // The above copyright notice and this permission notice shall be included in |
| 1163: | // all copies or substantial portions of the Software. |
| 1164: | // |
| 1165: | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 1166: | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 1167: | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 1168: | // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 1169: | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 1170: | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 1171: | |
| 1172: | |
| 1173: | var pSlice = Array.prototype.slice; |
| 1174: | |
| 1175: | // 1. The assert module provides functions that throw |
| 1176: | // AssertionError's when particular conditions are not met. The |
| 1177: | // assert module must conform to the following interface. |
| 1178: | |
| 1179: | var assert = exports; |
| 1180: | |
| 1181: | // 2. The AssertionError is defined in assert. |
| 1182: | // new assert.AssertionError({message: message, actual: actual, expected: expected}) |
| 1183: | |
| 1184: | assert.AssertionError = function AssertionError (options) { |
| 1185: | this.name = "AssertionError"; |
| 1186: | this.message = options.message; |
| 1187: | this.actual = options.actual; |
| 1188: | this.expected = options.expected; |
| 1189: | this.operator = options.operator; |
| 1190: | var stackStartFunction = options.stackStartFunction || fail; |
| 1191: | |
| 1192: | if (Error.captureStackTrace) { |
| 1193: | Error.captureStackTrace(this, stackStartFunction); |
| 1194: | } |
| 1195: | }; |
| 1196: | // code from util.inherits in node |
| 1197: | assert.AssertionError.super_ = Error; |
| 1198: | |
| 1199: | |
| 1200: | // EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call |
| 1201: | // TODO: test what effect this may have |
| 1202: | var ctor = function () { this.constructor = assert.AssertionError; }; |
| 1203: | ctor.prototype = Error.prototype; |
| 1204: | assert.AssertionError.prototype = new ctor(); |
| 1205: | |
| 1206: | |
| 1207: | assert.AssertionError.prototype.toString = function() { |
| 1208: | if (this.message) { |
| 1209: | return [this.name+":", this.message].join(' '); |
| 1210: | } else { |
| 1211: | return [ this.name+":" |
| 1212: | , JSON.stringify(this.expected ) |
| 1213: | , this.operator |
| 1214: | , JSON.stringify(this.actual) |
| 1215: | ].join(" "); |
| 1216: | } |
| 1217: | }; |
| 1218: | |
| 1219: | // assert.AssertionError instanceof Error |
| 1220: | |
| 1221: | assert.AssertionError.__proto__ = Error.prototype; |
| 1222: | |
| 1223: | // At present only the three keys mentioned above are used and |
| 1224: | // understood by the spec. Implementations or sub modules can pass |
| 1225: | // other keys to the AssertionError's constructor - they will be |
| 1226: | // ignored. |
| 1227: | |
| 1228: | // 3. All of the following functions must throw an AssertionError |
| 1229: | // when a corresponding condition is not met, with a message that |
| 1230: | // may be undefined if not provided. All assertion methods provide |
| 1231: | // both the actual and expected values to the assertion error for |
| 1232: | // display purposes. |
| 1233: | |
| 1234: | function fail(actual, expected, message, operator, stackStartFunction) { |
| 1235: | throw new assert.AssertionError({ |
| 1236: | message: message, |
| 1237: | actual: actual, |
| 1238: | expected: expected, |
| 1239: | operator: operator, |
| 1240: | stackStartFunction: stackStartFunction |
| 1241: | }); |
| 1242: | } |
| 1243: | |
| 1244: | // EXTENSION! allows for well behaved errors defined elsewhere. |
| 1245: | assert.fail = fail; |
| 1246: | |
| 1247: | // 4. Pure assertion tests whether a value is truthy, as determined |
| 1248: | // by !!guard. |
| 1249: | // assert.ok(guard, message_opt); |
| 1250: | // This statement is equivalent to assert.equal(true, guard, |
| 1251: | // message_opt);. To test strictly for the value true, use |
| 1252: | // assert.strictEqual(true, guard, message_opt);. |
| 1253: | |
| 1254: | assert.ok = function ok(value, message) { |
| 1255: | if (!!!value) fail(value, true, message, "==", assert.ok); |
| 1256: | }; |
| 1257: | |
| 1258: | // 5. The equality assertion tests shallow, coercive equality with |
| 1259: | // ==. |
| 1260: | // assert.equal(actual, expected, message_opt); |
| 1261: | |
| 1262: | assert.equal = function equal(actual, expected, message) { |
| 1263: | if (actual != expected) fail(actual, expected, message, "==", assert.equal); |
| 1264: | }; |
| 1265: | |
| 1266: | // 6. The non-equality assertion tests for whether two objects are not equal |
| 1267: | // with != assert.notEqual(actual, expected, message_opt); |
| 1268: | |
| 1269: | assert.notEqual = function notEqual(actual, expected, message) { |
| 1270: | if (actual == expected) { |
| 1271: | fail(actual, expected, message, "!=", assert.notEqual); |
| 1272: | } |
| 1273: | }; |
| 1274: | |
| 1275: | // 7. The equivalence assertion tests a deep equality relation. |
| 1276: | // assert.deepEqual(actual, expected, message_opt); |
| 1277: | |
| 1278: | assert.deepEqual = function deepEqual(actual, expected, message) { |
| 1279: | if (!_deepEqual(actual, expected)) { |
| 1280: | fail(actual, expected, message, "deepEqual", assert.deepEqual); |
| 1281: | } |
| 1282: | }; |
| 1283: | |
| 1284: | function _deepEqual(actual, expected) { |
| 1285: | // 7.1. All identical values are equivalent, as determined by ===. |
| 1286: | if (actual === expected) { |
| 1287: | return true; |
| 1288: | // 7.2. If the expected value is a Date object, the actual value is |
| 1289: | // equivalent if it is also a Date object that refers to the same time. |
| 1290: | } else if (actual instanceof Date && expected instanceof Date) { |
| 1291: | return actual.getTime() === expected.getTime(); |
| 1292: | |
| 1293: | // 7.3. Other pairs that do not both pass typeof value == "object", |
| 1294: | // equivalence is determined by ==. |
| 1295: | } else if (typeof actual != 'object' && typeof expected != 'object') { |
| 1296: | return actual == expected; |
| 1297: | |
| 1298: | // 7.4. For all other Object pairs, including Array objects, equivalence is |
| 1299: | // determined by having the same number of owned properties (as verified |
| 1300: | // with Object.prototype.hasOwnProperty.call), the same set of keys |
| 1301: | // (although not necessarily the same order), equivalent values for every |
| 1302: | // corresponding key, and an identical "prototype" property. Note: this |
| 1303: | // accounts for both named and indexed properties on Arrays. |
| 1304: | } else { |
| 1305: | return objEquiv(actual, expected); |
| 1306: | } |
| 1307: | } |
| 1308: | |
| 1309: | function isUndefinedOrNull (value) { |
| 1310: | return value === null || value === undefined; |
| 1311: | } |
| 1312: | |
| 1313: | function isArguments (object) { |
| 1314: | return Object.prototype.toString.call(object) == '[object Arguments]'; |
| 1315: | } |
| 1316: | |
| 1317: | function objEquiv (a, b) { |
| 1318: | if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) |
| 1319: | return false; |
| 1320: | // an identical "prototype" property. |
| 1321: | if (a.prototype !== b.prototype) return false; |
| 1322: | //~~~I've managed to break Object.keys through screwy arguments passing. |
| 1323: | // Converting to array solves the problem. |
| 1324: | if (isArguments(a)) { |
| 1325: | if (!isArguments(b)) { |
| 1326: | return false; |
| 1327: | } |
| 1328: | a = pSlice.call(a); |
| 1329: | b = pSlice.call(b); |
| 1330: | return _deepEqual(a, b); |
| 1331: | } |
| 1332: | try{ |
| 1333: | var ka = _keys(a), |
| 1334: | kb = _keys(b), |
| 1335: | key, i; |
| 1336: | } catch (e) {//happens when one is a string literal and the other isn't |
| 1337: | return false; |
| 1338: | } |
| 1339: | // having the same number of owned properties (keys incorporates hasOwnProperty) |
| 1340: | if (ka.length != kb.length) |
| 1341: | return false; |
| 1342: | //the same set of keys (although not necessarily the same order), |
| 1343: | ka.sort(); |
| 1344: | kb.sort(); |
| 1345: | //~~~cheap key test |
| 1346: | for (i = ka.length - 1; i >= 0; i--) { |
| 1347: | if (ka[i] != kb[i]) |
| 1348: | return false; |
| 1349: | } |
| 1350: | //equivalent values for every corresponding key, and |
| 1351: | //~~~possibly expensive deep test |
| 1352: | for (i = ka.length - 1; i >= 0; i--) { |
| 1353: | key = ka[i]; |
| 1354: | if (!_deepEqual(a[key], b[key] )) |
| 1355: | return false; |
| 1356: | } |
| 1357: | return true; |
| 1358: | } |
| 1359: | |
| 1360: | // 8. The non-equivalence assertion tests for any deep inequality. |
| 1361: | // assert.notDeepEqual(actual, expected, message_opt); |
| 1362: | |
| 1363: | assert.notDeepEqual = function notDeepEqual(actual, expected, message) { |
| 1364: | if (_deepEqual(actual, expected)) { |
| 1365: | fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual); |
| 1366: | } |
| 1367: | }; |
| 1368: | |
| 1369: | // 9. The strict equality assertion tests strict equality, as determined by ===. |
| 1370: | // assert.strictEqual(actual, expected, message_opt); |
| 1371: | |
| 1372: | assert.strictEqual = function strictEqual(actual, expected, message) { |
| 1373: | if (actual !== expected) { |
| 1374: | fail(actual, expected, message, "===", assert.strictEqual); |
| 1375: | } |
| 1376: | }; |
| 1377: | |
| 1378: | // 10. The strict non-equality assertion tests for strict inequality, as determined by !==. |
| 1379: | // assert.notStrictEqual(actual, expected, message_opt); |
| 1380: | |
| 1381: | assert.notStrictEqual = function notStrictEqual(actual, expected, message) { |
| 1382: | if (actual === expected) { |
| 1383: | fail(actual, expected, message, "!==", assert.notStrictEqual); |
| 1384: | } |
| 1385: | }; |
| 1386: | |
| 1387: | function _throws (shouldThrow, block, err, message) { |
| 1388: | var exception = null, |
| 1389: | threw = false, |
| 1390: | typematters = true; |
| 1391: | |
| 1392: | message = message || ""; |
| 1393: | |
| 1394: | //handle optional arguments |
| 1395: | if (arguments.length == 3) { |
| 1396: | if (typeof(err) == "string") { |
| 1397: | message = err; |
| 1398: | typematters = false; |
| 1399: | } |
| 1400: | } else if (arguments.length == 2) { |
| 1401: | typematters = false; |
| 1402: | } |
| 1403: | |
| 1404: | try { |
| 1405: | block(); |
| 1406: | } catch (e) { |
| 1407: | threw = true; |
| 1408: | exception = e; |
| 1409: | } |
| 1410: | |
| 1411: | if (shouldThrow && !threw) { |
| 1412: | fail( "Missing expected exception" |
| 1413: | + (err && err.name ? " ("+err.name+")." : '.') |
| 1414: | + (message ? " " + message : "") |
| 1415: | ); |
| 1416: | } |
| 1417: | if (!shouldThrow && threw && typematters && exception instanceof err) { |
| 1418: | fail( "Got unwanted exception" |
| 1419: | + (err && err.name ? " ("+err.name+")." : '.') |
| 1420: | + (message ? " " + message : "") |
| 1421: | ); |
| 1422: | } |
| 1423: | if ((shouldThrow && threw && typematters && !(exception instanceof err)) || |
| 1424: | (!shouldThrow && threw)) { |
| 1425: | throw exception; |
| 1426: | } |
| 1427: | }; |
| 1428: | |
| 1429: | // 11. Expected to throw an error: |
| 1430: | // assert.throws(block, Error_opt, message_opt); |
| 1431: | |
| 1432: | assert.throws = function(block, /*optional*/error, /*optional*/message) { |
| 1433: | _throws.apply(this, [true].concat(pSlice.call(arguments))); |
| 1434: | }; |
| 1435: | |
| 1436: | // EXTENSION! This is annoying to write outside this module. |
| 1437: | assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { |
| 1438: | _throws.apply(this, [false].concat(pSlice.call(arguments))); |
| 1439: | }; |
| 1440: | |
| 1441: | assert.ifError = function (err) { if (err) {throw err;}}; |
| 1442: | })(assert); |
| 1443: | (function(exports){ |
| 1444: | /*! |
| 1445: | * Nodeunit |
| 1446: | * Copyright (c) 2010 Caolan McMahon |
| 1447: | * MIT Licensed |
| 1448: | * |
| 1449: | * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! |
| 1450: | * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. |
| 1451: | * Only code on that line will be removed, its mostly to avoid requiring code |
| 1452: | * that is node specific |
| 1453: | */ |
| 1454: | |
| 1455: | /** |
| 1456: | * Module dependencies |
| 1457: | */ |
| 1458: | |
| 1459: | //var assert = require('./assert'), //@REMOVE_LINE_FOR_BROWSER |
| 1460: | // async = require('../deps/async'); //@REMOVE_LINE_FOR_BROWSER |
| 1461: | |
| 1462: | |
| 1463: | /** |
| 1464: | * Creates assertion objects representing the result of an assert call. |
| 1465: | * Accepts an object or AssertionError as its argument. |
| 1466: | * |
| 1467: | * @param {object} obj |
| 1468: | * @api public |
| 1469: | */ |
| 1470: | |
| 1471: | exports.assertion = function (obj) { |
| 1472: | return { |
| 1473: | method: obj.method || '', |
| 1474: | message: obj.message || (obj.error && obj.error.message) || '', |
| 1475: | error: obj.error, |
| 1476: | passed: function () { |
| 1477: | return !this.error; |
| 1478: | }, |
| 1479: | failed: function () { |
| 1480: | return Boolean(this.error); |
| 1481: | } |
| 1482: | }; |
| 1483: | }; |
| 1484: | |
| 1485: | /** |
| 1486: | * Creates an assertion list object representing a group of assertions. |
| 1487: | * Accepts an array of assertion objects. |
| 1488: | * |
| 1489: | * @param {Array} arr |
| 1490: | * @param {Number} duration |
| 1491: | * @api public |
| 1492: | */ |
| 1493: | |
| 1494: | exports.assertionList = function (arr, duration) { |
| 1495: | var that = arr || []; |
| 1496: | that.failures = function () { |
| 1497: | var failures = 0; |
| 1498: | for (var i = 0; i < this.length; i += 1) { |
| 1499: | if (this[i].failed()) { |
| 1500: | failures += 1; |
| 1501: | } |
| 1502: | } |
| 1503: | return failures; |
| 1504: | }; |
| 1505: | that.passes = function () { |
| 1506: | return that.length - that.failures(); |
| 1507: | }; |
| 1508: | that.duration = duration || 0; |
| 1509: | return that; |
| 1510: | }; |
| 1511: | |
| 1512: | /** |
| 1513: | * Create a wrapper function for assert module methods. Executes a callback |
| 1514: | * after the it's complete with an assertion object representing the result. |
| 1515: | * |
| 1516: | * @param {Function} callback |
| 1517: | * @api private |
| 1518: | */ |
| 1519: | |
| 1520: | var assertWrapper = function (callback) { |
| 1521: | return function (new_method, assert_method, arity) { |
| 1522: | return function () { |
| 1523: | var message = arguments[arity - 1]; |
| 1524: | var a = exports.assertion({method: new_method, message: message}); |
| 1525: | try { |
| 1526: | assert[assert_method].apply(null, arguments); |
| 1527: | } |
| 1528: | catch (e) { |
| 1529: | a.error = e; |
| 1530: | } |
| 1531: | callback(a); |
| 1532: | }; |
| 1533: | }; |
| 1534: | }; |
| 1535: | |
| 1536: | /** |
| 1537: | * Creates the 'test' object that gets passed to every test function. |
| 1538: | * Accepts the name of the test function as its first argument, followed by |
| 1539: | * the start time in ms, the options object and a callback function. |
| 1540: | * |
| 1541: | * @param {String} name |
| 1542: | * @param {Number} start |
| 1543: | * @param {Object} options |
| 1544: | * @param {Function} callback |
| 1545: | * @api public |
| 1546: | */ |
| 1547: | |
| 1548: | exports.test = function (name, start, options, callback) { |
| 1549: | var expecting; |
| 1550: | var a_list = []; |
| 1551: | |
| 1552: | var wrapAssert = assertWrapper(function (a) { |
| 1553: | a_list.push(a); |
| 1554: | if (options.log) { |
| 1555: | async.nextTick(function () { |
| 1556: | options.log(a); |
| 1557: | }); |
| 1558: | } |
| 1559: | }); |
| 1560: | |
| 1561: | var test = { |
| 1562: | done: function (err) { |
| 1563: | if (expecting !== undefined && expecting !== a_list.length) { |
| 1564: | var e = new Error( |
| 1565: | 'Expected ' + expecting + ' assertions, ' + |
| 1566: | a_list.length + ' ran' |
| 1567: | ); |
| 1568: | var a1 = exports.assertion({method: 'expect', error: e}); |
| 1569: | a_list.push(a1); |
| 1570: | if (options.log) { |
| 1571: | async.nextTick(function () { |
| 1572: | options.log(a1); |
| 1573: | }); |
| 1574: | } |
| 1575: | } |
| 1576: | if (err) { |
| 1577: | var a2 = exports.assertion({error: err}); |
| 1578: | a_list.push(a2); |
| 1579: | if (options.log) { |
| 1580: | async.nextTick(function () { |
| 1581: | options.log(a2); |
| 1582: | }); |
| 1583: | } |
| 1584: | } |
| 1585: | var end = new Date().getTime(); |
| 1586: | async.nextTick(function () { |
| 1587: | var assertion_list = exports.assertionList(a_list, end - start); |
| 1588: | options.testDone(name, assertion_list); |
| 1589: | callback(null, a_list); |
| 1590: | }); |
| 1591: | }, |
| 1592: | ok: wrapAssert('ok', 'ok', 2), |
| 1593: | same: wrapAssert('same', 'deepEqual', 3), |
| 1594: | equals: wrapAssert('equals', 'equal', 3), |
| 1595: | expect: function (num) { |
| 1596: | expecting = num; |
| 1597: | }, |
| 1598: | _assertion_list: a_list |
| 1599: | }; |
| 1600: | // add all functions from the assert module |
| 1601: | for (var k in assert) { |
| 1602: | if (assert.hasOwnProperty(k)) { |
| 1603: | test[k] = wrapAssert(k, k, assert[k].length); |
| 1604: | } |
| 1605: | } |
| 1606: | return test; |
| 1607: | }; |
| 1608: | |
| 1609: | /** |
| 1610: | * Ensures an options object has all callbacks, adding empty callback functions |
| 1611: | * if any are missing. |
| 1612: | * |
| 1613: | * @param {Object} opt |
| 1614: | * @return {Object} |
| 1615: | * @api public |
| 1616: | */ |
| 1617: | |
| 1618: | exports.options = function (opt) { |
| 1619: | var optionalCallback = function (name) { |
| 1620: | opt[name] = opt[name] || function () {}; |
| 1621: | }; |
| 1622: | |
| 1623: | optionalCallback('moduleStart'); |
| 1624: | optionalCallback('moduleDone'); |
| 1625: | optionalCallback('testStart'); |
| 1626: | optionalCallback('testDone'); |
| 1627: | //optionalCallback('log'); |
| 1628: | |
| 1629: | // 'done' callback is not optional. |
| 1630: | |
| 1631: | return opt; |
| 1632: | }; |
| 1633: | })(types); |
| 1634: | (function(exports){ |
| 1635: | /*! |
| 1636: | * Nodeunit |
| 1637: | * Copyright (c) 2010 Caolan McMahon |
| 1638: | * MIT Licensed |
| 1639: | * |
| 1640: | * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! |
| 1641: | * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. |
| 1642: | * Only code on that line will be removed, its mostly to avoid requiring code |
| 1643: | * that is node specific |
| 1644: | */ |
| 1645: | |
| 1646: | /** |
| 1647: | * Module dependencies |
| 1648: | */ |
| 1649: | |
| 1650: | //var async = require('../deps/async'), //@REMOVE_LINE_FOR_BROWSER |
| 1651: | // types = require('./types'); //@REMOVE_LINE_FOR_BROWSER |
| 1652: | |
| 1653: | |
| 1654: | /** |
| 1655: | * Added for browser compatibility |
| 1656: | */ |
| 1657: | |
| 1658: | var _keys = function (obj) { |
| 1659: | if (Object.keys) { |
| 1660: | return Object.keys(obj); |
| 1661: | } |
| 1662: | var keys = []; |
| 1663: | for (var k in obj) { |
| 1664: | if (obj.hasOwnProperty(k)) { |
| 1665: | keys.push(k); |
| 1666: | } |
| 1667: | } |
| 1668: | return keys; |
| 1669: | }; |
| 1670: | |
| 1671: | |
| 1672: | var _copy = function (obj) { |
| 1673: | var nobj = {}; |
| 1674: | var keys = _keys(obj); |
| 1675: | for (var i = 0; i < keys.length; i += 1) { |
| 1676: | nobj[keys[i]] = obj[keys[i]]; |
| 1677: | } |
| 1678: | return nobj; |
| 1679: | }; |
| 1680: | |
| 1681: | |
| 1682: | /** |
| 1683: | * Runs a test function (fn) from a loaded module. After the test function |
| 1684: | * calls test.done(), the callback is executed with an assertionList as its |
| 1685: | * second argument. |
| 1686: | * |
| 1687: | * @param {String} name |
| 1688: | * @param {Function} fn |
| 1689: | * @param {Object} opt |
| 1690: | * @param {Function} callback |
| 1691: | * @api public |
| 1692: | */ |
| 1693: | |
| 1694: | exports.runTest = function (name, fn, opt, callback) { |
| 1695: | var options = types.options(opt); |
| 1696: | |
| 1697: | options.testStart(name); |
| 1698: | var start = new Date().getTime(); |
| 1699: | var test = types.test(name, start, options, callback); |
| 1700: | |
| 1701: | try { |
| 1702: | fn(test); |
| 1703: | } |
| 1704: | catch (e) { |
| 1705: | test.done(e); |
| 1706: | } |
| 1707: | }; |
| 1708: | |
| 1709: | /** |
| 1710: | * Takes an object containing test functions or other test suites as properties |
| 1711: | * and runs each in series. After all tests have completed, the callback is |
| 1712: | * called with a list of all assertions as the second argument. |
| 1713: | * |
| 1714: | * If a name is passed to this function it is prepended to all test and suite |
| 1715: | * names that run within it. |
| 1716: | * |
| 1717: | * @param {String} name |
| 1718: | * @param {Object} suite |
| 1719: | * @param {Object} opt |
| 1720: | * @param {Function} callback |
| 1721: | * @api public |
| 1722: | */ |
| 1723: | |
| 1724: | exports.runSuite = function (name, suite, opt, callback) { |
| 1725: | var keys = _keys(suite); |
| 1726: | |
| 1727: | async.concatSeries(keys, function (k, cb) { |
| 1728: | var prop = suite[k], _name; |
| 1729: | |
| 1730: | _name = name ? [].concat(name, k) : [k]; |
| 1731: | |
| 1732: | _name.toString = function () { |
| 1733: | // fallback for old one |
| 1734: | return this.join(' - '); |
| 1735: | }; |
| 1736: | |
| 1737: | if (typeof prop === 'function') { |
| 1738: | var in_name = false; |
| 1739: | for (var i = 0; i < _name.length; i += 1) { |
| 1740: | if (_name[i] === opt.testspec) { |
| 1741: | in_name = true; |
| 1742: | } |
| 1743: | } |
| 1744: | if (!opt.testspec || in_name) { |
| 1745: | if (opt.moduleStart) { |
| 1746: | opt.moduleStart(); |
| 1747: | } |
| 1748: | exports.runTest(_name, suite[k], opt, cb); |
| 1749: | } |
| 1750: | else { |
| 1751: | return cb(); |
| 1752: | } |
| 1753: | } |
| 1754: | else { |
| 1755: | exports.runSuite(_name, suite[k], opt, cb); |
| 1756: | } |
| 1757: | }, callback); |
| 1758: | }; |
| 1759: | |
| 1760: | /** |
| 1761: | * Run each exported test function or test suite from a loaded module. |
| 1762: | * |
| 1763: | * @param {String} name |
| 1764: | * @param {Object} mod |
| 1765: | * @param {Object} opt |
| 1766: | * @param {Function} callback |
| 1767: | * @api public |
| 1768: | */ |
| 1769: | |
| 1770: | exports.runModule = function (name, mod, opt, callback) { |
| 1771: | var options = _copy(types.options(opt)); |
| 1772: | |
| 1773: | var _run = false; |
| 1774: | var _moduleStart = options.moduleStart; |
| 1775: | function run_once() { |
| 1776: | if (!_run) { |
| 1777: | _run = true; |
| 1778: | _moduleStart(name); |
| 1779: | } |
| 1780: | } |
| 1781: | options.moduleStart = run_once; |
| 1782: | |
| 1783: | var start = new Date().getTime(); |
| 1784: | |
| 1785: | exports.runSuite(null, mod, options, function (err, a_list) { |
| 1786: | var end = new Date().getTime(); |
| 1787: | var assertion_list = types.assertionList(a_list, end - start); |
| 1788: | options.moduleDone(name, assertion_list); |
| 1789: | callback(null, a_list); |
| 1790: | }); |
| 1791: | }; |
| 1792: | |
| 1793: | /** |
| 1794: | * Treats an object literal as a list of modules keyed by name. Runs each |
| 1795: | * module and finished with calling 'done'. You can think of this as a browser |
| 1796: | * safe alternative to runFiles in the nodeunit module. |
| 1797: | * |
| 1798: | * @param {Object} modules |
| 1799: | * @param {Object} opt |
| 1800: | * @api public |
| 1801: | */ |
| 1802: | |
| 1803: | // TODO: add proper unit tests for this function |
| 1804: | exports.runModules = function (modules, opt) { |
| 1805: | var all_assertions = []; |
| 1806: | var options = types.options(opt); |
| 1807: | var start = new Date().getTime(); |
| 1808: | |
| 1809: | async.concatSeries(_keys(modules), function (k, cb) { |
| 1810: | exports.runModule(k, modules[k], options, cb); |
| 1811: | }, |
| 1812: | function (err, all_assertions) { |
| 1813: | var end = new Date().getTime(); |
| 1814: | options.done(types.assertionList(all_assertions, end - start)); |
| 1815: | }); |
| 1816: | }; |
| 1817: | |
| 1818: | |
| 1819: | /** |
| 1820: | * Wraps a test function with setUp and tearDown functions. |
| 1821: | * Used by testCase. |
| 1822: | * |
| 1823: | * @param {Function} setUp |
| 1824: | * @param {Function} tearDown |
| 1825: | * @param {Function} fn |
| 1826: | * @api private |
| 1827: | */ |
| 1828: | |
| 1829: | var wrapTest = function (setUp, tearDown, fn) { |
| 1830: | return function (test) { |
| 1831: | var context = {}; |
| 1832: | if (tearDown) { |
| 1833: | var done = test.done; |
| 1834: | test.done = function (err) { |
| 1835: | try { |
| 1836: | tearDown.call(context, function (err2) { |
| 1837: | if (err && err2) { |
| 1838: | test._assertion_list.push( |
| 1839: | types.assertion({error: err}) |
| 1840: | ); |
| 1841: | return done(err2); |
| 1842: | } |
| 1843: | done(err || err2); |
| 1844: | }); |
| 1845: | } |
| 1846: | catch (e) { |
| 1847: | done(e); |
| 1848: | } |
| 1849: | }; |
| 1850: | } |
| 1851: | if (setUp) { |
| 1852: | setUp.call(context, function (err) { |
| 1853: | if (err) { |
| 1854: | return test.done(err); |
| 1855: | } |
| 1856: | fn.call(context, test); |
| 1857: | }); |
| 1858: | } |
| 1859: | else { |
| 1860: | fn.call(context, test); |
| 1861: | } |
| 1862: | }; |
| 1863: | }; |
| 1864: | |
| 1865: | |
| 1866: | /** |
| 1867: | * Wraps a group of tests with setUp and tearDown functions. |
| 1868: | * Used by testCase. |
| 1869: | * |
| 1870: | * @param {Function} setUp |
| 1871: | * @param {Function} tearDown |
| 1872: | * @param {Object} group |
| 1873: | * @api private |
| 1874: | */ |
| 1875: | |
| 1876: | var wrapGroup = function (setUp, tearDown, group) { |
| 1877: | var tests = {}; |
| 1878: | var keys = _keys(group); |
| 1879: | for (var i = 0; i < keys.length; i += 1) { |
| 1880: | var k = keys[i]; |
| 1881: | if (typeof group[k] === 'function') { |
| 1882: | tests[k] = wrapTest(setUp, tearDown, group[k]); |
| 1883: | } |
| 1884: | else if (typeof group[k] === 'object') { |
| 1885: | tests[k] = wrapGroup(setUp, tearDown, group[k]); |
| 1886: | } |
| 1887: | } |
| 1888: | return tests; |
| 1889: | }; |
| 1890: | |
| 1891: | |
| 1892: | /** |
| 1893: | * Utility for wrapping a suite of test functions with setUp and tearDown |
| 1894: | * functions. |
| 1895: | * |
| 1896: | * @param {Object} suite |
| 1897: | * @return {Object} |
| 1898: | * @api public |
| 1899: | */ |
| 1900: | |
| 1901: | exports.testCase = function (suite) { |
| 1902: | var setUp = suite.setUp; |
| 1903: | var tearDown = suite.tearDown; |
| 1904: | delete suite.setUp; |
| 1905: | delete suite.tearDown; |
| 1906: | return wrapGroup(setUp, tearDown, suite); |
| 1907: | }; |
| 1908: | })(core); |
| 1909: | (function(exports){ |
| 1910: | /*! |
| 1911: | * Nodeunit |
| 1912: | * Copyright (c) 2010 Caolan McMahon |
| 1913: | * MIT Licensed |
| 1914: | * |
| 1915: | * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! |
| 1916: | * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. |
| 1917: | * Only code on that line will be removed, its mostly to avoid requiring code |
| 1918: | * that is node specific |
| 1919: | */ |
| 1920: | |
| 1921: | |
| 1922: | /** |
| 1923: | * NOTE: this test runner is not listed in index.js because it cannot be |
| 1924: | * used with the command-line tool, only inside the browser. |
| 1925: | */ |
| 1926: | |
| 1927: | |
| 1928: | /** |
| 1929: | * Reporter info string |
| 1930: | */ |
| 1931: | |
| 1932: | exports.info = "Browser-based test reporter"; |
| 1933: | |
| 1934: | |
| 1935: | /** |
| 1936: | * Run all tests within each module, reporting the results |
| 1937: | * |
| 1938: | * @param {Array} files |
| 1939: | * @api public |
| 1940: | */ |
| 1941: | |
| 1942: | exports.run = function (modules, options) { |
| 1943: | var start = new Date().getTime(); |
| 1944: | |
| 1945: | function setText(el, txt) { |
| 1946: | if ('innerText' in el) { |
| 1947: | el.innerText = txt; |
| 1948: | } |
| 1949: | else if ('textContent' in el){ |
| 1950: | el.textContent = txt; |
| 1951: | } |
| 1952: | } |
| 1953: | |
| 1954: | function getOrCreate(tag, id) { |
| 1955: | var el = document.getElementById(id); |
| 1956: | if (!el) { |
| 1957: | el = document.createElement(tag); |
| 1958: | el.id = id; |
| 1959: | document.body.appendChild(el); |
| 1960: | } |
| 1961: | return el; |
| 1962: | }; |
| 1963: | |
| 1964: | var header = getOrCreate('h1', 'nodeunit-header'); |
| 1965: | var banner = getOrCreate('h2', 'nodeunit-banner'); |
| 1966: | var userAgent = getOrCreate('h2', 'nodeunit-userAgent'); |
| 1967: | var tests = getOrCreate('ol', 'nodeunit-tests'); |
| 1968: | var result = getOrCreate('p', 'nodeunit-testresult'); |
| 1969: | |
| 1970: | setText(userAgent, navigator.userAgent); |
| 1971: | |
| 1972: | nodeunit.runModules(modules, { |
| 1973: | moduleStart: function (name) { |
| 1974: | /*var mheading = document.createElement('h2'); |
| 1975: | mheading.innerText = name; |
| 1976: | results.appendChild(mheading); |
| 1977: | module = document.createElement('ol'); |
| 1978: | results.appendChild(module);*/ |
| 1979: | }, |
| 1980: | testDone: function (name, assertions) { |
| 1981: | var test = document.createElement('li'); |
| 1982: | var strong = document.createElement('strong'); |
| 1983: | strong.innerHTML = name + ' <b style="color: black;">(' + |
| 1984: | '<b class="fail">' + assertions.failures() + '</b>, ' + |
| 1985: | '<b class="pass">' + assertions.passes() + '</b>, ' + |
| 1986: | assertions.length + |
| 1987: | ')</b>'; |
| 1988: | test.className = assertions.failures() ? 'fail': 'pass'; |
| 1989: | test.appendChild(strong); |
| 1990: | |
| 1991: | var aList = document.createElement('ol'); |
| 1992: | aList.style.display = 'none'; |
| 1993: | test.onclick = function () { |
| 1994: | var d = aList.style.display; |
| 1995: | aList.style.display = (d == 'none') ? 'block': 'none'; |
| 1996: | }; |
| 1997: | for (var i=0; i<assertions.length; i++) { |
| 1998: | var li = document.createElement('li'); |
| 1999: | var a = assertions[i]; |
| 2000: | if (a.failed()) { |
| 2001: | li.innerHTML = (a.message || a.method || 'no message') + |
| 2002: | '<pre>' + (a.error.stack || a.error) + '</pre>'; |
| 2003: | li.className = 'fail'; |
| 2004: | } |
| 2005: | else { |
| 2006: | li.innerHTML = a.message || a.method || 'no message'; |
| 2007: | li.className = 'pass'; |
| 2008: | } |
| 2009: | aList.appendChild(li); |
| 2010: | } |
| 2011: | test.appendChild(aList); |
| 2012: | tests.appendChild(test); |
| 2013: | }, |
| 2014: | done: function (assertions) { |
| 2015: | var end = new Date().getTime(); |
| 2016: | var duration = end - start; |
| 2017: | |
| 2018: | var failures = assertions.failures(); |
| 2019: | banner.className = failures ? 'fail': 'pass'; |
| 2020: | |
| 2021: | result.innerHTML = 'Tests completed in ' + duration + |
| 2022: | ' milliseconds.<br/><span class="passed">' + |
| 2023: | assertions.passes() + '</span> assertions of ' + |
| 2024: | '<span class="all">' + assertions.length + '<span> passed, ' + |
| 2025: | assertions.failures() + ' failed.'; |
| 2026: | } |
| 2027: | }); |
| 2028: | }; |
| 2029: | })(reporter); |
| 2030: | nodeunit = core; |
| 2031: | nodeunit.assert = assert; |
| 2032: | nodeunit.reporter = reporter; |
| 2033: | nodeunit.run = reporter.run; |
| 2034: | return nodeunit; })(); |
