137 lines
3.4 KiB
JavaScript
137 lines
3.4 KiB
JavaScript
"use strict";
|
|
|
|
var valueToString = require("@sinonjs/commons").valueToString;
|
|
|
|
var deepEqual = require("./deep-equal").use(match); // eslint-disable-line no-use-before-define
|
|
var getClass = require("./get-class");
|
|
var isDate = require("./is-date");
|
|
var isSet = require("./is-set");
|
|
var isSubset = require("./is-subset");
|
|
var createMatcher = require("./matcher");
|
|
|
|
function arrayContains(array, subset, compare) {
|
|
if (subset.length === 0) {
|
|
return true;
|
|
}
|
|
var i, l, j, k;
|
|
for (i = 0, l = array.length; i < l; ++i) {
|
|
if (compare(array[i], subset[0])) {
|
|
for (j = 0, k = subset.length; j < k; ++j) {
|
|
if (i + j >= l) {
|
|
return false;
|
|
}
|
|
if (!compare(array[i + j], subset[j])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @name samsam.match
|
|
* @param Object object
|
|
* @param Object matcher
|
|
*
|
|
* Compare arbitrary value ``object`` with matcher.
|
|
*/
|
|
function match(object, matcher) {
|
|
if (matcher && typeof matcher.test === "function") {
|
|
return matcher.test(object);
|
|
}
|
|
|
|
if (typeof matcher === "function") {
|
|
return matcher(object) === true;
|
|
}
|
|
|
|
if (typeof matcher === "string") {
|
|
matcher = matcher.toLowerCase();
|
|
var notNull = typeof object === "string" || !!object;
|
|
return (
|
|
notNull &&
|
|
valueToString(object)
|
|
.toLowerCase()
|
|
.indexOf(matcher) >= 0
|
|
);
|
|
}
|
|
|
|
if (typeof matcher === "number") {
|
|
return matcher === object;
|
|
}
|
|
|
|
if (typeof matcher === "boolean") {
|
|
return matcher === object;
|
|
}
|
|
|
|
if (typeof matcher === "undefined") {
|
|
return typeof object === "undefined";
|
|
}
|
|
|
|
if (matcher === null) {
|
|
return object === null;
|
|
}
|
|
|
|
if (object === null) {
|
|
return false;
|
|
}
|
|
|
|
if (isSet(object)) {
|
|
return isSubset(matcher, object, match);
|
|
}
|
|
|
|
if (getClass(object) === "Array" && getClass(matcher) === "Array") {
|
|
return arrayContains(object, matcher, match);
|
|
}
|
|
|
|
if (isDate(matcher)) {
|
|
return isDate(object) && object.getTime() === matcher.getTime();
|
|
}
|
|
|
|
if (matcher && typeof matcher === "object") {
|
|
if (matcher === object) {
|
|
return true;
|
|
}
|
|
if (typeof object !== "object") {
|
|
return false;
|
|
}
|
|
var prop;
|
|
// eslint-disable-next-line guard-for-in
|
|
for (prop in matcher) {
|
|
var value = object[prop];
|
|
if (
|
|
typeof value === "undefined" &&
|
|
typeof object.getAttribute === "function"
|
|
) {
|
|
value = object.getAttribute(prop);
|
|
}
|
|
if (
|
|
matcher[prop] === null ||
|
|
typeof matcher[prop] === "undefined"
|
|
) {
|
|
if (value !== matcher[prop]) {
|
|
return false;
|
|
}
|
|
} else if (
|
|
typeof value === "undefined" ||
|
|
!deepEqual(value, matcher[prop])
|
|
) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
throw new Error(
|
|
"Matcher was not a string, a number, a " +
|
|
"function, a boolean or an object"
|
|
);
|
|
}
|
|
|
|
Object.keys(createMatcher).forEach(function(key) {
|
|
match[key] = createMatcher[key];
|
|
});
|
|
|
|
module.exports = match;
|