unexpected
Advanced tools
Comparing version 3.1.1 to 3.1.2
@@ -26,3 +26,2 @@ /*global console, __dirname, weknowhow*/ | ||
'unexpected-utils.js', | ||
'unexpected-equal.js', | ||
'unexpected-inspect.js', | ||
@@ -29,0 +28,0 @@ 'unexpected-core.js', |
@@ -8,2 +8,3 @@ /*global namespace*/ | ||
var map = shim.map; | ||
var indexOf = shim.indexOf; | ||
var trim = shim.trim; | ||
@@ -15,2 +16,4 @@ var reduce = shim.reduce; | ||
var truncateStack = utils.truncateStack; | ||
var isUndefinedOrNull = utils.isUndefinedOrNull; | ||
var isArguments = utils.isArguments; | ||
var extend = utils.extend; | ||
@@ -68,4 +71,82 @@ var levenshteinDistance = utils.levenshteinDistance; | ||
Unexpected.prototype.equal = function (actual, expected) { | ||
return namespace.equal(actual, expected, this.types); | ||
Unexpected.prototype.equal = function (actual, expected, stack) { | ||
var matchingCustomType = utils.findFirst(this.types || [], function (type) { | ||
return type.identify(actual) && type.identify(expected); | ||
}); | ||
if (matchingCustomType) { | ||
return matchingCustomType.equal(actual, expected); | ||
} | ||
// 7.1. All identical values are equivalent, as determined by ===. | ||
if (actual === expected) { | ||
return true; | ||
// 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 using === for every | ||
// corresponding key, and an identical "prototype" property. Note: this | ||
// accounts for both named and indexed properties on Arrays. | ||
} else { | ||
if (isUndefinedOrNull(actual) || isUndefinedOrNull(expected)) { | ||
return false; | ||
} | ||
// an identical "prototype" property. | ||
if (actual.prototype !== expected.prototype) { | ||
return false; | ||
} | ||
//~~~I've managed to break Object.keys through screwy arguments passing. | ||
// Converting to array solves the problem. | ||
if (isArguments(actual)) { | ||
if (!isArguments(expected)) { | ||
return false; | ||
} | ||
return this.equal(Array.prototype.slice.call(actual), Array.prototype.slice.call(expected), stack); | ||
} | ||
var actualKeys, expectedKeys, key, i; | ||
try { | ||
actualKeys = getKeys(actual); | ||
expectedKeys = getKeys(expected); | ||
} 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 (actualKeys.length !== expectedKeys.length) { | ||
return false; | ||
} | ||
//the same set of keys (although not necessarily the same order), | ||
actualKeys.sort(); | ||
expectedKeys.sort(); | ||
//~~~cheap key test | ||
for (i = actualKeys.length - 1; i >= 0; i -= 1) { | ||
if (actualKeys[i] !== expectedKeys[i]) { | ||
return false; | ||
} | ||
} | ||
if (stack) { | ||
if (indexOf(stack, actual) !== -1) { | ||
throw new Error('Cannot compare circular structures'); | ||
} | ||
stack.push(actual); | ||
} else { | ||
stack = [actual]; | ||
} | ||
//equivalent values for every corresponding key, and | ||
//~~~possibly expensive deep test | ||
for (i = actualKeys.length - 1; i >= 0; i -= 1) { | ||
key = actualKeys[i]; | ||
if (!this.equal(actual[key], expected[key], stack)) { | ||
stack.pop(); | ||
return false; | ||
} | ||
} | ||
stack.pop(); | ||
return true; | ||
} | ||
}; | ||
@@ -153,19 +234,15 @@ | ||
var sanitized; | ||
for (i = 0 ; i < this.types.length ; i += 1) { | ||
if (this.types[i].identify(obj)) { | ||
stack.push(obj); | ||
sanitized = this.sanitize(this.types[i].toJSON(obj), stack); | ||
stack.pop(); | ||
return sanitized; | ||
} | ||
} | ||
if (isArray(obj)) { | ||
stack.push(obj); | ||
stack.push(obj); | ||
var sanitized, | ||
matchingCustomType = utils.findFirst(this.types || [], function (type) { | ||
return type.identify(obj); | ||
}); | ||
if (matchingCustomType) { | ||
sanitized = this.sanitize(matchingCustomType.toJSON(obj), stack); | ||
} else if (isArray(obj)) { | ||
sanitized = map(obj, function (item) { | ||
return this.sanitize(item, stack); | ||
}, this); | ||
stack.pop(); | ||
} else if (typeof obj === 'object' && obj) { | ||
stack.push(obj); | ||
sanitized = {}; | ||
@@ -175,6 +252,6 @@ forEach(getKeys(obj).sort(), function (key) { | ||
}, this); | ||
stack.pop(); | ||
} else { | ||
sanitized = obj; | ||
} | ||
stack.pop(); | ||
return sanitized; | ||
@@ -181,0 +258,0 @@ }; |
@@ -70,8 +70,41 @@ /*global namespace*/ | ||
}, | ||
getHexDumpLines: function (buffer, width) { | ||
var hexDumpLines = []; | ||
if (typeof width !== 'number') { | ||
width = 16; | ||
} else if (width === 0) { | ||
width = buffer.length; | ||
} | ||
for (var i = 0 ; i < buffer.length ; i += width) { | ||
var hexChars = '', | ||
asciiChars = ' |'; | ||
for (var j = 0 ; j < width ; j += 1) { | ||
if (i + j < buffer.length) { | ||
var octet = buffer[i + j]; | ||
hexChars += (octet < 16 ? '0' : '') + octet.toString(16).toUpperCase() + ' '; | ||
asciiChars += (octet >= 20 && octet < 127) ? String.fromCharCode(octet) : '.'; | ||
} else { | ||
hexChars += ' '; | ||
} | ||
} | ||
asciiChars += '|'; | ||
hexDumpLines.push(hexChars + asciiChars); | ||
} | ||
return hexDumpLines; | ||
}, | ||
inspect: function (buffer) { | ||
return buffer.toString(); | ||
var inspectedContents, | ||
maxLength = 20; | ||
if (buffer.length > maxLength) { | ||
inspectedContents = this.getHexDumpLines(buffer.slice(0, maxLength), 0) + ' (+' + (buffer.length - maxLength) + ')'; | ||
} else { | ||
inspectedContents = this.getHexDumpLines(buffer, 0).join('\n'); | ||
} | ||
return '[Buffer ' + inspectedContents + ']'; | ||
}, | ||
toJSON: function (buffer) { | ||
return { | ||
$buffer: Array.prototype.slice.call(buffer) | ||
$buffer: this.getHexDumpLines(buffer) | ||
}; | ||
@@ -78,0 +111,0 @@ } |
{ | ||
"name": "unexpected", | ||
"version": "3.1.1", | ||
"version": "3.1.2", | ||
"author": "Sune Sloth Simonsen <sune@we-knowhow.dk>", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -194,2 +194,12 @@ /*global describe, it, expect, beforeEach, setTimeout*/ | ||
it('fails gracefully when comparing circular structures', function () { | ||
var foo = {}, | ||
bar = {}; | ||
foo.foo = foo; | ||
bar.foo = bar; | ||
expect(function () { | ||
expect(foo, 'not to equal', bar); | ||
}, 'to throw', 'Cannot compare circular structures'); | ||
}); | ||
it('throws when the assertion fails', function () { | ||
@@ -256,2 +266,32 @@ expect(function () { | ||
}); | ||
if (typeof Buffer !== 'undefined') { | ||
it('produces a hex-diff in JSON when Buffers differ', function () { | ||
expect(function () { | ||
expect( | ||
new Buffer('\x00\x01\x02Here is the thing I was talking about', 'utf-8'), | ||
'to equal', | ||
new Buffer('\x00\x01\x02Here is the thing I was quuxing about', 'utf-8') | ||
); | ||
}, 'to throw', function (err) { | ||
expect(err, 'to have properties', { | ||
showDiff: true, | ||
actual: { | ||
$buffer: [ | ||
'00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 |...Here is the t|', | ||
'68 69 6E 67 20 49 20 77 61 73 20 74 61 6C 6B 69 |hing I was talki|', | ||
'6E 67 20 61 62 6F 75 74 |ng about|' | ||
] | ||
}, | ||
expected: { | ||
$buffer: [ | ||
'00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 |...Here is the t|', | ||
'68 69 6E 67 20 49 20 77 61 73 20 71 75 75 78 69 |hing I was quuxi|', | ||
'6E 67 20 61 62 6F 75 74 |ng about|' | ||
] | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
}); | ||
@@ -258,0 +298,0 @@ |
@@ -209,12 +209,2 @@ (function () { | ||
} | ||
}, | ||
findFirst: function (arr, predicate, thisObj) { | ||
var scope = thisObj || null; | ||
for (var i = 0 ; i < arr.length ; i += 1) { | ||
if (predicate.call(scope, arr[i], i, arr)) { | ||
return arr[i]; | ||
} | ||
} | ||
return null; | ||
} | ||
@@ -231,2 +221,3 @@ }; | ||
var utils = namespace.utils; | ||
var isRegExp = utils.isRegExp; | ||
var isArguments = utils.isArguments; | ||
@@ -240,15 +231,16 @@ var isUndefinedOrNull = utils.isUndefinedOrNull; | ||
*/ | ||
function equal(actual, expected, types) { | ||
var matchingCustomType = utils.findFirst(types || [], function (type) { | ||
return type.identify(actual) && type.identify(expected); | ||
}); | ||
if (matchingCustomType) { | ||
return matchingCustomType.equal(actual, expected, types); | ||
} | ||
function equal(actual, expected) { | ||
// 7.1. All identical values are equivalent, as determined by ===. | ||
if (actual === expected) { | ||
return true; | ||
} else if ('undefined' !== typeof Buffer && | ||
Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { | ||
if (actual.length !== expected.length) return false; | ||
for (var i = 0; i < actual.length; i += 1) { | ||
if (actual[i] !== expected[i]) return false; | ||
} | ||
return true; | ||
// 7.2. If the expected value is a Date object, the actual value is | ||
@@ -271,7 +263,7 @@ // equivalent if it is also a Date object that refers to the same time. | ||
} else { | ||
return objEquiv(actual, expected, types); | ||
return objEquiv(actual, expected); | ||
} | ||
} | ||
function objEquiv(a, b, types) { | ||
function objEquiv(a, b) { | ||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) | ||
@@ -283,2 +275,8 @@ return false; | ||
// Converting to array solves the problem. | ||
if (isRegExp(a)) { | ||
if (!isRegExp(b)) { | ||
return false; | ||
} | ||
return a.source === b.source && a.global === b.global && a.ignoreCase === b.ignoreCase && a.multiline === b.multiline; | ||
} | ||
if (isArguments(a)) { | ||
@@ -290,3 +288,3 @@ if (!isArguments(b)) { | ||
b = Array.prototype.slice.call(b); | ||
return equal(a, b, types); | ||
return equal(a, b); | ||
} | ||
@@ -315,3 +313,3 @@ var ka, kb, key, i; | ||
key = ka[i]; | ||
if (!equal(a[key], b[key], types)) | ||
if (!equal(a[key], b[key])) | ||
return false; | ||
@@ -350,3 +348,3 @@ } | ||
*/ | ||
var inspect = function (obj, showHidden, depth, types) { | ||
var inspect = function (obj, showHidden, depth) { | ||
var seen = []; | ||
@@ -359,10 +357,3 @@ | ||
function format(value, recurseTimes) { | ||
var matchingCustomType = utils.findFirst(types || [], function (type) { | ||
return type.identify(value); | ||
}); | ||
if (matchingCustomType) { | ||
return matchingCustomType.inspect(value); | ||
} | ||
// Provide a hook for user-specified inspect functions. | ||
@@ -557,2 +548,5 @@ // Check that value is an object with an inspect function on it | ||
(function () { | ||
var inspect = namespace.inspect; | ||
var equal = namespace.equal; | ||
var shim = namespace.shim; | ||
@@ -571,10 +565,5 @@ var bind = shim.bind; | ||
var levenshteinDistance = utils.levenshteinDistance; | ||
var isArray = utils.isArray; | ||
function Assertion(expect, subject, testDescription, flags, args) { | ||
this.expect = expect; | ||
function Assertion(subject, testDescription, flags, args) { | ||
this.obj = subject; // deprecated | ||
this.equal = bind(expect.equal, expect); // deprecated | ||
this.eql = this.equal; // deprecated | ||
this.inspect = bind(expect.inspect, expect); // deprecated | ||
this.subject = subject; | ||
@@ -588,5 +577,4 @@ this.testDescription = testDescription; | ||
Assertion.prototype.standardErrorMessage = function () { | ||
var expect = this.expect; | ||
var argsString = map(this.args, function (arg) { | ||
return expect.inspect(arg); | ||
return inspect(arg); | ||
}).join(', '); | ||
@@ -599,3 +587,3 @@ | ||
return 'expected ' + | ||
expect.inspect(this.subject) + | ||
inspect(this.subject) + | ||
' ' + this.testDescription + | ||
@@ -619,19 +607,10 @@ argsString; | ||
function Unexpected(assertions, types) { | ||
function Unexpected(assertions) { | ||
this.assertions = assertions || {}; | ||
this.types = types || []; | ||
} | ||
Unexpected.prototype.equal = function (actual, expected) { | ||
return namespace.equal(actual, expected, this.types); | ||
}; | ||
Unexpected.prototype.inspect = function (obj) { | ||
return namespace.inspect(obj, false, 2, this.types); | ||
}; | ||
Unexpected.prototype.format = function (message, args) { | ||
args = map(args, function (arg) { | ||
return this.inspect(arg); | ||
}, this); | ||
return inspect(arg); | ||
}); | ||
message = message.replace(/\{(\d+)\}/g, function (match, n) { | ||
@@ -683,8 +662,2 @@ return args[n] || match; | ||
Unexpected.prototype.addType = function (obj) { | ||
this.types.unshift(obj); | ||
return this.expect; | ||
}; | ||
Unexpected.prototype.installPlugin = function (plugin) { | ||
@@ -700,41 +673,2 @@ if (typeof plugin !== 'function') { | ||
Unexpected.prototype.sanitize = function (obj, stack) { | ||
stack = stack || []; | ||
var i; | ||
for (i = 0 ; i < stack.length ; i += 1) { | ||
if (stack[i] === obj) { | ||
return obj; | ||
} | ||
} | ||
var sanitized; | ||
for (i = 0 ; i < this.types.length ; i += 1) { | ||
if (this.types[i].identify(obj)) { | ||
stack.push(obj); | ||
sanitized = this.sanitize(this.types[i].toJSON(obj), stack); | ||
stack.pop(); | ||
return sanitized; | ||
} | ||
} | ||
if (isArray(obj)) { | ||
stack.push(obj); | ||
sanitized = map(obj, function (item) { | ||
return this.sanitize(item, stack); | ||
}, this); | ||
stack.pop(); | ||
} else if (typeof obj === 'object' && obj) { | ||
stack.push(obj); | ||
sanitized = {}; | ||
forEach(getKeys(obj).sort(), function (key) { | ||
sanitized[key] = this.sanitize(obj[key], stack); | ||
}, this); | ||
stack.pop(); | ||
} else { | ||
sanitized = obj; | ||
} | ||
return sanitized; | ||
}; | ||
function handleNestedExpects(e, assertion) { | ||
@@ -757,8 +691,4 @@ switch (assertion.errorMode) { | ||
var expect = bind(expectFunction, unexpected); | ||
expect.equal = bind(unexpected.equal, unexpected); | ||
expect.sanitize = bind(unexpected.sanitize, unexpected); | ||
expect.inspect = bind(unexpected.inspect, unexpected); | ||
expect.fail = bind(unexpected.fail, unexpected); | ||
expect.addAssertion = bind(unexpected.addAssertion, unexpected); | ||
expect.addType = bind(unexpected.addType, unexpected); | ||
expect.clone = bind(unexpected.clone, unexpected); | ||
@@ -812,11 +742,5 @@ expect.toString = bind(unexpected.toString, unexpected); | ||
// Not sure this is the right way to go about this: | ||
wrappedExpect.equal = this.equal; | ||
wrappedExpect.types = this.types; | ||
wrappedExpect.sanitize = this.sanitize; | ||
wrappedExpect.inspect = this.inspect; | ||
var args = Array.prototype.slice.call(arguments, 2); | ||
args.unshift(wrappedExpect, subject); | ||
var assertion = new Assertion(wrappedExpect, subject, testDescriptionString, flags, args.slice(2)); | ||
var assertion = new Assertion(subject, testDescriptionString, flags, args.slice(2)); | ||
var handler = assertionRule.handler; | ||
@@ -847,3 +771,3 @@ try { | ||
Unexpected.prototype.clone = function () { | ||
var unexpected = new Unexpected(extend({}, this.assertions), [].concat(this.types)); | ||
var unexpected = new Unexpected(extend({}, this.assertions)); | ||
return makeExpectFunction(unexpected); | ||
@@ -1001,2 +925,7 @@ }; | ||
Assertion.prototype.inspect = inspect; | ||
Assertion.prototype.eql = equal; // Deprecated | ||
Assertion.prototype.equal = equal; | ||
namespace.expect = Unexpected.create(); | ||
@@ -1106,23 +1035,9 @@ }()); | ||
// TODO the not flag does not make a lot of sense in this case | ||
if (this.flags.not) { | ||
forEach(getKeys(properties), function (property) { | ||
forEach(getKeys(properties), function (property) { | ||
if (this.flags.not) { | ||
expect(subject, 'not to have [own] property', property); | ||
}); | ||
} else { | ||
try { | ||
forEach(getKeys(properties), function (property) { | ||
expect(subject, 'to have [own] property', property, properties[property]); | ||
}); | ||
} catch (e) { | ||
e.expected = expect.sanitize(properties); | ||
for (var propertyName in subject) { | ||
if ((!this.flags.own || subject.hasOwnProperty(propertyName)) && !(propertyName in properties)) { | ||
e.expected[propertyName] = expect.sanitize(subject[propertyName]); | ||
} | ||
} | ||
e.actual = expect.sanitize(subject); | ||
e.showDiff = true; | ||
throw e; | ||
} else { | ||
expect(subject, 'to have [own] property', property, properties[property]); | ||
} | ||
} | ||
}, this); | ||
} else { | ||
@@ -1236,7 +1151,7 @@ throw new Error("Assertion '" + this.testDescription + "' only supports " + | ||
try { | ||
expect(expect.equal(value, subject), '[not] to be true'); | ||
expect(this.equal(value, subject), '[not] to be true'); | ||
} catch (e) { | ||
if (!this.flags.not) { | ||
e.expected = expect.sanitize(value); | ||
e.actual = expect.sanitize(subject); | ||
e.expected = value; | ||
e.actual = subject; | ||
// Explicitly tell mocha to stringify and diff arrays | ||
@@ -1319,3 +1234,3 @@ // and objects, but only when the types are identical | ||
if (errors.length > 0) { | ||
var objectString = expect.inspect(subject); | ||
var objectString = this.inspect(subject); | ||
var prefix = /\n/.test(objectString) ? '\n' : ' '; | ||
@@ -1399,82 +1314,2 @@ var message = 'failed expectation in' + prefix + objectString + ':\n' + | ||
(function () { | ||
var expect = namespace.expect; | ||
var utils = namespace.utils; | ||
var isRegExp = utils.isRegExp; | ||
expect.addType({ | ||
identify: function (obj) { | ||
return Object.prototype.toString.call(obj) === '[object Date]'; | ||
}, | ||
equal: function (a, b) { | ||
return a.getTime() === b.getTime(); | ||
}, | ||
inspect: function (date) { | ||
return '[Date ' + date.toUTCString() + ']'; | ||
}, | ||
toJSON: function (date) { | ||
return { | ||
$date: this.inspect(date) | ||
}; | ||
} | ||
}); | ||
expect.addType({ | ||
identify: function (f) { | ||
return typeof f === 'function'; | ||
}, | ||
equal: function (a, b) { | ||
return a === b || a.toString() === b.toString(); | ||
}, | ||
inspect: function (f) { | ||
var n = f.name ? ': ' + f.name : ''; | ||
return '[Function' + n + ']'; | ||
}, | ||
toJSON: function (f) { | ||
return { | ||
$function: this.inspect(f) | ||
}; | ||
} | ||
}); | ||
expect.addType({ | ||
identify: isRegExp, | ||
equal: function (a, b) { | ||
return a.source === b.source && a.global === b.global && a.ignoreCase === b.ignoreCase && a.multiline === b.multiline; | ||
}, | ||
inspect: function (regExp) { | ||
return '' + regExp; | ||
}, | ||
toJSON: function (regExp) { | ||
return { | ||
$regExp: this.inspect(regExp) | ||
}; | ||
} | ||
}); | ||
if (typeof Buffer !== 'undefined') { | ||
expect.addType({ | ||
identify: Buffer.isBuffer, | ||
equal: function (a, b) { | ||
if (a.length !== b.length) return false; | ||
for (var i = 0; i < a.length; i += 1) { | ||
if (a[i] !== b[i]) return false; | ||
} | ||
return true; | ||
}, | ||
inspect: function (buffer) { | ||
return buffer.toString(); | ||
}, | ||
toJSON: function (buffer) { | ||
return { | ||
$buffer: Array.prototype.slice.call(buffer) | ||
}; | ||
} | ||
}); | ||
} | ||
}()); | ||
(function () { | ||
var global = this; | ||
@@ -1481,0 +1316,0 @@ var expect = namespace.expect; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
288020
26
5615