1432 lines
47 KiB
JavaScript
1432 lines
47 KiB
JavaScript
|
(function (global, factory) {
|
||
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@sinonjs/commons'), require('type-detect'), require('lodash.get')) :
|
||
|
typeof define === 'function' && define.amd ? define(['exports', '@sinonjs/commons', 'type-detect', 'lodash.get'], factory) :
|
||
|
(global = global || self, factory(global.samsam = {}, global.commons, global.typeDetect, global.lodash));
|
||
|
}(this, (function (exports, commons, typeDetect, lodash) { 'use strict';
|
||
|
|
||
|
commons = commons && commons.hasOwnProperty('default') ? commons['default'] : commons;
|
||
|
typeDetect = typeDetect && typeDetect.hasOwnProperty('default') ? typeDetect['default'] : typeDetect;
|
||
|
lodash = lodash && lodash.hasOwnProperty('default') ? lodash['default'] : lodash;
|
||
|
|
||
|
/**
|
||
|
* Compares a `value` to `NaN`
|
||
|
*
|
||
|
* @private
|
||
|
* @param {*} value A value to examine
|
||
|
* @returns {boolean} Returns `true` when `value` is `NaN`
|
||
|
*/
|
||
|
function isNaN(value) {
|
||
|
// Unlike global `isNaN`, this function avoids type coercion
|
||
|
// `typeof` check avoids IE host object issues, hat tip to
|
||
|
// lodash
|
||
|
|
||
|
// eslint-disable-next-line no-self-compare
|
||
|
return typeof value === "number" && value !== value;
|
||
|
}
|
||
|
|
||
|
var isNan = isNaN;
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when `value` is `-0`
|
||
|
*
|
||
|
* @alias module:samsam.isNegZero
|
||
|
* @param {*} value A value to examine
|
||
|
* @returns {boolean} Returns `true` when `value` is `-0`
|
||
|
*/
|
||
|
function isNegZero(value) {
|
||
|
return value === 0 && 1 / value === -Infinity;
|
||
|
}
|
||
|
|
||
|
var isNegZero_1 = isNegZero;
|
||
|
|
||
|
/**
|
||
|
* Strict equality check according to EcmaScript Harmony's `egal`.
|
||
|
*
|
||
|
* **From the Harmony wiki:**
|
||
|
* > An `egal` function simply makes available the internal `SameValue` function
|
||
|
* > from section 9.12 of the ES5 spec. If two values are egal, then they are not
|
||
|
* > observably distinguishable.
|
||
|
*
|
||
|
* `identical` returns `true` when `===` is `true`, except for `-0` and
|
||
|
* `+0`, where it returns `false`. Additionally, it returns `true` when
|
||
|
* `NaN` is compared to itself.
|
||
|
*
|
||
|
* @alias module:samsam.identical
|
||
|
* @param {*} obj1 The first value to compare
|
||
|
* @param {*} obj2 The second value to compare
|
||
|
* @returns {boolean} Returns `true` when the objects are *egal*, `false` otherwise
|
||
|
*/
|
||
|
function identical(obj1, obj2) {
|
||
|
if (obj1 === obj2 || (isNan(obj1) && isNan(obj2))) {
|
||
|
return obj1 !== 0 || isNegZero_1(obj1) === isNegZero_1(obj2);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
var identical_1 = identical;
|
||
|
|
||
|
var toString = commons.prototypes.object.toString;
|
||
|
|
||
|
/**
|
||
|
* Returns the internal `Class` by calling `Object.prototype.toString`
|
||
|
* with the provided value as `this`. Return value is a `String`, naming the
|
||
|
* internal class, e.g. "Array"
|
||
|
*
|
||
|
* @private
|
||
|
* @param {*} value - Any value
|
||
|
* @returns {string} - A string representation of the `Class` of `value`
|
||
|
*/
|
||
|
function getClass(value) {
|
||
|
return toString(value).split(/[ \]]/)[1];
|
||
|
}
|
||
|
|
||
|
var getClass_1 = getClass;
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when `object` is an `arguments` object, `false` otherwise
|
||
|
*
|
||
|
* @alias module:samsam.isArguments
|
||
|
* @param {*} object - The object to examine
|
||
|
* @returns {boolean} `true` when `object` is an `arguments` object
|
||
|
*/
|
||
|
function isArguments(object) {
|
||
|
return getClass_1(object) === "Arguments";
|
||
|
}
|
||
|
|
||
|
var isArguments_1 = isArguments;
|
||
|
|
||
|
var div = typeof document !== "undefined" && document.createElement("div");
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when `object` is a DOM element node.
|
||
|
*
|
||
|
* Unlike Underscore.js/lodash, this function will return `false` if `object`
|
||
|
* is an *element-like* object, i.e. a regular object with a `nodeType`
|
||
|
* property that holds the value `1`.
|
||
|
*
|
||
|
* @alias module:samsam.isElement
|
||
|
* @param {object} object The object to examine
|
||
|
* @returns {boolean} Returns `true` for DOM element nodes
|
||
|
*/
|
||
|
function isElement(object) {
|
||
|
if (!object || object.nodeType !== 1 || !div) {
|
||
|
return false;
|
||
|
}
|
||
|
try {
|
||
|
object.appendChild(div);
|
||
|
object.removeChild(div);
|
||
|
} catch (e) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
var isElement_1 = isElement;
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when the argument is an instance of Set, `false` otherwise
|
||
|
*
|
||
|
* @alias module:samsam.isSet
|
||
|
* @param {*} val - A value to examine
|
||
|
* @returns {boolean} Returns `true` when the argument is an instance of Set, `false` otherwise
|
||
|
*/
|
||
|
function isSet(val) {
|
||
|
return (typeof Set !== "undefined" && val instanceof Set) || false;
|
||
|
}
|
||
|
|
||
|
var isSet_1 = isSet;
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when `value` is a Map
|
||
|
*
|
||
|
* @param {*} value A value to examine
|
||
|
* @returns {boolean} `true` when `value` is an instance of `Map`, `false` otherwise
|
||
|
* @private
|
||
|
*/
|
||
|
function isMap(value) {
|
||
|
return typeof Map !== "undefined" && value instanceof Map;
|
||
|
}
|
||
|
|
||
|
var isMap_1 = isMap;
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when `value` is an instance of Date
|
||
|
*
|
||
|
* @private
|
||
|
* @param {Date} value The value to examine
|
||
|
* @returns {boolean} `true` when `value` is an instance of Date
|
||
|
*/
|
||
|
function isDate(value) {
|
||
|
return value instanceof Date;
|
||
|
}
|
||
|
|
||
|
var isDate_1 = isDate;
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when the value is a regular Object and not a specialized Object
|
||
|
*
|
||
|
* This helps speed up deepEqual cyclic checks
|
||
|
*
|
||
|
* The premise is that only Objects are stored in the visited array.
|
||
|
* So if this function returns false, we don't have to do the
|
||
|
* expensive operation of searching for the value in the the array of already
|
||
|
* visited objects
|
||
|
*
|
||
|
* @private
|
||
|
* @param {object} value The object to examine
|
||
|
* @returns {boolean} `true` when the object is a non-specialised object
|
||
|
*/
|
||
|
function isObject(value) {
|
||
|
return (
|
||
|
typeof value === "object" &&
|
||
|
value !== null &&
|
||
|
// none of these are collection objects, so we can return false
|
||
|
!(value instanceof Boolean) &&
|
||
|
!(value instanceof Date) &&
|
||
|
!(value instanceof Error) &&
|
||
|
!(value instanceof Number) &&
|
||
|
!(value instanceof RegExp) &&
|
||
|
!(value instanceof String)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
var isObject_1 = isObject;
|
||
|
|
||
|
var forEach = commons.prototypes.set.forEach;
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when `s1` is a subset of `s2`, `false` otherwise
|
||
|
*
|
||
|
* @private
|
||
|
* @param {Array|Set} s1 The target value
|
||
|
* @param {Array|Set} s2 The containing value
|
||
|
* @param {Function} compare A comparison function, should return `true` when
|
||
|
* values are considered equal
|
||
|
* @returns {boolean} Returns `true` when `s1` is a subset of `s2`, `false`` otherwise
|
||
|
*/
|
||
|
function isSubset(s1, s2, compare) {
|
||
|
var allContained = true;
|
||
|
forEach(s1, function(v1) {
|
||
|
var includes = false;
|
||
|
forEach(s2, function(v2) {
|
||
|
if (compare(v2, v1)) {
|
||
|
includes = true;
|
||
|
}
|
||
|
});
|
||
|
allContained = allContained && includes;
|
||
|
});
|
||
|
|
||
|
return allContained;
|
||
|
}
|
||
|
|
||
|
var isSubset_1 = isSubset;
|
||
|
|
||
|
var valueToString = commons.valueToString;
|
||
|
var className = commons.className;
|
||
|
var typeOf = commons.typeOf;
|
||
|
var arrayProto = commons.prototypes.array;
|
||
|
var objectProto = commons.prototypes.object;
|
||
|
var mapForEach = commons.prototypes.map.forEach;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
var concat = arrayProto.concat;
|
||
|
var every = arrayProto.every;
|
||
|
var push = arrayProto.push;
|
||
|
|
||
|
var getTime = Date.prototype.getTime;
|
||
|
var hasOwnProperty = objectProto.hasOwnProperty;
|
||
|
var indexOf = arrayProto.indexOf;
|
||
|
var keys = Object.keys;
|
||
|
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
||
|
|
||
|
/**
|
||
|
* Deep equal comparison. Two values are "deep equal" when:
|
||
|
*
|
||
|
* - They are equal, according to samsam.identical
|
||
|
* - They are both date objects representing the same time
|
||
|
* - They are both arrays containing elements that are all deepEqual
|
||
|
* - They are objects with the same set of properties, and each property
|
||
|
* in ``actual`` is deepEqual to the corresponding property in ``expectation``
|
||
|
*
|
||
|
* Supports cyclic objects.
|
||
|
*
|
||
|
* @alias module:samsam.deepEqual
|
||
|
* @param {*} actual The object to examine
|
||
|
* @param {*} expectation The object actual is expected to be equal to
|
||
|
* @param {object} match A value to match on
|
||
|
* @returns {boolean} Returns true when actual and expectation are considered equal
|
||
|
*/
|
||
|
function deepEqualCyclic(actual, expectation, match) {
|
||
|
// used for cyclic comparison
|
||
|
// contain already visited objects
|
||
|
var actualObjects = [];
|
||
|
var expectationObjects = [];
|
||
|
// contain pathes (position in the object structure)
|
||
|
// of the already visited objects
|
||
|
// indexes same as in objects arrays
|
||
|
var actualPaths = [];
|
||
|
var expectationPaths = [];
|
||
|
// contains combinations of already compared objects
|
||
|
// in the manner: { "$1['ref']$2['ref']": true }
|
||
|
var compared = {};
|
||
|
|
||
|
// does the recursion for the deep equal check
|
||
|
// eslint-disable-next-line complexity
|
||
|
return (function deepEqual(
|
||
|
actualObj,
|
||
|
expectationObj,
|
||
|
actualPath,
|
||
|
expectationPath
|
||
|
) {
|
||
|
// If both are matchers they must be the same instance in order to be
|
||
|
// considered equal If we didn't do that we would end up running one
|
||
|
// matcher against the other
|
||
|
if (match && match.isMatcher(expectationObj)) {
|
||
|
if (match.isMatcher(actualObj)) {
|
||
|
return actualObj === expectationObj;
|
||
|
}
|
||
|
return expectationObj.test(actualObj);
|
||
|
}
|
||
|
|
||
|
var actualType = typeof actualObj;
|
||
|
var expectationType = typeof expectationObj;
|
||
|
|
||
|
if (
|
||
|
actualObj === expectationObj ||
|
||
|
isNan(actualObj) ||
|
||
|
isNan(expectationObj) ||
|
||
|
actualObj === null ||
|
||
|
expectationObj === null ||
|
||
|
actualObj === undefined ||
|
||
|
expectationObj === undefined ||
|
||
|
actualType !== "object" ||
|
||
|
expectationType !== "object"
|
||
|
) {
|
||
|
return identical_1(actualObj, expectationObj);
|
||
|
}
|
||
|
|
||
|
// Elements are only equal if identical(expected, actual)
|
||
|
if (isElement_1(actualObj) || isElement_1(expectationObj)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
var isActualDate = isDate_1(actualObj);
|
||
|
var isExpectationDate = isDate_1(expectationObj);
|
||
|
if (isActualDate || isExpectationDate) {
|
||
|
if (
|
||
|
!isActualDate ||
|
||
|
!isExpectationDate ||
|
||
|
getTime.call(actualObj) !== getTime.call(expectationObj)
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (actualObj instanceof RegExp && expectationObj instanceof RegExp) {
|
||
|
if (valueToString(actualObj) !== valueToString(expectationObj)) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (actualObj instanceof Error && expectationObj instanceof Error) {
|
||
|
return actualObj === expectationObj;
|
||
|
}
|
||
|
|
||
|
var actualClass = getClass_1(actualObj);
|
||
|
var expectationClass = getClass_1(expectationObj);
|
||
|
var actualKeys = keys(actualObj);
|
||
|
var expectationKeys = keys(expectationObj);
|
||
|
var actualName = className(actualObj);
|
||
|
var expectationName = className(expectationObj);
|
||
|
var expectationSymbols =
|
||
|
typeOf(getOwnPropertySymbols) === "function"
|
||
|
? getOwnPropertySymbols(expectationObj)
|
||
|
: /* istanbul ignore next: cannot collect coverage for engine that doesn't support Symbol */
|
||
|
[];
|
||
|
var expectationKeysAndSymbols = concat(
|
||
|
expectationKeys,
|
||
|
expectationSymbols
|
||
|
);
|
||
|
|
||
|
if (isArguments_1(actualObj) || isArguments_1(expectationObj)) {
|
||
|
if (actualObj.length !== expectationObj.length) {
|
||
|
return false;
|
||
|
}
|
||
|
} else {
|
||
|
if (
|
||
|
actualType !== expectationType ||
|
||
|
actualClass !== expectationClass ||
|
||
|
actualKeys.length !== expectationKeys.length ||
|
||
|
(actualName &&
|
||
|
expectationName &&
|
||
|
actualName !== expectationName)
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (isSet_1(actualObj) || isSet_1(expectationObj)) {
|
||
|
if (
|
||
|
!isSet_1(actualObj) ||
|
||
|
!isSet_1(expectationObj) ||
|
||
|
actualObj.size !== expectationObj.size
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return isSubset_1(actualObj, expectationObj, deepEqual);
|
||
|
}
|
||
|
|
||
|
if (isMap_1(actualObj) || isMap_1(expectationObj)) {
|
||
|
if (
|
||
|
!isMap_1(actualObj) ||
|
||
|
!isMap_1(expectationObj) ||
|
||
|
actualObj.size !== expectationObj.size
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
var mapsDeeplyEqual = true;
|
||
|
mapForEach(actualObj, function(value, key) {
|
||
|
mapsDeeplyEqual =
|
||
|
mapsDeeplyEqual &&
|
||
|
deepEqualCyclic(value, expectationObj.get(key));
|
||
|
});
|
||
|
|
||
|
return mapsDeeplyEqual;
|
||
|
}
|
||
|
|
||
|
return every(expectationKeysAndSymbols, function(key) {
|
||
|
if (!hasOwnProperty(actualObj, key)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
var actualValue = actualObj[key];
|
||
|
var expectationValue = expectationObj[key];
|
||
|
var actualObject = isObject_1(actualValue);
|
||
|
var expectationObject = isObject_1(expectationValue);
|
||
|
// determines, if the objects were already visited
|
||
|
// (it's faster to check for isObject first, than to
|
||
|
// get -1 from getIndex for non objects)
|
||
|
var actualIndex = actualObject
|
||
|
? indexOf(actualObjects, actualValue)
|
||
|
: -1;
|
||
|
var expectationIndex = expectationObject
|
||
|
? indexOf(expectationObjects, expectationValue)
|
||
|
: -1;
|
||
|
// determines the new paths of the objects
|
||
|
// - for non cyclic objects the current path will be extended
|
||
|
// by current property name
|
||
|
// - for cyclic objects the stored path is taken
|
||
|
var newActualPath =
|
||
|
actualIndex !== -1
|
||
|
? actualPaths[actualIndex]
|
||
|
: actualPath + "[" + JSON.stringify(key) + "]";
|
||
|
var newExpectationPath =
|
||
|
expectationIndex !== -1
|
||
|
? expectationPaths[expectationIndex]
|
||
|
: expectationPath + "[" + JSON.stringify(key) + "]";
|
||
|
var combinedPath = newActualPath + newExpectationPath;
|
||
|
|
||
|
// stop recursion if current objects are already compared
|
||
|
if (compared[combinedPath]) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// remember the current objects and their paths
|
||
|
if (actualIndex === -1 && actualObject) {
|
||
|
push(actualObjects, actualValue);
|
||
|
push(actualPaths, newActualPath);
|
||
|
}
|
||
|
if (expectationIndex === -1 && expectationObject) {
|
||
|
push(expectationObjects, expectationValue);
|
||
|
push(expectationPaths, newExpectationPath);
|
||
|
}
|
||
|
|
||
|
// remember that the current objects are already compared
|
||
|
if (actualObject && expectationObject) {
|
||
|
compared[combinedPath] = true;
|
||
|
}
|
||
|
|
||
|
// End of cyclic logic
|
||
|
|
||
|
// neither actualValue nor expectationValue is a cycle
|
||
|
// continue with next level
|
||
|
return deepEqual(
|
||
|
actualValue,
|
||
|
expectationValue,
|
||
|
newActualPath,
|
||
|
newExpectationPath
|
||
|
);
|
||
|
});
|
||
|
})(actual, expectation, "$1", "$2");
|
||
|
}
|
||
|
|
||
|
deepEqualCyclic.use = function(match) {
|
||
|
return function deepEqual(a, b) {
|
||
|
return deepEqualCyclic(a, b, match);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
var deepEqual = deepEqualCyclic;
|
||
|
|
||
|
var ARRAY_TYPES = [
|
||
|
Array,
|
||
|
Int8Array,
|
||
|
Uint8Array,
|
||
|
Uint8ClampedArray,
|
||
|
Int16Array,
|
||
|
Uint16Array,
|
||
|
Int32Array,
|
||
|
Uint32Array,
|
||
|
Float32Array,
|
||
|
Float64Array
|
||
|
];
|
||
|
|
||
|
var arrayTypes = ARRAY_TYPES;
|
||
|
|
||
|
var functionName = commons.functionName;
|
||
|
var indexOf$1 = commons.prototypes.array.indexOf;
|
||
|
var map = commons.prototypes.array.map;
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when `object` is an array type, `false` otherwise
|
||
|
*
|
||
|
* @param {*} object - The object to examine
|
||
|
* @returns {boolean} `true` when `object` is an array type
|
||
|
* @private
|
||
|
*/
|
||
|
function isArrayType(object) {
|
||
|
return indexOf$1(map(arrayTypes, functionName), typeDetect(object)) !== -1;
|
||
|
}
|
||
|
|
||
|
var isArrayType_1 = isArrayType;
|
||
|
|
||
|
var slice = commons.prototypes.string.slice;
|
||
|
var typeOf$1 = commons.typeOf;
|
||
|
var valueToString$1 = commons.valueToString;
|
||
|
|
||
|
/**
|
||
|
* Creates a string represenation of an iterable object
|
||
|
*
|
||
|
* @private
|
||
|
* @param {object} obj The iterable object to stringify
|
||
|
* @returns {string} A string representation
|
||
|
*/
|
||
|
function iterableToString(obj) {
|
||
|
if (typeOf$1(obj) === "map") {
|
||
|
return mapToString(obj);
|
||
|
}
|
||
|
|
||
|
return genericIterableToString(obj);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a string representation of a Map
|
||
|
*
|
||
|
* @private
|
||
|
* @param {Map} map The map to stringify
|
||
|
* @returns {string} A string representation
|
||
|
*/
|
||
|
function mapToString(map) {
|
||
|
var representation = "";
|
||
|
|
||
|
/* eslint-disable-next-line local-rules/no-prototype-methods */
|
||
|
map.forEach(function(value, key) {
|
||
|
representation += "[" + stringify(key) + "," + stringify(value) + "],";
|
||
|
});
|
||
|
|
||
|
representation = slice(representation, 0, -1);
|
||
|
return representation;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Create a string represenation for an iterable
|
||
|
*
|
||
|
* @private
|
||
|
* @param {object} iterable The iterable to stringify
|
||
|
* @returns {string} A string representation
|
||
|
*/
|
||
|
function genericIterableToString(iterable) {
|
||
|
var representation = "";
|
||
|
|
||
|
/* eslint-disable-next-line local-rules/no-prototype-methods */
|
||
|
iterable.forEach(function(value) {
|
||
|
representation += stringify(value) + ",";
|
||
|
});
|
||
|
|
||
|
representation = slice(representation, 0, -1);
|
||
|
return representation;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a string representation of the passed `item`
|
||
|
*
|
||
|
* @private
|
||
|
* @param {object} item The item to stringify
|
||
|
* @returns {string} A string representation of `item`
|
||
|
*/
|
||
|
function stringify(item) {
|
||
|
return typeof item === "string" ? "'" + item + "'" : valueToString$1(item);
|
||
|
}
|
||
|
|
||
|
var iterableToString_1 = iterableToString;
|
||
|
|
||
|
var matcherPrototype = {
|
||
|
toString: function() {
|
||
|
return this.message;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
matcherPrototype.or = function(valueOrMatcher) {
|
||
|
var createMatcher = createMatcher_1;
|
||
|
var isMatcher = createMatcher.isMatcher;
|
||
|
|
||
|
if (!arguments.length) {
|
||
|
throw new TypeError("Matcher expected");
|
||
|
}
|
||
|
|
||
|
var m2 = isMatcher(valueOrMatcher)
|
||
|
? valueOrMatcher
|
||
|
: createMatcher(valueOrMatcher);
|
||
|
var m1 = this;
|
||
|
var or = Object.create(matcherPrototype);
|
||
|
or.test = function(actual) {
|
||
|
return m1.test(actual) || m2.test(actual);
|
||
|
};
|
||
|
or.message = m1.message + ".or(" + m2.message + ")";
|
||
|
return or;
|
||
|
};
|
||
|
|
||
|
matcherPrototype.and = function(valueOrMatcher) {
|
||
|
var createMatcher = createMatcher_1;
|
||
|
var isMatcher = createMatcher.isMatcher;
|
||
|
|
||
|
if (!arguments.length) {
|
||
|
throw new TypeError("Matcher expected");
|
||
|
}
|
||
|
|
||
|
var m2 = isMatcher(valueOrMatcher)
|
||
|
? valueOrMatcher
|
||
|
: createMatcher(valueOrMatcher);
|
||
|
var m1 = this;
|
||
|
var and = Object.create(matcherPrototype);
|
||
|
and.test = function(actual) {
|
||
|
return m1.test(actual) && m2.test(actual);
|
||
|
};
|
||
|
and.message = m1.message + ".and(" + m2.message + ")";
|
||
|
return and;
|
||
|
};
|
||
|
|
||
|
var matcherPrototype_1 = matcherPrototype;
|
||
|
|
||
|
var isPrototypeOf = commons.prototypes.object.isPrototypeOf;
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Returns `true` when `object` is a matcher
|
||
|
*
|
||
|
* @private
|
||
|
* @param {*} object A value to examine
|
||
|
* @returns {boolean} Returns `true` when `object` is a matcher
|
||
|
*/
|
||
|
function isMatcher(object) {
|
||
|
return isPrototypeOf(matcherPrototype_1, object);
|
||
|
}
|
||
|
|
||
|
var isMatcher_1 = isMatcher;
|
||
|
|
||
|
/**
|
||
|
* Throws a TypeError when `value` is not a matcher
|
||
|
*
|
||
|
* @private
|
||
|
* @param {*} value The value to examine
|
||
|
*/
|
||
|
function assertMatcher(value) {
|
||
|
if (!isMatcher_1(value)) {
|
||
|
throw new TypeError("Matcher expected");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var assertMatcher_1 = assertMatcher;
|
||
|
|
||
|
/**
|
||
|
* Throws a TypeError when expected method doesn't exist
|
||
|
*
|
||
|
* @private
|
||
|
* @param {*} value A value to examine
|
||
|
* @param {string} method The name of the method to look for
|
||
|
* @param {name} name A name to use for the error message
|
||
|
* @param {string} methodPath The name of the method to use for error messages
|
||
|
* @throws {TypeError} When the method doesn't exist
|
||
|
*/
|
||
|
function assertMethodExists(value, method, name, methodPath) {
|
||
|
if (value[method] === null || value[method] === undefined) {
|
||
|
throw new TypeError(
|
||
|
"Expected " + name + " to have method " + methodPath
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var assertMethodExists_1 = assertMethodExists;
|
||
|
|
||
|
var typeOf$2 = commons.typeOf;
|
||
|
|
||
|
/**
|
||
|
* Ensures that value is of type
|
||
|
*
|
||
|
* @private
|
||
|
* @param {*} value A value to examine
|
||
|
* @param {string} type A basic JavaScript type to compare to, e.g. "object", "string"
|
||
|
* @param {string} name A string to use for the error message
|
||
|
* @throws {TypeError} If value is not of the expected type
|
||
|
* @returns {undefined}
|
||
|
*/
|
||
|
function assertType(value, type, name) {
|
||
|
var actual = typeOf$2(value);
|
||
|
if (actual !== type) {
|
||
|
throw new TypeError(
|
||
|
"Expected type of " +
|
||
|
name +
|
||
|
" to be " +
|
||
|
type +
|
||
|
", but was " +
|
||
|
actual
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var assertType_1 = assertType;
|
||
|
|
||
|
var typeOf$3 = commons.typeOf;
|
||
|
|
||
|
/**
|
||
|
* Returns `true` for iterables
|
||
|
*
|
||
|
* @private
|
||
|
* @param {*} value A value to examine
|
||
|
* @returns {boolean} Returns `true` when `value` looks like an iterable
|
||
|
*/
|
||
|
function isIterable(value) {
|
||
|
return Boolean(value) && typeOf$3(value.forEach) === "function";
|
||
|
}
|
||
|
|
||
|
var isIterable_1 = isIterable;
|
||
|
|
||
|
var every$1 = commons.prototypes.array.every;
|
||
|
var concat$1 = commons.prototypes.array.concat;
|
||
|
var typeOf$4 = commons.typeOf;
|
||
|
|
||
|
var deepEqualFactory = deepEqual.use;
|
||
|
|
||
|
|
||
|
|
||
|
var keys$1 = Object.keys;
|
||
|
var getOwnPropertySymbols$1 = Object.getOwnPropertySymbols;
|
||
|
|
||
|
/**
|
||
|
* Matches `actual` with `expectation`
|
||
|
*
|
||
|
* @private
|
||
|
* @param {*} actual A value to examine
|
||
|
* @param {object} expectation An object with properties to match on
|
||
|
* @param {object} matcher A matcher to use for comparison
|
||
|
* @returns {boolean} Returns true when `actual` matches all properties in `expectation`
|
||
|
*/
|
||
|
function matchObject(actual, expectation, matcher) {
|
||
|
var deepEqual = deepEqualFactory(matcher);
|
||
|
if (actual === null || actual === undefined) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
var expectedKeys = keys$1(expectation);
|
||
|
/* istanbul ignore else: cannot collect coverage for engine that doesn't support Symbol */
|
||
|
if (typeOf$4(getOwnPropertySymbols$1) === "function") {
|
||
|
expectedKeys = concat$1(expectedKeys, getOwnPropertySymbols$1(expectation));
|
||
|
}
|
||
|
|
||
|
return every$1(expectedKeys, function(key) {
|
||
|
var exp = expectation[key];
|
||
|
var act = actual[key];
|
||
|
|
||
|
if (isMatcher_1(exp)) {
|
||
|
if (!exp.test(act)) {
|
||
|
return false;
|
||
|
}
|
||
|
} else if (typeOf$4(exp) === "object") {
|
||
|
if (!matchObject(act, exp, matcher)) {
|
||
|
return false;
|
||
|
}
|
||
|
} else if (!deepEqual(act, exp)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
var matchObject_1 = matchObject;
|
||
|
|
||
|
var functionName$1 = commons.functionName;
|
||
|
var join = commons.prototypes.array.join;
|
||
|
var map$1 = commons.prototypes.array.map;
|
||
|
var stringIndexOf = commons.prototypes.string.indexOf;
|
||
|
var valueToString$2 = commons.valueToString;
|
||
|
|
||
|
|
||
|
|
||
|
var createTypeMap = function(match) {
|
||
|
return {
|
||
|
function: function(m, expectation, message) {
|
||
|
m.test = expectation;
|
||
|
m.message = message || "match(" + functionName$1(expectation) + ")";
|
||
|
},
|
||
|
number: function(m, expectation) {
|
||
|
m.test = function(actual) {
|
||
|
// we need type coercion here
|
||
|
return expectation == actual; // eslint-disable-line eqeqeq
|
||
|
};
|
||
|
},
|
||
|
object: function(m, expectation) {
|
||
|
var array = [];
|
||
|
|
||
|
if (typeof expectation.test === "function") {
|
||
|
m.test = function(actual) {
|
||
|
return expectation.test(actual) === true;
|
||
|
};
|
||
|
m.message = "match(" + functionName$1(expectation.test) + ")";
|
||
|
return m;
|
||
|
}
|
||
|
|
||
|
array = map$1(Object.keys(expectation), function(key) {
|
||
|
return key + ": " + valueToString$2(expectation[key]);
|
||
|
});
|
||
|
|
||
|
m.test = function(actual) {
|
||
|
return matchObject_1(actual, expectation, match);
|
||
|
};
|
||
|
m.message = "match(" + join(array, ", ") + ")";
|
||
|
|
||
|
return m;
|
||
|
},
|
||
|
regexp: function(m, expectation) {
|
||
|
m.test = function(actual) {
|
||
|
return typeof actual === "string" && expectation.test(actual);
|
||
|
};
|
||
|
},
|
||
|
string: function(m, expectation) {
|
||
|
m.test = function(actual) {
|
||
|
return (
|
||
|
typeof actual === "string" &&
|
||
|
stringIndexOf(actual, expectation) !== -1
|
||
|
);
|
||
|
};
|
||
|
m.message = 'match("' + expectation + '")';
|
||
|
}
|
||
|
};
|
||
|
};
|
||
|
|
||
|
var typeMap = createTypeMap;
|
||
|
|
||
|
var arrayProto$1 = commons.prototypes.array;
|
||
|
var deepEqual$1 = deepEqual.use(createMatcher); // eslint-disable-line no-use-before-define
|
||
|
var every$2 = commons.every;
|
||
|
var functionName$2 = commons.functionName;
|
||
|
|
||
|
|
||
|
var objectProto$1 = commons.prototypes.object;
|
||
|
var typeOf$5 = commons.typeOf;
|
||
|
var valueToString$3 = commons.valueToString;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
var arrayIndexOf = arrayProto$1.indexOf;
|
||
|
var some = arrayProto$1.some;
|
||
|
|
||
|
var hasOwnProperty$1 = objectProto$1.hasOwnProperty;
|
||
|
var objectToString = objectProto$1.toString;
|
||
|
|
||
|
var TYPE_MAP = typeMap(createMatcher); // eslint-disable-line no-use-before-define
|
||
|
|
||
|
/**
|
||
|
* Creates a matcher object for the passed expectation
|
||
|
*
|
||
|
* @alias module:samsam.createMatcher
|
||
|
* @param {*} expectation An expecttation
|
||
|
* @param {string} message A message for the expectation
|
||
|
* @returns {object} A matcher object
|
||
|
*/
|
||
|
function createMatcher(expectation, message) {
|
||
|
var m = Object.create(matcherPrototype_1);
|
||
|
var type = typeOf$5(expectation);
|
||
|
|
||
|
if (message !== undefined && typeof message !== "string") {
|
||
|
throw new TypeError("Message should be a string");
|
||
|
}
|
||
|
|
||
|
if (arguments.length > 2) {
|
||
|
throw new TypeError(
|
||
|
"Expected 1 or 2 arguments, received " + arguments.length
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (type in TYPE_MAP) {
|
||
|
TYPE_MAP[type](m, expectation, message);
|
||
|
} else {
|
||
|
m.test = function(actual) {
|
||
|
return deepEqual$1(actual, expectation);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (!m.message) {
|
||
|
m.message = "match(" + valueToString$3(expectation) + ")";
|
||
|
}
|
||
|
|
||
|
return m;
|
||
|
}
|
||
|
|
||
|
createMatcher.isMatcher = isMatcher_1;
|
||
|
|
||
|
createMatcher.any = createMatcher(function() {
|
||
|
return true;
|
||
|
}, "any");
|
||
|
|
||
|
createMatcher.defined = createMatcher(function(actual) {
|
||
|
return actual !== null && actual !== undefined;
|
||
|
}, "defined");
|
||
|
|
||
|
createMatcher.truthy = createMatcher(function(actual) {
|
||
|
return Boolean(actual);
|
||
|
}, "truthy");
|
||
|
|
||
|
createMatcher.falsy = createMatcher(function(actual) {
|
||
|
return !actual;
|
||
|
}, "falsy");
|
||
|
|
||
|
createMatcher.same = function(expectation) {
|
||
|
return createMatcher(function(actual) {
|
||
|
return expectation === actual;
|
||
|
}, "same(" + valueToString$3(expectation) + ")");
|
||
|
};
|
||
|
|
||
|
createMatcher.in = function(arrayOfExpectations) {
|
||
|
if (typeOf$5(arrayOfExpectations) !== "array") {
|
||
|
throw new TypeError("array expected");
|
||
|
}
|
||
|
|
||
|
return createMatcher(function(actual) {
|
||
|
return some(arrayOfExpectations, function(expectation) {
|
||
|
return expectation === actual;
|
||
|
});
|
||
|
}, "in(" + valueToString$3(arrayOfExpectations) + ")");
|
||
|
};
|
||
|
|
||
|
createMatcher.typeOf = function(type) {
|
||
|
assertType_1(type, "string", "type");
|
||
|
return createMatcher(function(actual) {
|
||
|
return typeOf$5(actual) === type;
|
||
|
}, 'typeOf("' + type + '")');
|
||
|
};
|
||
|
|
||
|
createMatcher.instanceOf = function(type) {
|
||
|
/* istanbul ignore if */
|
||
|
if (
|
||
|
typeof Symbol === "undefined" ||
|
||
|
typeof Symbol.hasInstance === "undefined"
|
||
|
) {
|
||
|
assertType_1(type, "function", "type");
|
||
|
} else {
|
||
|
assertMethodExists_1(
|
||
|
type,
|
||
|
Symbol.hasInstance,
|
||
|
"type",
|
||
|
"[Symbol.hasInstance]"
|
||
|
);
|
||
|
}
|
||
|
return createMatcher(function(actual) {
|
||
|
return actual instanceof type;
|
||
|
}, "instanceOf(" + (functionName$2(type) || objectToString(type)) + ")");
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Creates a property matcher
|
||
|
*
|
||
|
* @private
|
||
|
* @param {Function} propertyTest A function to test the property against a value
|
||
|
* @param {string} messagePrefix A prefix to use for messages generated by the matcher
|
||
|
* @returns {object} A matcher
|
||
|
*/
|
||
|
function createPropertyMatcher(propertyTest, messagePrefix) {
|
||
|
return function(property, value) {
|
||
|
assertType_1(property, "string", "property");
|
||
|
var onlyProperty = arguments.length === 1;
|
||
|
var message = messagePrefix + '("' + property + '"';
|
||
|
if (!onlyProperty) {
|
||
|
message += ", " + valueToString$3(value);
|
||
|
}
|
||
|
message += ")";
|
||
|
return createMatcher(function(actual) {
|
||
|
if (
|
||
|
actual === undefined ||
|
||
|
actual === null ||
|
||
|
!propertyTest(actual, property)
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
return onlyProperty || deepEqual$1(actual[property], value);
|
||
|
}, message);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
createMatcher.has = createPropertyMatcher(function(actual, property) {
|
||
|
if (typeof actual === "object") {
|
||
|
return property in actual;
|
||
|
}
|
||
|
return actual[property] !== undefined;
|
||
|
}, "has");
|
||
|
|
||
|
createMatcher.hasOwn = createPropertyMatcher(function(actual, property) {
|
||
|
return hasOwnProperty$1(actual, property);
|
||
|
}, "hasOwn");
|
||
|
|
||
|
createMatcher.hasNested = function(property, value) {
|
||
|
assertType_1(property, "string", "property");
|
||
|
var onlyProperty = arguments.length === 1;
|
||
|
var message = 'hasNested("' + property + '"';
|
||
|
if (!onlyProperty) {
|
||
|
message += ", " + valueToString$3(value);
|
||
|
}
|
||
|
message += ")";
|
||
|
return createMatcher(function(actual) {
|
||
|
if (
|
||
|
actual === undefined ||
|
||
|
actual === null ||
|
||
|
lodash(actual, property) === undefined
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
return onlyProperty || deepEqual$1(lodash(actual, property), value);
|
||
|
}, message);
|
||
|
};
|
||
|
|
||
|
var jsonParseResultTypes = {
|
||
|
null: true,
|
||
|
boolean: true,
|
||
|
number: true,
|
||
|
string: true,
|
||
|
object: true,
|
||
|
array: true
|
||
|
};
|
||
|
createMatcher.json = function(value) {
|
||
|
if (!jsonParseResultTypes[typeOf$5(value)]) {
|
||
|
throw new TypeError("Value cannot be the result of JSON.parse");
|
||
|
}
|
||
|
var message = "json(" + JSON.stringify(value, null, " ") + ")";
|
||
|
return createMatcher(function(actual) {
|
||
|
var parsed;
|
||
|
try {
|
||
|
parsed = JSON.parse(actual);
|
||
|
} catch (e) {
|
||
|
return false;
|
||
|
}
|
||
|
return deepEqual$1(parsed, value);
|
||
|
}, message);
|
||
|
};
|
||
|
|
||
|
createMatcher.every = function(predicate) {
|
||
|
assertMatcher_1(predicate);
|
||
|
|
||
|
return createMatcher(function(actual) {
|
||
|
if (typeOf$5(actual) === "object") {
|
||
|
return every$2(Object.keys(actual), function(key) {
|
||
|
return predicate.test(actual[key]);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
isIterable_1(actual) &&
|
||
|
every$2(actual, function(element) {
|
||
|
return predicate.test(element);
|
||
|
})
|
||
|
);
|
||
|
}, "every(" + predicate.message + ")");
|
||
|
};
|
||
|
|
||
|
createMatcher.some = function(predicate) {
|
||
|
assertMatcher_1(predicate);
|
||
|
|
||
|
return createMatcher(function(actual) {
|
||
|
if (typeOf$5(actual) === "object") {
|
||
|
return !every$2(Object.keys(actual), function(key) {
|
||
|
return !predicate.test(actual[key]);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
isIterable_1(actual) &&
|
||
|
!every$2(actual, function(element) {
|
||
|
return !predicate.test(element);
|
||
|
})
|
||
|
);
|
||
|
}, "some(" + predicate.message + ")");
|
||
|
};
|
||
|
|
||
|
createMatcher.array = createMatcher.typeOf("array");
|
||
|
|
||
|
createMatcher.array.deepEquals = function(expectation) {
|
||
|
return createMatcher(function(actual) {
|
||
|
// Comparing lengths is the fastest way to spot a difference before iterating through every item
|
||
|
var sameLength = actual.length === expectation.length;
|
||
|
return (
|
||
|
typeOf$5(actual) === "array" &&
|
||
|
sameLength &&
|
||
|
every$2(actual, function(element, index) {
|
||
|
var expected = expectation[index];
|
||
|
return typeOf$5(expected) === "array" &&
|
||
|
typeOf$5(element) === "array"
|
||
|
? createMatcher.array.deepEquals(expected).test(element)
|
||
|
: deepEqual$1(expected, element);
|
||
|
})
|
||
|
);
|
||
|
}, "deepEquals([" + iterableToString_1(expectation) + "])");
|
||
|
};
|
||
|
|
||
|
createMatcher.array.startsWith = function(expectation) {
|
||
|
return createMatcher(function(actual) {
|
||
|
return (
|
||
|
typeOf$5(actual) === "array" &&
|
||
|
every$2(expectation, function(expectedElement, index) {
|
||
|
return actual[index] === expectedElement;
|
||
|
})
|
||
|
);
|
||
|
}, "startsWith([" + iterableToString_1(expectation) + "])");
|
||
|
};
|
||
|
|
||
|
createMatcher.array.endsWith = function(expectation) {
|
||
|
return createMatcher(function(actual) {
|
||
|
// This indicates the index in which we should start matching
|
||
|
var offset = actual.length - expectation.length;
|
||
|
|
||
|
return (
|
||
|
typeOf$5(actual) === "array" &&
|
||
|
every$2(expectation, function(expectedElement, index) {
|
||
|
return actual[offset + index] === expectedElement;
|
||
|
})
|
||
|
);
|
||
|
}, "endsWith([" + iterableToString_1(expectation) + "])");
|
||
|
};
|
||
|
|
||
|
createMatcher.array.contains = function(expectation) {
|
||
|
return createMatcher(function(actual) {
|
||
|
return (
|
||
|
typeOf$5(actual) === "array" &&
|
||
|
every$2(expectation, function(expectedElement) {
|
||
|
return arrayIndexOf(actual, expectedElement) !== -1;
|
||
|
})
|
||
|
);
|
||
|
}, "contains([" + iterableToString_1(expectation) + "])");
|
||
|
};
|
||
|
|
||
|
createMatcher.map = createMatcher.typeOf("map");
|
||
|
|
||
|
createMatcher.map.deepEquals = function mapDeepEquals(expectation) {
|
||
|
return createMatcher(function(actual) {
|
||
|
// Comparing lengths is the fastest way to spot a difference before iterating through every item
|
||
|
var sameLength = actual.size === expectation.size;
|
||
|
return (
|
||
|
typeOf$5(actual) === "map" &&
|
||
|
sameLength &&
|
||
|
every$2(actual, function(element, key) {
|
||
|
return expectation.has(key) && expectation.get(key) === element;
|
||
|
})
|
||
|
);
|
||
|
}, "deepEquals(Map[" + iterableToString_1(expectation) + "])");
|
||
|
};
|
||
|
|
||
|
createMatcher.map.contains = function mapContains(expectation) {
|
||
|
return createMatcher(function(actual) {
|
||
|
return (
|
||
|
typeOf$5(actual) === "map" &&
|
||
|
every$2(expectation, function(element, key) {
|
||
|
return actual.has(key) && actual.get(key) === element;
|
||
|
})
|
||
|
);
|
||
|
}, "contains(Map[" + iterableToString_1(expectation) + "])");
|
||
|
};
|
||
|
|
||
|
createMatcher.set = createMatcher.typeOf("set");
|
||
|
|
||
|
createMatcher.set.deepEquals = function setDeepEquals(expectation) {
|
||
|
return createMatcher(function(actual) {
|
||
|
// Comparing lengths is the fastest way to spot a difference before iterating through every item
|
||
|
var sameLength = actual.size === expectation.size;
|
||
|
return (
|
||
|
typeOf$5(actual) === "set" &&
|
||
|
sameLength &&
|
||
|
every$2(actual, function(element) {
|
||
|
return expectation.has(element);
|
||
|
})
|
||
|
);
|
||
|
}, "deepEquals(Set[" + iterableToString_1(expectation) + "])");
|
||
|
};
|
||
|
|
||
|
createMatcher.set.contains = function setContains(expectation) {
|
||
|
return createMatcher(function(actual) {
|
||
|
return (
|
||
|
typeOf$5(actual) === "set" &&
|
||
|
every$2(expectation, function(element) {
|
||
|
return actual.has(element);
|
||
|
})
|
||
|
);
|
||
|
}, "contains(Set[" + iterableToString_1(expectation) + "])");
|
||
|
};
|
||
|
|
||
|
createMatcher.bool = createMatcher.typeOf("boolean");
|
||
|
createMatcher.number = createMatcher.typeOf("number");
|
||
|
createMatcher.string = createMatcher.typeOf("string");
|
||
|
createMatcher.object = createMatcher.typeOf("object");
|
||
|
createMatcher.func = createMatcher.typeOf("function");
|
||
|
createMatcher.regexp = createMatcher.typeOf("regexp");
|
||
|
createMatcher.date = createMatcher.typeOf("date");
|
||
|
createMatcher.symbol = createMatcher.typeOf("symbol");
|
||
|
|
||
|
var createMatcher_1 = createMatcher;
|
||
|
|
||
|
var valueToString$4 = commons.valueToString;
|
||
|
var indexOf$2 = commons.prototypes.string.indexOf;
|
||
|
var forEach$1 = commons.prototypes.array.forEach;
|
||
|
|
||
|
|
||
|
var engineCanCompareMaps = typeof Array.from === "function";
|
||
|
var deepEqual$2 = deepEqual.use(match); // eslint-disable-line no-use-before-define
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Returns true when `array` contains all of `subset` as defined by the `compare`
|
||
|
* argument
|
||
|
*
|
||
|
* @param {Array} array An array to search for a subset
|
||
|
* @param {Array} subset The subset to find in the array
|
||
|
* @param {Function} compare A comparison function
|
||
|
* @returns {boolean} [description]
|
||
|
* @private
|
||
|
*/
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
/* eslint-disable complexity */
|
||
|
/**
|
||
|
* Matches an object with a matcher (or value)
|
||
|
*
|
||
|
* @alias module:samsam.match
|
||
|
* @param {object} object The object candidate to match
|
||
|
* @param {object} matcherOrValue A matcher or value to match against
|
||
|
* @returns {boolean} true when `object` matches `matcherOrValue`
|
||
|
*/
|
||
|
function match(object, matcherOrValue) {
|
||
|
if (matcherOrValue && typeof matcherOrValue.test === "function") {
|
||
|
return matcherOrValue.test(object);
|
||
|
}
|
||
|
|
||
|
switch (typeDetect(matcherOrValue)) {
|
||
|
case "bigint":
|
||
|
case "boolean":
|
||
|
case "number":
|
||
|
case "symbol":
|
||
|
return matcherOrValue === object;
|
||
|
case "function":
|
||
|
return matcherOrValue(object) === true;
|
||
|
case "string":
|
||
|
var notNull = typeof object === "string" || Boolean(object);
|
||
|
return (
|
||
|
notNull &&
|
||
|
indexOf$2(
|
||
|
valueToString$4(object).toLowerCase(),
|
||
|
matcherOrValue.toLowerCase()
|
||
|
) >= 0
|
||
|
);
|
||
|
case "null":
|
||
|
return object === null;
|
||
|
case "undefined":
|
||
|
return typeof object === "undefined";
|
||
|
case "Date":
|
||
|
/* istanbul ignore else */
|
||
|
if (typeDetect(object) === "Date") {
|
||
|
return object.getTime() === matcherOrValue.getTime();
|
||
|
}
|
||
|
/* istanbul ignore next: this is basically the rest of the function, which is covered */
|
||
|
break;
|
||
|
case "Array":
|
||
|
case "Int8Array":
|
||
|
case "Uint8Array":
|
||
|
case "Uint8ClampedArray":
|
||
|
case "Int16Array":
|
||
|
case "Uint16Array":
|
||
|
case "Int32Array":
|
||
|
case "Uint32Array":
|
||
|
case "Float32Array":
|
||
|
case "Float64Array":
|
||
|
return (
|
||
|
isArrayType_1(matcherOrValue) &&
|
||
|
arrayContains(object, matcherOrValue, match)
|
||
|
);
|
||
|
case "Map":
|
||
|
/* istanbul ignore next: this is covered by a test, that is only run in IE, but we collect coverage information in node*/
|
||
|
if (!engineCanCompareMaps) {
|
||
|
throw new Error(
|
||
|
"The JavaScript engine does not support Array.from and cannot reliably do value comparison of Map instances"
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
typeDetect(object) === "Map" &&
|
||
|
arrayContains(
|
||
|
Array.from(object),
|
||
|
Array.from(matcherOrValue),
|
||
|
match
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
switch (typeDetect(object)) {
|
||
|
case "null":
|
||
|
return false;
|
||
|
case "Set":
|
||
|
return isSubset_1(matcherOrValue, object, match);
|
||
|
}
|
||
|
|
||
|
/* istanbul ignore else */
|
||
|
if (matcherOrValue && typeof matcherOrValue === "object") {
|
||
|
if (matcherOrValue === object) {
|
||
|
return true;
|
||
|
}
|
||
|
if (typeof object !== "object") {
|
||
|
return false;
|
||
|
}
|
||
|
var prop;
|
||
|
// eslint-disable-next-line guard-for-in
|
||
|
for (prop in matcherOrValue) {
|
||
|
var value = object[prop];
|
||
|
if (
|
||
|
typeof value === "undefined" &&
|
||
|
typeof object.getAttribute === "function"
|
||
|
) {
|
||
|
value = object.getAttribute(prop);
|
||
|
}
|
||
|
if (
|
||
|
matcherOrValue[prop] === null ||
|
||
|
typeof matcherOrValue[prop] === "undefined"
|
||
|
) {
|
||
|
if (value !== matcherOrValue[prop]) {
|
||
|
return false;
|
||
|
}
|
||
|
} else if (
|
||
|
typeof value === "undefined" ||
|
||
|
!deepEqual$2(value, matcherOrValue[prop])
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* istanbul ignore next */
|
||
|
throw new Error("Matcher was an unknown or unsupported type");
|
||
|
}
|
||
|
/* eslint-enable complexity */
|
||
|
|
||
|
forEach$1(Object.keys(createMatcher_1), function(key) {
|
||
|
match[key] = createMatcher_1[key];
|
||
|
});
|
||
|
|
||
|
var match_1 = match;
|
||
|
|
||
|
/**
|
||
|
* @module samsam
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
var deepEqualCyclic$1 = deepEqual.use(match_1);
|
||
|
|
||
|
|
||
|
var samsam = {
|
||
|
createMatcher: createMatcher_1,
|
||
|
deepEqual: deepEqualCyclic$1,
|
||
|
identical: identical_1,
|
||
|
isArguments: isArguments_1,
|
||
|
isElement: isElement_1,
|
||
|
isMap: isMap_1,
|
||
|
isNegZero: isNegZero_1,
|
||
|
isSet: isSet_1,
|
||
|
match: match_1
|
||
|
};
|
||
|
var samsam_1 = samsam.createMatcher;
|
||
|
var samsam_2 = samsam.deepEqual;
|
||
|
var samsam_3 = samsam.identical;
|
||
|
var samsam_4 = samsam.isArguments;
|
||
|
var samsam_5 = samsam.isElement;
|
||
|
var samsam_6 = samsam.isMap;
|
||
|
var samsam_7 = samsam.isNegZero;
|
||
|
var samsam_8 = samsam.isSet;
|
||
|
var samsam_9 = samsam.match;
|
||
|
|
||
|
exports.createMatcher = samsam_1;
|
||
|
exports.deepEqual = samsam_2;
|
||
|
exports.default = samsam;
|
||
|
exports.identical = samsam_3;
|
||
|
exports.isArguments = samsam_4;
|
||
|
exports.isElement = samsam_5;
|
||
|
exports.isMap = samsam_6;
|
||
|
exports.isNegZero = samsam_7;
|
||
|
exports.isSet = samsam_8;
|
||
|
exports.match = samsam_9;
|
||
|
|
||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||
|
|
||
|
})));
|