mirror of https://gitee.com/bigwinds/arangodb
262 lines
8.5 KiB
JavaScript
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
|
|
));
|