diff options
Diffstat (limited to 'deps/nodeunit.js')
-rw-r--r-- | deps/nodeunit.js | 305 |
1 files changed, 228 insertions, 77 deletions
diff --git a/deps/nodeunit.js b/deps/nodeunit.js index 5957184..6251ba1 100644 --- a/deps/nodeunit.js +++ b/deps/nodeunit.js @@ -171,9 +171,7 @@ nodeunit = (function(){ // Create a JSON object only if one does not already exist. We create the // methods in a closure to avoid creating global variables. -if (!this.JSON) { - this.JSON = {}; -} +var JSON = {}; (function () { "use strict"; @@ -579,14 +577,19 @@ var reporter = {}; //// exported async module functions //// //// nextTick implementation with browser-compatible fallback //// - async.nextTick = function (fn) { - if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + setImmediate(fn); + }; + } + else if (typeof process !== 'undefined' && process.nextTick) { + async.nextTick = process.nextTick; + } + else { + async.nextTick = function (fn) { setTimeout(fn, 0); - } - else { - process.nextTick(fn); - } - }; + }; + } async.forEach = function (arr, iterator, callback) { if (!arr.length) { @@ -1099,6 +1102,27 @@ var reporter = {}; async.warn = _console_fn('warn'); async.error = _console_fn('error');*/ + async.memoize = function (fn, hasher) { + var memo = {}; + hasher = hasher || function (x) { + return x; + }; + return function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else { + fn.apply(null, args.concat([function () { + memo[key] = arguments; + callback.apply(null, arguments); + }])); + } + }; + }; + }()); (function(exports){ /** @@ -1114,6 +1138,9 @@ var reporter = {}; var _keys = function(obj){ if(Object.keys) return Object.keys(obj); + if (typeof obj != 'object' && typeof obj != 'function') { + throw new TypeError('-'); + } var keys = []; for(var k in obj){ if(obj.hasOwnProperty(k)) keys.push(k); @@ -1187,9 +1214,9 @@ assert.AssertionError.prototype.toString = function() { return [this.name+":", this.message].join(' '); } else { return [ this.name+":" - , JSON.stringify(this.expected ) + , typeof this.expected !== 'undefined' ? JSON.stringify(this.expected) : 'undefined' , this.operator - , JSON.stringify(this.actual) + , typeof this.actual !== 'undefined' ? JSON.stringify(this.actual) : 'undefined' ].join(" "); } }; @@ -1259,6 +1286,17 @@ assert.deepEqual = function deepEqual(actual, expected, message) { } }; +var Buffer = null; +if (typeof require !== 'undefined' && typeof process !== 'undefined') { + try { + Buffer = require('buffer').Buffer; + } + catch (e) { + // May be a CommonJS environment other than Node.js + Buffer = null; + } +} + function _deepEqual(actual, expected) { // 7.1. All identical values are equivalent, as determined by ===. if (actual === expected) { @@ -1268,6 +1306,25 @@ function _deepEqual(actual, expected) { } else if (actual instanceof Date && expected instanceof Date) { return actual.getTime() === expected.getTime(); + // 7.2.1 If the expcted value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object that refers to the same source and options + } else if (actual instanceof RegExp && expected instanceof RegExp) { + return actual.source === expected.source && + actual.global === expected.global && + actual.ignoreCase === expected.ignoreCase && + actual.multiline === expected.multiline; + + } else if (Buffer && actual instanceof Buffer && expected instanceof Buffer) { + return (function() { + var i, len; + + for (i = 0, len = expected.length; i < len; i++) { + if (actual[i] !== expected[i]) { + return false; + } + } + return actual.length === expected.length; + })(); // 7.3. Other pairs that do not both pass typeof value == "object", // equivalence is determined by ==. } else if (typeof actual != 'object' && typeof expected != 'object') { @@ -1362,47 +1419,52 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) { } }; -function _throws (shouldThrow, block, err, message) { - var exception = null, - threw = false, - typematters = true; +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } - message = message || ""; + if (expected instanceof RegExp) { + return expected.test(actual.message || actual); + } else if (actual instanceof expected) { + return true; + } else if (expected.call({}, actual) === true) { + return true; + } - //handle optional arguments - if (arguments.length == 3) { - if (typeof(err) == "string") { - message = err; - typematters = false; - } - } else if (arguments.length == 2) { - typematters = false; + return false; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (typeof expected === 'string') { + message = expected; + expected = null; } try { block(); } catch (e) { - threw = true; - exception = e; + actual = e; } - if (shouldThrow && !threw) { - fail( "Missing expected exception" - + (err && err.name ? " ("+err.name+")." : '.') - + (message ? " " + message : "") - ); + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail('Missing expected exception' + message); } - if (!shouldThrow && threw && typematters && exception instanceof err) { - fail( "Got unwanted exception" - + (err && err.name ? " ("+err.name+")." : '.') - + (message ? " " + message : "") - ); + + if (!shouldThrow && expectedException(actual, expected)) { + fail('Got unwanted exception' + message); } - if ((shouldThrow && threw && typematters && !(exception instanceof err)) || - (!shouldThrow && threw)) { - throw exception; + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; } -}; +} // 11. Expected to throw an error: // assert.throws(block, Error_opt, message_opt); @@ -1425,7 +1487,7 @@ assert.ifError = function (err) { if (err) {throw err;}}; * MIT Licensed * * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! - * Only code on that line will be removed, its mostly to avoid requiring code + * Only code on that line will be removed, it's mostly to avoid requiring code * that is node specific */ @@ -1470,8 +1532,10 @@ exports.assertionList = function (arr, duration) { var that = arr || []; that.failures = function () { var failures = 0; - for (var i=0; i<this.length; i++) { - if (this[i].failed()) failures++; + for (var i = 0; i < this.length; i += 1) { + if (this[i].failed()) { + failures += 1; + } } return failures; }; @@ -1484,7 +1548,7 @@ exports.assertionList = function (arr, duration) { /** * Create a wrapper function for assert module methods. Executes a callback - * after the it's complete with an assertion object representing the result. + * after it's complete with an assertion object representing the result. * * @param {Function} callback * @api private @@ -1493,7 +1557,7 @@ exports.assertionList = function (arr, duration) { var assertWrapper = function (callback) { return function (new_method, assert_method, arity) { return function () { - var message = arguments[arity-1]; + var message = arguments[arity - 1]; var a = exports.assertion({method: new_method, message: message}); try { assert[assert_method].apply(null, arguments); @@ -1596,6 +1660,7 @@ exports.options = function (opt) { optionalCallback('moduleStart'); optionalCallback('moduleDone'); optionalCallback('testStart'); + optionalCallback('testReady'); optionalCallback('testDone'); //optionalCallback('log'); @@ -1611,7 +1676,7 @@ exports.options = function (opt) { * MIT Licensed * * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! - * Only code on that line will be removed, its mostly to avoid requiring code + * Only code on that line will be removed, it's mostly to avoid requiring code * that is node specific */ @@ -1625,16 +1690,30 @@ exports.options = function (opt) { * Added for browser compatibility */ -var _keys = function(obj){ - if(Object.keys) return Object.keys(obj); +var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } var keys = []; - for(var k in obj){ - if(obj.hasOwnProperty(k)) keys.push(k); + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } } return keys; }; +var _copy = function (obj) { + var nobj = {}; + var keys = _keys(obj); + for (var i = 0; i < keys.length; i += 1) { + nobj[keys[i]] = obj[keys[i]]; + } + return nobj; +}; + + /** * Runs a test function (fn) from a loaded module. After the test function * calls test.done(), the callback is executed with an assertionList as its @@ -1654,6 +1733,7 @@ exports.runTest = function (name, fn, opt, callback) { var start = new Date().getTime(); var test = types.test(name, start, options, callback); + options.testReady(test); try { fn(test); } @@ -1678,20 +1758,36 @@ exports.runTest = function (name, fn, opt, callback) { */ exports.runSuite = function (name, suite, opt, callback) { + suite = wrapGroup(suite); var keys = _keys(suite); async.concatSeries(keys, function (k, cb) { var prop = suite[k], _name; _name = name ? [].concat(name, k) : [k]; - _name.toString = function () { // fallback for old one return this.join(' - '); }; if (typeof prop === 'function') { - exports.runTest(_name, suite[k], opt, cb); + var in_name = false, + in_specific_test = (_name.toString() === opt.testFullSpec) ? true : false; + for (var i = 0; i < _name.length; i += 1) { + if (_name[i] === opt.testspec) { + in_name = true; + } + } + + if ((!opt.testFullSpec || in_specific_test) && (!opt.testspec || in_name)) { + if (opt.moduleStart) { + opt.moduleStart(); + } + exports.runTest(_name, suite[k], opt, cb); + } + else { + return cb(); + } } else { exports.runSuite(_name, suite[k], opt, cb); @@ -1710,15 +1806,30 @@ exports.runSuite = function (name, suite, opt, callback) { */ exports.runModule = function (name, mod, opt, callback) { - var options = types.options(opt); + var options = _copy(types.options(opt)); + + var _run = false; + var _moduleStart = options.moduleStart; + + mod = wrapGroup(mod); + + function run_once() { + if (!_run) { + _run = true; + _moduleStart(name); + } + } + options.moduleStart = run_once; - options.moduleStart(name); var start = new Date().getTime(); - exports.runSuite(null, mod, opt, function (err, a_list) { + exports.runSuite(null, mod, options, function (err, a_list) { var end = new Date().getTime(); var assertion_list = types.assertionList(a_list, end - start); options.moduleDone(name, assertion_list); + if (nodeunit.complete) { + nodeunit.complete(name, assertion_list); + } callback(null, a_list); }); }; @@ -1792,7 +1903,34 @@ var wrapTest = function (setUp, tearDown, fn) { else { fn.call(context, test); } + }; +}; + + +/** + * Returns a serial callback from two functions. + * + * @param {Function} funcFirst + * @param {Function} funcSecond + * @api private + */ + +var getSerialCallback = function (fns) { + if (!fns.length) { + return null; } + return function (callback) { + var that = this; + var bound_fns = []; + for (var i = 0, len = fns.length; i < len; i++) { + (function (j) { + bound_fns.push(function () { + return fns[j].apply(that, arguments); + }); + })(i); + } + return async.series(bound_fns, callback); + }; }; @@ -1800,43 +1938,52 @@ var wrapTest = function (setUp, tearDown, fn) { * Wraps a group of tests with setUp and tearDown functions. * Used by testCase. * - * @param {Function} setUp - * @param {Function} tearDown * @param {Object} group + * @param {Array} setUps - parent setUp functions + * @param {Array} tearDowns - parent tearDown functions * @api private */ -var wrapGroup = function (setUp, tearDown, group) { +var wrapGroup = function (group, setUps, tearDowns) { var tests = {}; + + var setUps = setUps ? setUps.slice(): []; + var tearDowns = tearDowns ? tearDowns.slice(): []; + + if (group.setUp) { + setUps.push(group.setUp); + delete group.setUp; + } + if (group.tearDown) { + tearDowns.unshift(group.tearDown); + delete group.tearDown; + } + var keys = _keys(group); - for (var i=0; i<keys.length; i++) { + + for (var i = 0; i < keys.length; i += 1) { var k = keys[i]; if (typeof group[k] === 'function') { - tests[k] = wrapTest(setUp, tearDown, group[k]); + tests[k] = wrapTest( + getSerialCallback(setUps), + getSerialCallback(tearDowns), + group[k] + ); } else if (typeof group[k] === 'object') { - tests[k] = wrapGroup(setUp, tearDown, group[k]); + tests[k] = wrapGroup(group[k], setUps, tearDowns); } } return tests; -} +}; /** - * Utility for wrapping a suite of test functions with setUp and tearDown - * functions. - * - * @param {Object} suite - * @return {Object} - * @api public + * Backwards compatibility for test suites using old testCase API */ exports.testCase = function (suite) { - var setUp = suite.setUp; - var tearDown = suite.tearDown; - delete suite.setUp; - delete suite.tearDown; - return wrapGroup(setUp, tearDown, suite); + return suite; }; })(core); (function(exports){ @@ -1871,8 +2018,10 @@ exports.info = "Browser-based test reporter"; * @api public */ -exports.run = function (modules, options) { - var start = new Date().getTime(); +exports.run = function (modules, options, callback) { + var start = new Date().getTime(), div; + options = options || {}; + div = options.div || document.body; function setText(el, txt) { if ('innerText' in el) { @@ -1888,7 +2037,7 @@ exports.run = function (modules, options) { if (!el) { el = document.createElement(tag); el.id = id; - document.body.appendChild(el); + div.appendChild(el); } return el; }; @@ -1955,6 +2104,8 @@ exports.run = function (modules, options) { assertions.passes() + '</span> assertions of ' + '<span class="all">' + assertions.length + '<span> passed, ' + assertions.failures() + ' failed.'; + + if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined); } }); }; |