1
0
Fork 0
arangodb/js/node/node_modules/sinon/lib/sinon/match.js

262 lines
8.5 KiB
JavaScript

/**
* @depend util/core.js
* @depend typeOf.js
*/
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
/*global module, require, sinon*/
/**
* Match functions
*
* @author Maximilian Antoni (mail@maxantoni.de)
* @license BSD
*
* Copyright (c) 2012 Maximilian Antoni
*/
(function (sinonGlobal) {
"use strict";
function makeApi(sinon) {
function assertType(value, type, name) {
var actual = sinon.typeOf(value);
if (actual !== type) {
throw new TypeError("Expected type of " + name + " to be " +
type + ", but was " + actual);
}
}
var matcher = {
toString: function () {
return this.message;
}
};
function isMatcher(object) {
return matcher.isPrototypeOf(object);
}
function matchObject(expectation, actual) {
if (actual === null || actual === undefined) {
return false;
}
for (var key in expectation) {
if (expectation.hasOwnProperty(key)) {
var exp = expectation[key];
var act = actual[key];
if (isMatcher(exp)) {
if (!exp.test(act)) {
return false;
}
} else if (sinon.typeOf(exp) === "object") {
if (!matchObject(exp, act)) {
return false;
}
} else if (!sinon.deepEqual(exp, act)) {
return false;
}
}
}
return true;
}
function match(expectation, message) {
var m = sinon.create(matcher);
var type = sinon.typeOf(expectation);
switch (type) {
case "object":
if (typeof expectation.test === "function") {
m.test = function (actual) {
return expectation.test(actual) === true;
};
m.message = "match(" + sinon.functionName(expectation.test) + ")";
return m;
}
var str = [];
for (var key in expectation) {
if (expectation.hasOwnProperty(key)) {
str.push(key + ": " + expectation[key]);
}
}
m.test = function (actual) {
return matchObject(expectation, actual);
};
m.message = "match(" + str.join(", ") + ")";
break;
case "number":
m.test = function (actual) {
// we need type coercion here
return expectation == actual; // eslint-disable-line eqeqeq
};
break;
case "string":
m.test = function (actual) {
if (typeof actual !== "string") {
return false;
}
return actual.indexOf(expectation) !== -1;
};
m.message = "match(\"" + expectation + "\")";
break;
case "regexp":
m.test = function (actual) {
if (typeof actual !== "string") {
return false;
}
return expectation.test(actual);
};
break;
case "function":
m.test = expectation;
if (message) {
m.message = message;
} else {
m.message = "match(" + sinon.functionName(expectation) + ")";
}
break;
default:
m.test = function (actual) {
return sinon.deepEqual(expectation, actual);
};
}
if (!m.message) {
m.message = "match(" + expectation + ")";
}
return m;
}
matcher.or = function (m2) {
if (!arguments.length) {
throw new TypeError("Matcher expected");
} else if (!isMatcher(m2)) {
m2 = match(m2);
}
var m1 = this;
var or = sinon.create(matcher);
or.test = function (actual) {
return m1.test(actual) || m2.test(actual);
};
or.message = m1.message + ".or(" + m2.message + ")";
return or;
};
matcher.and = function (m2) {
if (!arguments.length) {
throw new TypeError("Matcher expected");
} else if (!isMatcher(m2)) {
m2 = match(m2);
}
var m1 = this;
var and = sinon.create(matcher);
and.test = function (actual) {
return m1.test(actual) && m2.test(actual);
};
and.message = m1.message + ".and(" + m2.message + ")";
return and;
};
match.isMatcher = isMatcher;
match.any = match(function () {
return true;
}, "any");
match.defined = match(function (actual) {
return actual !== null && actual !== undefined;
}, "defined");
match.truthy = match(function (actual) {
return !!actual;
}, "truthy");
match.falsy = match(function (actual) {
return !actual;
}, "falsy");
match.same = function (expectation) {
return match(function (actual) {
return expectation === actual;
}, "same(" + expectation + ")");
};
match.typeOf = function (type) {
assertType(type, "string", "type");
return match(function (actual) {
return sinon.typeOf(actual) === type;
}, "typeOf(\"" + type + "\")");
};
match.instanceOf = function (type) {
assertType(type, "function", "type");
return match(function (actual) {
return actual instanceof type;
}, "instanceOf(" + sinon.functionName(type) + ")");
};
function createPropertyMatcher(propertyTest, messagePrefix) {
return function (property, value) {
assertType(property, "string", "property");
var onlyProperty = arguments.length === 1;
var message = messagePrefix + "(\"" + property + "\"";
if (!onlyProperty) {
message += ", " + value;
}
message += ")";
return match(function (actual) {
if (actual === undefined || actual === null ||
!propertyTest(actual, property)) {
return false;
}
return onlyProperty || sinon.deepEqual(value, actual[property]);
}, message);
};
}
match.has = createPropertyMatcher(function (actual, property) {
if (typeof actual === "object") {
return property in actual;
}
return actual[property] !== undefined;
}, "has");
match.hasOwn = createPropertyMatcher(function (actual, property) {
return actual.hasOwnProperty(property);
}, "hasOwn");
match.bool = match.typeOf("boolean");
match.number = match.typeOf("number");
match.string = match.typeOf("string");
match.object = match.typeOf("object");
match.func = match.typeOf("function");
match.array = match.typeOf("array");
match.regexp = match.typeOf("regexp");
match.date = match.typeOf("date");
sinon.match = match;
return match;
}
var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
function loadDependencies(require, exports, module) {
var sinon = require("./util/core");
require("./typeOf");
module.exports = makeApi(sinon);
}
if (isAMD) {
define(loadDependencies);
return;
}
if (isNode) {
loadDependencies(require, module.exports, module);
return;
}
if (sinonGlobal) {
makeApi(sinonGlobal);
}
}(
typeof sinon === "object" && sinon // eslint-disable-line no-undef
));