Last active
September 1, 2017 11:18
-
-
Save davidnormo/77918a46d40c4008de33 to your computer and use it in GitHub Desktop.
Deep equality jasmine 2.3 matcher
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var observableDiff = require("deep-diff").observableDiff, | |
lodash = require("lodash"); | |
function valueToString(target) { | |
return JSON.stringify(target, function(key, value) { | |
var type = Object.prototype.toString.call(value); | |
if (value instanceof jasmine.Any) { | |
return value.jasmineToString(); | |
} if (/Function/.test(type)) { | |
return "Function"; | |
} | |
return value; | |
}, 4); | |
} | |
function jasmineAnyInPath(actual, expected, path) { | |
var accumulatedPath = [], | |
expectedValue, | |
actualValue; | |
return lodash.some(path, function(step) { | |
accumulatedPath.push(step); | |
expectedValue = lodash.get(expected, accumulatedPath); | |
if (expectedValue instanceof jasmine.Any) { | |
actualValue = lodash.get(actual, accumulatedPath); | |
return expectedValue.asymmetricMatch(actualValue); | |
} | |
}); | |
} | |
/** | |
* Assert two objects are deep equal | |
* @param {Object} expected | |
* @return {Boolean} | |
*/ | |
var deepCompare = function(actual, expected) { | |
var result = [], | |
getPath, | |
getErrorMessage, | |
messages; | |
/** | |
* Return the string representation of an object path | |
* @param {Array} path | |
* @return {String} | |
*/ | |
getPath = function(path) { | |
return lodash.reduce(path, function(path, next) { | |
if (typeof next === "number") { | |
path += "[" + next + "]"; | |
} else if (path) { | |
path += "." + next; | |
} else { | |
path = next; | |
} | |
return path; | |
}, ""); | |
}; | |
getErrorMessage = function(error) { | |
switch (error.kind) { | |
// Indicates a newly added property/element | |
case "N": | |
return "Property has been added: " + | |
getPath(error.path) + | |
" (New value: " + valueToString(error.rhs) + ")"; | |
// Indicates a property/element was deleted | |
case "D": | |
return "Property has been deleted: " + | |
getPath(error.path) + | |
" (Actual value: " + valueToString(error.lhs) + ")"; | |
// Indicates a property/element was edited | |
case "E": | |
return "Property has been edited: " + | |
getPath(error.path) + | |
"\n\tActual:\t\t" + valueToString(error.lhs) + | |
"\n\tExpected:\t" + valueToString(error.rhs) + "\n"; | |
// Indicates a change occurred within an array | |
case "A": | |
var path = error.path || []; | |
path.push(error.index); | |
path = getPath(path) + " (" + getErrorMessage(error.item) + ")"; | |
return "Array has been changed: (path: " + path + ")"; | |
} | |
}; | |
observableDiff(actual, expected, function(diff) { | |
if (diff.kind === "E" && diff.rhs instanceof jasmine.Any) { | |
if (!diff.rhs.asymmetricMatch(diff.lhs)) { | |
result.push(diff); | |
} | |
} else if (!jasmineAnyInPath(actual, expected, diff.path)) { | |
result.push(diff); | |
} | |
}); | |
if (result.length === 0) { | |
return true; | |
} | |
// Loop through errors | |
messages = lodash.map(result, getErrorMessage); | |
return messages.join("\n"); | |
}; | |
module.exports = { | |
"toDeepEqual": function() { | |
return { | |
"compare": function(actual, expected) { | |
var result = deepCompare(actual, expected); | |
if (result === true) { | |
return { | |
"pass": true | |
}; | |
} | |
return { | |
"pass": false, | |
"message": "\n" + result | |
}; | |
} | |
}; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment