unexpected
Advanced tools
Comparing version 3.1.7 to 3.1.8
{ | ||
"name": "unexpected", | ||
"version": "3.1.7", | ||
"version": "3.1.8", | ||
"author": "Sune Sloth Simonsen <sune@we-knowhow.dk>", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -236,2 +236,211 @@ (function () { | ||
var shim = namespace.shim; | ||
var json = shim.JSON; | ||
var getKeys = shim.getKeys; | ||
var map = shim.map; | ||
var indexOf = shim.indexOf; | ||
var reduce = shim.reduce; | ||
var utils = namespace.utils; | ||
var isDOMElement = utils.isDOMElement; | ||
var getOuterHTML = utils.getOuterHTML; | ||
var isArray = utils.isArray; | ||
var isRegExp = utils.isRegExp; | ||
var isError = utils.isError; | ||
function formatError(err) { | ||
return '[' + Error.prototype.toString.call(err) + ']'; | ||
} | ||
/** | ||
* Inspects an object. | ||
* | ||
* @see taken from node.js `util` module (copyright Joyent, MIT license) | ||
*/ | ||
var inspect = function (obj, showHidden, depth, types) { | ||
var seen = []; | ||
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. | ||
// Check that value is an object with an inspect function on it | ||
if (value && typeof value.inspect === 'function' && | ||
// Filter out the util module, it's inspect function is special | ||
(typeof exports === 'undefined' || value !== exports) && | ||
// Also filter out any prototype objects using the circular check. | ||
!(value.constructor && value.constructor.prototype === value)) { | ||
return value.inspect(recurseTimes); | ||
} | ||
// Primitive types cannot have properties | ||
switch (typeof value) { | ||
case 'undefined': | ||
return 'undefined'; | ||
case 'string': | ||
return '\'' + json.stringify(value).replace(/^"|"$/g, '') | ||
.replace(/'/g, "\\'") | ||
.replace(/\\"/g, '"') + '\''; | ||
case 'number': | ||
case 'boolean': | ||
return '' + value; | ||
} | ||
// For some reason typeof null is "object", so special case here. | ||
if (value === null) { | ||
return 'null'; | ||
} | ||
if (isDOMElement(value)) { | ||
return getOuterHTML(value); | ||
} | ||
if (isRegExp(value)) { | ||
return '' + value; | ||
} | ||
if (isError(value)) { | ||
return formatError(value); | ||
} | ||
// Look up the keys of the object. | ||
var visible_keys = getKeys(value); | ||
var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys; | ||
// Functions without properties can be shortcutted. | ||
if (typeof value === 'function' && $keys.length === 0) { | ||
if (isRegExp(value)) { | ||
return '' + value; | ||
} else { | ||
var name = value.name ? ': ' + value.name : ''; | ||
return '[Function' + name + ']'; | ||
} | ||
} | ||
var base, type, braces; | ||
// Determine the object type | ||
if (isArray(value)) { | ||
type = 'Array'; | ||
braces = ['[', ']']; | ||
} else { | ||
type = 'Object'; | ||
braces = ['{', '}']; | ||
} | ||
// Make functions say that they are functions | ||
if (typeof value === 'function') { | ||
var n = value.name ? ': ' + value.name : ''; | ||
base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; | ||
} else { | ||
base = ''; | ||
} | ||
if ($keys.length === 0) { | ||
return braces[0] + base + braces[1]; | ||
} | ||
if (recurseTimes < 0) { | ||
if (isRegExp(value)) { | ||
return '' + value; | ||
} else { | ||
return '[Object]'; | ||
} | ||
} | ||
seen.push(value); | ||
var output = map($keys, function (key) { | ||
var name, str; | ||
if (value.__lookupGetter__) { | ||
if (value.__lookupGetter__(key)) { | ||
if (value.__lookupSetter__(key)) { | ||
str = '[Getter/Setter]'; | ||
} else { | ||
str = '[Getter]'; | ||
} | ||
} else { | ||
if (value.__lookupSetter__(key)) { | ||
str = '[Setter]'; | ||
} | ||
} | ||
} | ||
if (indexOf(visible_keys, key) < 0) { | ||
name = '[' + key + ']'; | ||
} | ||
if (!str) { | ||
if (indexOf(seen, value[key]) < 0) { | ||
if (recurseTimes === null) { | ||
str = format(value[key]); | ||
} else { | ||
str = format(value[key], recurseTimes - 1); | ||
} | ||
if (str.indexOf('\n') > -1) { | ||
if (isArray(value)) { | ||
str = map(str.split('\n'), function (line) { | ||
return ' ' + line; | ||
}).join('\n').substr(2); | ||
} else { | ||
str = '\n' + map(str.split('\n'), function (line) { | ||
return ' ' + line; | ||
}).join('\n'); | ||
} | ||
} | ||
} else { | ||
str = '[Circular]'; | ||
} | ||
} | ||
if (typeof name === 'undefined') { | ||
if (type === 'Array' && key.match(/^\d+$/)) { | ||
return str; | ||
} | ||
name = json.stringify('' + key); | ||
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { | ||
name = name.substr(1, name.length - 2); | ||
} else { | ||
name = name.replace(/'/g, "\\'") | ||
.replace(/\\"/g, '"') | ||
.replace(/(^"|"$)/g, "'"); | ||
} | ||
} | ||
return name + ': ' + str; | ||
}); | ||
seen.pop(); | ||
var numLinesEst = 0; | ||
var length = reduce(output, function (prev, cur) { | ||
numLinesEst += 1; | ||
if (indexOf(cur, '\n') >= 0) numLinesEst += 1; | ||
return prev + cur.length + 1; | ||
}, 0); | ||
if (length > 50) { | ||
output = braces[0] + | ||
(base === '' ? '' : base + '\n ') + | ||
' ' + | ||
output.join(',\n ') + | ||
' ' + | ||
braces[1]; | ||
} else { | ||
output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; | ||
} | ||
return output; | ||
} | ||
return format(obj, (typeof depth === 'undefined' ? 2 : depth)); | ||
}; | ||
namespace.inspect = inspect; | ||
}()); | ||
(function () { | ||
var shim = namespace.shim; | ||
var bind = shim.bind; | ||
@@ -241,2 +450,3 @@ var forEach = shim.forEach; | ||
var map = shim.map; | ||
var indexOf = shim.indexOf; | ||
var trim = shim.trim; | ||
@@ -248,2 +458,5 @@ var reduce = shim.reduce; | ||
var truncateStack = utils.truncateStack; | ||
var isUndefinedOrNull = utils.isUndefinedOrNull; | ||
var isArguments = utils.isArguments; | ||
var getKeysOfDefinedProperties = utils.getKeysOfDefinedProperties; | ||
var extend = utils.extend; | ||
@@ -301,4 +514,3 @@ var levenshteinDistance = utils.levenshteinDistance; | ||
Unexpected.prototype.equal = function (actual, expected) { | ||
var that = this; | ||
Unexpected.prototype.equal = function (actual, expected, stack) { | ||
var matchingCustomType = utils.findFirst(this.types || [], function (type) { | ||
@@ -309,36 +521,81 @@ return type.identify(actual) && type.identify(expected); | ||
if (matchingCustomType) { | ||
return matchingCustomType.equal(actual, expected, function (a, b) { | ||
return that.equal(a, b); | ||
}); | ||
return matchingCustomType.equal(actual, expected); | ||
} | ||
return false; // we should never get there | ||
}; | ||
// 7.1. All identical values are equivalent, as determined by ===. | ||
if (actual === expected) { | ||
return true; | ||
Unexpected.prototype.inspect = function (obj) { | ||
var types = this.types; | ||
var seen = []; | ||
var format = function (obj, depth) { | ||
if (depth === 0) { | ||
return '...'; | ||
// 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 (typeof actual !== typeof expected) { | ||
return false; | ||
} else { | ||
if (isUndefinedOrNull(actual) || isUndefinedOrNull(expected)) { | ||
return false; | ||
} | ||
// an identical "prototype" property. | ||
if (actual.prototype !== expected.prototype) { | ||
return false; | ||
} | ||
seen = seen || []; | ||
if (seen.indexOf(obj) !== -1) { | ||
return '[Circular]'; | ||
//~~~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 = (actual && typeof actual === 'object') ? getKeysOfDefinedProperties(actual) : [], | ||
expectedKeys = (expected && typeof expected === 'object') ? getKeysOfDefinedProperties(expected) : [], | ||
key, | ||
i; | ||
var matchingCustomType = utils.findFirst(types || [], function (type) { | ||
return type.identify(obj); | ||
}); | ||
if (matchingCustomType) { | ||
return matchingCustomType.inspect(obj, function (v) { | ||
seen.push(obj); | ||
return format(v, depth - 1); | ||
}); | ||
// 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; | ||
} | ||
}; | ||
return format(obj, 3); | ||
Unexpected.prototype.inspect = function (obj) { | ||
return namespace.inspect(obj, false, 2, this.types); | ||
}; | ||
@@ -396,21 +653,5 @@ | ||
Unexpected.prototype.getType = function (typeName) { | ||
return utils.findFirst(this.types, function (type) { | ||
return type.name === typeName; | ||
}); | ||
}; | ||
Unexpected.prototype.addType = function (obj) { | ||
this.types.unshift(obj); | ||
Unexpected.prototype.addType = function (type) { | ||
if (type.base) { | ||
var base = utils.findFirst(this.types, function (t) { | ||
return t.name === type.base; | ||
}); | ||
if (!base) { | ||
throw new Error('Unknown base type: ' + type.base); | ||
} | ||
type = extend({ baseType: base }, base, type); | ||
} | ||
this.types.unshift(type); | ||
return this.expect; | ||
@@ -430,3 +671,2 @@ }; | ||
Unexpected.prototype.sanitize = function (obj, stack) { | ||
var that = this; | ||
stack = stack || []; | ||
@@ -448,5 +688,3 @@ | ||
if (matchingCustomType) { | ||
sanitized = matchingCustomType.toJSON(obj, function (v) { | ||
return that.sanitize(v, stack); | ||
}); | ||
sanitized = this.sanitize(matchingCustomType.toJSON(obj), stack); | ||
} else if (isArray(obj)) { | ||
@@ -963,6 +1201,2 @@ sanitized = map(obj, function (item) { | ||
} catch (e) { | ||
if (e.message && e.message.match(/Maximum call stack size exceeded/)) { | ||
throw new Error('Cannot compare circular structures'); | ||
} | ||
if (!this.flags.not) { | ||
@@ -1132,166 +1366,4 @@ e.expected = expect.sanitize(value); | ||
var leftPad = utils.leftPad; | ||
var shim = namespace.shim; | ||
var json = shim.JSON; | ||
var every = shim.every; | ||
var map = shim.map; | ||
var getKeys = shim.getKeys; | ||
var reduce = shim.reduce; | ||
expect.addType({ | ||
name: 'primitive', | ||
identify: function (value) { | ||
return true; | ||
}, | ||
equal: function (a, b) { | ||
return a === b; | ||
}, | ||
inspect: function (value) { | ||
return '' + value; | ||
}, | ||
toJSON: function (value) { | ||
return value; | ||
} | ||
}); | ||
expect.addType({ | ||
name: 'object', | ||
identify: function (arr) { | ||
return typeof arr === 'object'; | ||
}, | ||
equal: function (a, b, equal) { | ||
// 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 (utils.isArguments(a)) { | ||
if (!utils.isArguments(b)) { | ||
return false; | ||
} | ||
return equal(Array.prototype.slice.call(a), Array.prototype.slice.call(b)); | ||
} | ||
var actualKeys = utils.getKeysOfDefinedProperties(a), | ||
expectedKeys = utils.getKeysOfDefinedProperties(b), | ||
key, | ||
i; | ||
// 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; | ||
} | ||
} | ||
//equivalent values for every corresponding key, and | ||
//~~~possibly expensive deep test | ||
for (i = actualKeys.length - 1; i >= 0; i -= 1) { | ||
key = actualKeys[i]; | ||
if (!equal(a[key], b[key])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
}, | ||
inspect: function (obj, inspect) { | ||
var keys = getKeys(obj); | ||
if (keys.length === 0) { | ||
return '{}'; | ||
} | ||
var inspectedItems = map(keys, function (key) { | ||
var parts = [key + ':']; | ||
if (obj.__lookupGetter__) { | ||
var hasGetter = obj.__lookupGetter__(key); | ||
var hasSetter = obj.__lookupSetter__(key); | ||
if (hasGetter || !hasSetter) { | ||
parts.push(inspect(obj[key])); | ||
} | ||
if (hasGetter && hasSetter) { | ||
parts.push('[Getter/Setter]'); | ||
} else if (hasGetter) { | ||
parts.push('[Getter]'); | ||
} else if (hasSetter) { | ||
parts.push('[Setter]'); | ||
} | ||
} | ||
return parts.join(' '); | ||
}); | ||
var length = reduce(inspectedItems, function (result, v) { | ||
return result + v.length; | ||
}, 0); | ||
if (length > 50) { | ||
return '{\n ' + inspectedItems.join(',\n ') + '\n}'; | ||
} else { | ||
return '{ ' + inspectedItems.join(', ') + ' }'; | ||
} | ||
}, | ||
toJSON: function (obj, toJSON) { | ||
return reduce(getKeys(obj), function (result, key) { | ||
result[key] = toJSON(obj[key]); | ||
return result; | ||
}, {}); | ||
} | ||
}); | ||
expect.addType({ | ||
name: 'array', | ||
identify: function (arr) { | ||
return utils.isArray(arr); | ||
}, | ||
equal: function (a, b, equal) { | ||
return a === b || (a.length === b.length && every(a, function (v, index) { | ||
return equal(v, b[index]); | ||
})); | ||
}, | ||
inspect: function (arr, inspect) { | ||
if (arr.length === 0) { | ||
return '[]'; | ||
} | ||
var inspectedItems = map(arr, function (v) { | ||
return inspect(v); | ||
}); | ||
var length = reduce(inspectedItems, function (result, v) { | ||
return result + v.length; | ||
}, 0); | ||
if (length > 50) { | ||
return '[\n ' + inspectedItems.join(',\n ') + '\n]'; | ||
} else { | ||
return '[ ' + inspectedItems.join(', ') + ' ]'; | ||
} | ||
}, | ||
toJSON: function (arr, toJSON) { | ||
return map(arr, toJSON); | ||
} | ||
}); | ||
expect.addType({ | ||
base: 'object', | ||
identify: function (value) { | ||
return utils.isError(value); | ||
}, | ||
equal: function (a, b, equal) { | ||
return a === b || | ||
(equal(a.message, b.message) && this.baseType.equal(a, b, equal)); | ||
}, | ||
inspect: function (value) { | ||
return '[' + Error.prototype.toString.call(value) + ']'; | ||
} | ||
}); | ||
expect.addType({ | ||
name: 'date', | ||
identify: function (obj) { | ||
@@ -1314,3 +1386,2 @@ return Object.prototype.toString.call(obj) === '[object Date]'; | ||
expect.addType({ | ||
name: 'function', | ||
identify: function (f) { | ||
@@ -1334,3 +1405,2 @@ return typeof f === 'function'; | ||
expect.addType({ | ||
name: 'regexp', | ||
identify: isRegExp, | ||
@@ -1350,12 +1420,2 @@ equal: function (a, b) { | ||
expect.addType({ | ||
name: 'DomElement', | ||
identify: function (value) { | ||
return utils.isDOMElement(value); | ||
}, | ||
inspect: function (value) { | ||
return utils.getOuterHTML(value); | ||
} | ||
}); | ||
function getHexDumpLinesForBufferLikeObject(obj, width, digitWidth) { | ||
@@ -1416,3 +1476,2 @@ digitWidth = digitWidth || 2; | ||
expect.addType({ | ||
name: 'Buffer', | ||
identify: Buffer.isBuffer, | ||
@@ -1433,3 +1492,2 @@ equal: bufferLikeObjectsEqual, | ||
expect.addType({ | ||
name: 'Uint8Array', | ||
identify: function (obj) { | ||
@@ -1453,3 +1511,2 @@ return obj && obj instanceof Uint8Array; | ||
expect.addType({ | ||
name: 'Uint16Array', | ||
identify: function (obj) { | ||
@@ -1469,47 +1526,2 @@ return obj && obj instanceof Uint16Array; | ||
} | ||
expect.addType({ | ||
base: 'primitive', | ||
name: 'string', | ||
identify: function (value) { | ||
return typeof value === 'string'; | ||
}, | ||
inspect: function (value) { | ||
return '\'' + json.stringify(value).replace(/^"|"$/g, '') | ||
.replace(/'/g, "\\'") | ||
.replace(/\\"/g, '"') + '\''; | ||
} | ||
}); | ||
expect.addType({ | ||
base: 'primitive', | ||
name: 'number', | ||
identify: function (value) { | ||
return typeof value === 'number'; | ||
} | ||
}); | ||
expect.addType({ | ||
base: 'primitive', | ||
name: 'boolean', | ||
identify: function (value) { | ||
return typeof value === 'boolean'; | ||
} | ||
}); | ||
expect.addType({ | ||
base: 'primitive', | ||
name: 'undefined', | ||
identify: function (value) { | ||
return typeof value === 'undefined'; | ||
} | ||
}); | ||
expect.addType({ | ||
base: 'primitive', | ||
name: 'null', | ||
identify: function (value) { | ||
return value === null; | ||
} | ||
}); | ||
}()); | ||
@@ -1516,0 +1528,0 @@ |
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
312422
6176