|
|
@ -36,32 +36,38 @@ var assert = exports; |
|
|
|
// new assert.AssertionError({message: message, actual: actual, expected: expected})
|
|
|
|
|
|
|
|
assert.AssertionError = function AssertionError(options) { |
|
|
|
this.name = "AssertionError"; |
|
|
|
this.message = options.message; |
|
|
|
this.actual = options.actual; |
|
|
|
this.expected = options.expected; |
|
|
|
this.operator = options.operator; |
|
|
|
//v8 specific
|
|
|
|
if(Error.captureStackTrace){ |
|
|
|
Error.captureStackTrace(this,fail); |
|
|
|
//node specific, removes the node machinery stack frames
|
|
|
|
if(typeof(__filename) !== undefined){ |
|
|
|
var stack = this.stack.split('\n'); |
|
|
|
for (var i = stack.length - 1; i >= 0; i--) { |
|
|
|
if(stack[i].indexOf(__filename) != -1){ |
|
|
|
this.stack = stack.slice(0,i+2).join('\n'); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
this.name = "AssertionError"; |
|
|
|
this.message = options.message; |
|
|
|
this.actual = options.actual; |
|
|
|
this.expected = options.expected; |
|
|
|
this.operator = options.operator; |
|
|
|
|
|
|
|
//v8 specific
|
|
|
|
if (Error.captureStackTrace) { |
|
|
|
Error.captureStackTrace(this, fail); |
|
|
|
//node specific, removes the node machinery stack frames
|
|
|
|
if (typeof(__filename) !== undefined) { |
|
|
|
var stack = this.stack.split('\n'); |
|
|
|
for (var i = stack.length - 1; i >= 0; i--) { |
|
|
|
if (stack[i].indexOf(__filename) != -1) { |
|
|
|
this.stack = stack.slice(0, i+2).join('\n'); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
assert.AssertionError.prototype.toString = function(){ |
|
|
|
if(this.message) |
|
|
|
return [this.name+":", this.message].join(' '); |
|
|
|
else |
|
|
|
return [this.name+":", JSON.stringify(this.expected ), this.operator , JSON.stringify(this.actual)].join(" "); |
|
|
|
assert.AssertionError.prototype.toString = function() { |
|
|
|
if (this.message) { |
|
|
|
return [this.name+":", this.message].join(' '); |
|
|
|
} else { |
|
|
|
return [ this.name+":" |
|
|
|
, JSON.stringify(this.expected ) |
|
|
|
, this.operator |
|
|
|
, JSON.stringify(this.actual) |
|
|
|
].join(" "); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// assert.AssertionError instanceof Error
|
|
|
@ -80,12 +86,12 @@ assert.AssertionError.__proto__ = Error.prototype; |
|
|
|
// display purposes.
|
|
|
|
|
|
|
|
function fail(actual, expected, message, operator) { |
|
|
|
throw new assert.AssertionError({ |
|
|
|
message: message, |
|
|
|
actual: actual, |
|
|
|
expected: expected, |
|
|
|
operator: operator |
|
|
|
}); |
|
|
|
throw new assert.AssertionError({ |
|
|
|
message: message, |
|
|
|
actual: actual, |
|
|
|
expected: expected, |
|
|
|
operator: operator |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// EXTENSION! allows for well behaved errors defined elsewhere.
|
|
|
@ -99,8 +105,7 @@ assert.fail = fail; |
|
|
|
// assert.strictEqual(true, guard, message_opt);.
|
|
|
|
|
|
|
|
assert.ok = function ok(value, message) { |
|
|
|
if (!!!value) |
|
|
|
fail(value, true, message, "=="); |
|
|
|
if (!!!value) fail(value, true, message, "=="); |
|
|
|
}; |
|
|
|
|
|
|
|
// 5. The equality assertion tests shallow, coercive equality with
|
|
|
@ -108,179 +113,175 @@ assert.ok = function ok(value, message) { |
|
|
|
// assert.equal(actual, expected, message_opt);
|
|
|
|
|
|
|
|
assert.equal = function equal(actual, expected, message) { |
|
|
|
if (actual != expected) |
|
|
|
fail(actual, expected, message, "=="); |
|
|
|
if (actual != expected) fail(actual, expected, message, "=="); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 6. The non-equality assertion tests for whether two objects are not equal
|
|
|
|
// with != assert.notEqual(actual, expected, message_opt);
|
|
|
|
|
|
|
|
assert.notEqual = function notEqual(actual, expected, message) { |
|
|
|
if (actual == expected) |
|
|
|
fail(actual, expected, message, "!="); |
|
|
|
if (actual == expected) fail(actual, expected, message, "!="); |
|
|
|
}; |
|
|
|
|
|
|
|
// 7. The equivalence assertion tests a deep equality relation.
|
|
|
|
// assert.deepEqual(actual, expected, message_opt);
|
|
|
|
|
|
|
|
exports.deepEqual = function deepEqual(actual, expected, message) { |
|
|
|
if (!_deepEqual(actual, expected)) |
|
|
|
fail(actual, expected, message, "deepEqual"); |
|
|
|
if (!_deepEqual(actual, expected)) { |
|
|
|
fail(actual, expected, message, "deepEqual"); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
function _deepEqual(actual, expected) { |
|
|
|
// 7.1. All identical values are equivalent, as determined by ===.
|
|
|
|
if (actual === expected) { |
|
|
|
return true; |
|
|
|
|
|
|
|
// 7.2. If the expected value is a Date object, the actual value is
|
|
|
|
// equivalent if it is also a Date object that refers to the same time.
|
|
|
|
} else if (actual instanceof Date |
|
|
|
&& expected instanceof Date) { |
|
|
|
return actual.getTime() === expected.getTime(); |
|
|
|
|
|
|
|
// 7.3. Other pairs that do not both pass typeof value == "object",
|
|
|
|
// equivalence is determined by ==.
|
|
|
|
} else if (typeof actual != 'object' |
|
|
|
&& typeof expected != 'object') { |
|
|
|
return actual == expected; |
|
|
|
|
|
|
|
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
|
|
|
// determined by having the same number of owned properties (as verified
|
|
|
|
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
|
|
// (although not necessarily the same order), equivalent values for every
|
|
|
|
// corresponding key, and an identical "prototype" property. Note: this
|
|
|
|
// accounts for both named and indexed properties on Arrays.
|
|
|
|
} else { |
|
|
|
return objEquiv(actual, expected); |
|
|
|
} |
|
|
|
// 7.1. All identical values are equivalent, as determined by ===.
|
|
|
|
if (actual === expected) { |
|
|
|
return true; |
|
|
|
|
|
|
|
// 7.2. If the expected value is a Date object, the actual value is
|
|
|
|
// equivalent if it is also a Date object that refers to the same time.
|
|
|
|
} else if (actual instanceof Date && expected instanceof Date) { |
|
|
|
return actual.getTime() === expected.getTime(); |
|
|
|
|
|
|
|
// 7.3. Other pairs that do not both pass typeof value == "object",
|
|
|
|
// equivalence is determined by ==.
|
|
|
|
} else if (typeof actual != 'object' && typeof expected != 'object') { |
|
|
|
return actual == expected; |
|
|
|
|
|
|
|
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
|
|
|
// determined by having the same number of owned properties (as verified
|
|
|
|
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
|
|
// (although not necessarily the same order), equivalent values for every
|
|
|
|
// corresponding key, and an identical "prototype" property. Note: this
|
|
|
|
// accounts for both named and indexed properties on Arrays.
|
|
|
|
} else { |
|
|
|
return objEquiv(actual, expected); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function isUndefinedOrNull (value) { |
|
|
|
return value === null || value === undefined; |
|
|
|
return value === null || value === undefined; |
|
|
|
} |
|
|
|
|
|
|
|
function isArguments (object){ |
|
|
|
return Object.prototype.toString.call(object) == '[object Arguments]'; |
|
|
|
function isArguments (object) { |
|
|
|
return Object.prototype.toString.call(object) == '[object Arguments]'; |
|
|
|
} |
|
|
|
|
|
|
|
function objEquiv (a, b) { |
|
|
|
if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) |
|
|
|
return false; |
|
|
|
// an identical "prototype" property.
|
|
|
|
if (a.prototype !== b.prototype) return false; |
|
|
|
//~~~I've managed to break Object.keys through screwy arguments passing.
|
|
|
|
// Converting to array solves the problem.
|
|
|
|
if(isArguments(a)){ |
|
|
|
if(!isArguments(b)){ |
|
|
|
return false; |
|
|
|
} |
|
|
|
a = pSlice.call(a); |
|
|
|
b = pSlice.call(b); |
|
|
|
return _deepEqual(a,b); |
|
|
|
} |
|
|
|
try{ |
|
|
|
var ka = Object.keys(a), |
|
|
|
kb = Object.keys(b), |
|
|
|
key, i; |
|
|
|
} catch (e) {//happens when one is a string literal and the other isn't
|
|
|
|
return false; |
|
|
|
if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) |
|
|
|
return false; |
|
|
|
// an identical "prototype" property.
|
|
|
|
if (a.prototype !== b.prototype) return false; |
|
|
|
//~~~I've managed to break Object.keys through screwy arguments passing.
|
|
|
|
// Converting to array solves the problem.
|
|
|
|
if (isArguments(a)) { |
|
|
|
if (!isArguments(b)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
// having the same number of owned properties (keys incorporates hasOwnProperty)
|
|
|
|
if(ka.length != kb.length) |
|
|
|
return false; |
|
|
|
//the same set of keys (although not necessarily the same order),
|
|
|
|
ka.sort(); |
|
|
|
kb.sort(); |
|
|
|
//~~~cheap key test
|
|
|
|
for (i = ka.length - 1; i >= 0; i--) { |
|
|
|
if(ka[i] != kb[i]) |
|
|
|
return false; |
|
|
|
} |
|
|
|
//equivalent values for every corresponding key, and
|
|
|
|
//~~~possibly expensive deep test
|
|
|
|
for (i = ka.length - 1; i >= 0; i--) { |
|
|
|
key = ka[i]; |
|
|
|
if(!_deepEqual(a[key], b[key] )) |
|
|
|
return false; |
|
|
|
} |
|
|
|
return true; |
|
|
|
a = pSlice.call(a); |
|
|
|
b = pSlice.call(b); |
|
|
|
return _deepEqual(a, b); |
|
|
|
} |
|
|
|
try{ |
|
|
|
var ka = Object.keys(a), |
|
|
|
kb = Object.keys(b), |
|
|
|
key, i; |
|
|
|
} catch (e) {//happens when one is a string literal and the other isn't
|
|
|
|
return false; |
|
|
|
} |
|
|
|
// having the same number of owned properties (keys incorporates hasOwnProperty)
|
|
|
|
if (ka.length != kb.length) |
|
|
|
return false; |
|
|
|
//the same set of keys (although not necessarily the same order),
|
|
|
|
ka.sort(); |
|
|
|
kb.sort(); |
|
|
|
//~~~cheap key test
|
|
|
|
for (i = ka.length - 1; i >= 0; i--) { |
|
|
|
if (ka[i] != kb[i]) |
|
|
|
return false; |
|
|
|
} |
|
|
|
//equivalent values for every corresponding key, and
|
|
|
|
//~~~possibly expensive deep test
|
|
|
|
for (i = ka.length - 1; i >= 0; i--) { |
|
|
|
key = ka[i]; |
|
|
|
if (!_deepEqual(a[key], b[key] )) |
|
|
|
return false; |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
// 8. The non-equivalence assertion tests for any deep inequality.
|
|
|
|
// assert.notDeepEqual(actual, expected, message_opt);
|
|
|
|
|
|
|
|
exports.notDeepEqual = function notDeepEqual(actual, expected, message) { |
|
|
|
if (_deepEqual(actual, expected)) |
|
|
|
fail(actual, expected, message, "notDeepEqual"); |
|
|
|
if (_deepEqual(actual, expected)) { |
|
|
|
fail(actual, expected, message, "notDeepEqual"); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
|
|
|
// assert.strictEqual(actual, expected, message_opt);
|
|
|
|
|
|
|
|
assert.strictEqual = function strictEqual(actual, expected, message) { |
|
|
|
if (actual !== expected) |
|
|
|
fail(actual, expected, message, "==="); |
|
|
|
if (actual !== expected) fail(actual, expected, message, "==="); |
|
|
|
}; |
|
|
|
|
|
|
|
// 10. The strict non-equality assertion tests for strict inequality, as determined by !==.
|
|
|
|
// assert.notStrictEqual(actual, expected, message_opt);
|
|
|
|
|
|
|
|
assert.notStrictEqual = function notStrictEqual(actual, expected, message) { |
|
|
|
if (actual === expected) |
|
|
|
fail(actual, expected, message, "!=="); |
|
|
|
if (actual === expected) fail(actual, expected, message, "!=="); |
|
|
|
}; |
|
|
|
|
|
|
|
// 11. Expected to throw an error:
|
|
|
|
// assert.throws(block, Error_opt, message_opt);
|
|
|
|
function _throws (shouldThrow, block, err, message) { |
|
|
|
var exception = null, |
|
|
|
threw = false, |
|
|
|
typematters = true; |
|
|
|
|
|
|
|
assert.throws = function(block, /*optional*/error, /*optional*/message){ |
|
|
|
var args = [true] |
|
|
|
_throws.apply(this, args.concat(pSlice.call(arguments))); |
|
|
|
} |
|
|
|
message = message || ""; |
|
|
|
|
|
|
|
// EXTENSION! This is annoying to write outside this module.
|
|
|
|
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message){ |
|
|
|
var args = [false] |
|
|
|
_throws.apply(this, args.concat(pSlice.call(arguments))); |
|
|
|
//handle optional arguments
|
|
|
|
if (arguments.length == 3) { |
|
|
|
if (typeof(err) == "string") { |
|
|
|
message = err; |
|
|
|
typematters = false; |
|
|
|
} |
|
|
|
} else if (arguments.length == 2) { |
|
|
|
typematters = false; |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
block(); |
|
|
|
} catch (e) { |
|
|
|
threw = true; |
|
|
|
exception = e; |
|
|
|
} |
|
|
|
|
|
|
|
if (shouldThrow && !threw) { |
|
|
|
fail( "Missing expected exception" |
|
|
|
+ (err && err.name ? " ("+err.name+")." : '.') |
|
|
|
+ (message ? " " + message : "") |
|
|
|
); |
|
|
|
} |
|
|
|
if (!shouldThrow && threw && typematters && exception instanceof err) { |
|
|
|
fail( "Got unwanted exception" |
|
|
|
+ (err && err.name ? " ("+err.name+")." : '.') |
|
|
|
+ (message ? " " + message : "") |
|
|
|
); |
|
|
|
} |
|
|
|
if ((shouldThrow && threw && typematters && !(exception instanceof err)) || |
|
|
|
(!shouldThrow && threw)) { |
|
|
|
throw exception; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var _throws = function (shouldThrow, block, err, message) { |
|
|
|
var exception = null |
|
|
|
threw = false |
|
|
|
typematters = true; |
|
|
|
message = message || ""; |
|
|
|
|
|
|
|
//handle optional arguments
|
|
|
|
if(arguments.length == 3){ |
|
|
|
if(typeof(err) == "string"){ |
|
|
|
message = err; |
|
|
|
typematters = false; |
|
|
|
} |
|
|
|
} else if(arguments.length == 2) { |
|
|
|
typematters = false; |
|
|
|
} |
|
|
|
// 11. Expected to throw an error:
|
|
|
|
// assert.throws(block, Error_opt, message_opt);
|
|
|
|
|
|
|
|
try { |
|
|
|
block(); |
|
|
|
} catch (e) { |
|
|
|
threw = true; |
|
|
|
exception = e; |
|
|
|
} |
|
|
|
assert.throws = function(block, /*optional*/error, /*optional*/message) { |
|
|
|
_throws.apply(this, [true].concat(pSlice.call(arguments))); |
|
|
|
}; |
|
|
|
|
|
|
|
if(shouldThrow && !threw){ |
|
|
|
fail("Missing expected exception"+ |
|
|
|
(err && err.name ? " ("+err.name+")." : '.') + |
|
|
|
(message ? " " + message : "")); |
|
|
|
} |
|
|
|
if(!shouldThrow && threw && typematters && exception instanceof err){ |
|
|
|
fail("Got unwanted exception" + |
|
|
|
(err && err.name ? " ("+err.name+")." : '.') + |
|
|
|
(message ? " " + message : "")); |
|
|
|
} |
|
|
|
if((shouldThrow && threw && typematters && !(exception instanceof err)) || |
|
|
|
(!shouldThrow && threw)){ |
|
|
|
throw exception; |
|
|
|
} |
|
|
|
// EXTENSION! This is annoying to write outside this module.
|
|
|
|
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { |
|
|
|
_throws.apply(this, [false].concat(pSlice.call(arguments))); |
|
|
|
}; |
|
|
|