123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- "use strict";
-
- var valueToString = require("@sinonjs/commons").valueToString;
- var indexOf = require("@sinonjs/commons").prototypes.string.indexOf;
- var forEach = require("@sinonjs/commons").prototypes.array.forEach;
- var type = require("type-detect");
-
- var engineCanCompareMaps = typeof Array.from === "function";
- var deepEqual = require("./deep-equal").use(match); // eslint-disable-line no-use-before-define
- var isArrayType = require("./is-array-type");
- var isSubset = require("./is-subset");
- var createMatcher = require("./create-matcher");
-
- /**
- * 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 (type(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(
- valueToString(object).toLowerCase(),
- matcherOrValue.toLowerCase()
- ) >= 0
- );
- case "null":
- return object === null;
- case "undefined":
- return typeof object === "undefined";
- case "Date":
- /* istanbul ignore else */
- if (type(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(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 (
- type(object) === "Map" &&
- arrayContains(
- Array.from(object),
- Array.from(matcherOrValue),
- match
- )
- );
- default:
- break;
- }
-
- switch (type(object)) {
- case "null":
- return false;
- case "Set":
- return isSubset(matcherOrValue, object, match);
- default:
- break;
- }
-
- /* 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(value, matcherOrValue[prop])
- ) {
- return false;
- }
- }
- return true;
- }
-
- /* istanbul ignore next */
- throw new Error("Matcher was an unknown or unsupported type");
- }
- /* eslint-enable complexity */
-
- forEach(Object.keys(createMatcher), function (key) {
- match[key] = createMatcher[key];
- });
-
- module.exports = match;
|