mirror of https://gitee.com/bigwinds/arangodb
372 lines
12 KiB
JavaScript
372 lines
12 KiB
JavaScript
/**
|
|
* @depend util/core.js
|
|
* @depend extend.js
|
|
*/
|
|
/**
|
|
* Stub behavior
|
|
*
|
|
* @author Christian Johansen (christian@cjohansen.no)
|
|
* @author Tim Fischbach (mail@timfischbach.de)
|
|
* @license BSD
|
|
*
|
|
* Copyright (c) 2010-2013 Christian Johansen
|
|
*/
|
|
(function (sinonGlobal) {
|
|
"use strict";
|
|
|
|
var slice = Array.prototype.slice;
|
|
var join = Array.prototype.join;
|
|
var useLeftMostCallback = -1;
|
|
var useRightMostCallback = -2;
|
|
|
|
var nextTick = (function () {
|
|
if (typeof process === "object" && typeof process.nextTick === "function") {
|
|
return process.nextTick;
|
|
}
|
|
|
|
if (typeof setImmediate === "function") {
|
|
return setImmediate;
|
|
}
|
|
|
|
return function (callback) {
|
|
setTimeout(callback, 0);
|
|
};
|
|
})();
|
|
|
|
function throwsException(error, message) {
|
|
if (typeof error === "string") {
|
|
this.exception = new Error(message || "");
|
|
this.exception.name = error;
|
|
} else if (!error) {
|
|
this.exception = new Error("Error");
|
|
} else {
|
|
this.exception = error;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
function getCallback(behavior, args) {
|
|
var callArgAt = behavior.callArgAt;
|
|
|
|
if (callArgAt >= 0) {
|
|
return args[callArgAt];
|
|
}
|
|
|
|
var argumentList;
|
|
|
|
if (callArgAt === useLeftMostCallback) {
|
|
argumentList = args;
|
|
}
|
|
|
|
if (callArgAt === useRightMostCallback) {
|
|
argumentList = slice.call(args).reverse();
|
|
}
|
|
|
|
var callArgProp = behavior.callArgProp;
|
|
|
|
for (var i = 0, l = argumentList.length; i < l; ++i) {
|
|
if (!callArgProp && typeof argumentList[i] === "function") {
|
|
return argumentList[i];
|
|
}
|
|
|
|
if (callArgProp && argumentList[i] &&
|
|
typeof argumentList[i][callArgProp] === "function") {
|
|
return argumentList[i][callArgProp];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function makeApi(sinon) {
|
|
function getCallbackError(behavior, func, args) {
|
|
if (behavior.callArgAt < 0) {
|
|
var msg;
|
|
|
|
if (behavior.callArgProp) {
|
|
msg = sinon.functionName(behavior.stub) +
|
|
" expected to yield to '" + behavior.callArgProp +
|
|
"', but no object with such a property was passed.";
|
|
} else {
|
|
msg = sinon.functionName(behavior.stub) +
|
|
" expected to yield, but no callback was passed.";
|
|
}
|
|
|
|
if (args.length > 0) {
|
|
msg += " Received [" + join.call(args, ", ") + "]";
|
|
}
|
|
|
|
return msg;
|
|
}
|
|
|
|
return "argument at index " + behavior.callArgAt + " is not a function: " + func;
|
|
}
|
|
|
|
function callCallback(behavior, args) {
|
|
if (typeof behavior.callArgAt === "number") {
|
|
var func = getCallback(behavior, args);
|
|
|
|
if (typeof func !== "function") {
|
|
throw new TypeError(getCallbackError(behavior, func, args));
|
|
}
|
|
|
|
if (behavior.callbackAsync) {
|
|
nextTick(function () {
|
|
func.apply(behavior.callbackContext, behavior.callbackArguments);
|
|
});
|
|
} else {
|
|
func.apply(behavior.callbackContext, behavior.callbackArguments);
|
|
}
|
|
}
|
|
}
|
|
|
|
var proto = {
|
|
create: function create(stub) {
|
|
var behavior = sinon.extend({}, sinon.behavior);
|
|
delete behavior.create;
|
|
behavior.stub = stub;
|
|
|
|
return behavior;
|
|
},
|
|
|
|
isPresent: function isPresent() {
|
|
return (typeof this.callArgAt === "number" ||
|
|
this.exception ||
|
|
typeof this.returnArgAt === "number" ||
|
|
this.returnThis ||
|
|
this.returnValueDefined);
|
|
},
|
|
|
|
invoke: function invoke(context, args) {
|
|
callCallback(this, args);
|
|
|
|
if (this.exception) {
|
|
throw this.exception;
|
|
} else if (typeof this.returnArgAt === "number") {
|
|
return args[this.returnArgAt];
|
|
} else if (this.returnThis) {
|
|
return context;
|
|
}
|
|
|
|
return this.returnValue;
|
|
},
|
|
|
|
onCall: function onCall(index) {
|
|
return this.stub.onCall(index);
|
|
},
|
|
|
|
onFirstCall: function onFirstCall() {
|
|
return this.stub.onFirstCall();
|
|
},
|
|
|
|
onSecondCall: function onSecondCall() {
|
|
return this.stub.onSecondCall();
|
|
},
|
|
|
|
onThirdCall: function onThirdCall() {
|
|
return this.stub.onThirdCall();
|
|
},
|
|
|
|
withArgs: function withArgs(/* arguments */) {
|
|
throw new Error(
|
|
"Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" " +
|
|
"is not supported. Use \"stub.withArgs(...).onCall(...)\" " +
|
|
"to define sequential behavior for calls with certain arguments."
|
|
);
|
|
},
|
|
|
|
callsArg: function callsArg(pos) {
|
|
if (typeof pos !== "number") {
|
|
throw new TypeError("argument index is not number");
|
|
}
|
|
|
|
this.callArgAt = pos;
|
|
this.callbackArguments = [];
|
|
this.callbackContext = undefined;
|
|
this.callArgProp = undefined;
|
|
this.callbackAsync = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
callsArgOn: function callsArgOn(pos, context) {
|
|
if (typeof pos !== "number") {
|
|
throw new TypeError("argument index is not number");
|
|
}
|
|
if (typeof context !== "object") {
|
|
throw new TypeError("argument context is not an object");
|
|
}
|
|
|
|
this.callArgAt = pos;
|
|
this.callbackArguments = [];
|
|
this.callbackContext = context;
|
|
this.callArgProp = undefined;
|
|
this.callbackAsync = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
callsArgWith: function callsArgWith(pos) {
|
|
if (typeof pos !== "number") {
|
|
throw new TypeError("argument index is not number");
|
|
}
|
|
|
|
this.callArgAt = pos;
|
|
this.callbackArguments = slice.call(arguments, 1);
|
|
this.callbackContext = undefined;
|
|
this.callArgProp = undefined;
|
|
this.callbackAsync = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
callsArgOnWith: function callsArgWith(pos, context) {
|
|
if (typeof pos !== "number") {
|
|
throw new TypeError("argument index is not number");
|
|
}
|
|
if (typeof context !== "object") {
|
|
throw new TypeError("argument context is not an object");
|
|
}
|
|
|
|
this.callArgAt = pos;
|
|
this.callbackArguments = slice.call(arguments, 2);
|
|
this.callbackContext = context;
|
|
this.callArgProp = undefined;
|
|
this.callbackAsync = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
yields: function () {
|
|
this.callArgAt = useLeftMostCallback;
|
|
this.callbackArguments = slice.call(arguments, 0);
|
|
this.callbackContext = undefined;
|
|
this.callArgProp = undefined;
|
|
this.callbackAsync = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
yieldsRight: function () {
|
|
this.callArgAt = useRightMostCallback;
|
|
this.callbackArguments = slice.call(arguments, 0);
|
|
this.callbackContext = undefined;
|
|
this.callArgProp = undefined;
|
|
this.callbackAsync = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
yieldsOn: function (context) {
|
|
if (typeof context !== "object") {
|
|
throw new TypeError("argument context is not an object");
|
|
}
|
|
|
|
this.callArgAt = useLeftMostCallback;
|
|
this.callbackArguments = slice.call(arguments, 1);
|
|
this.callbackContext = context;
|
|
this.callArgProp = undefined;
|
|
this.callbackAsync = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
yieldsTo: function (prop) {
|
|
this.callArgAt = useLeftMostCallback;
|
|
this.callbackArguments = slice.call(arguments, 1);
|
|
this.callbackContext = undefined;
|
|
this.callArgProp = prop;
|
|
this.callbackAsync = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
yieldsToOn: function (prop, context) {
|
|
if (typeof context !== "object") {
|
|
throw new TypeError("argument context is not an object");
|
|
}
|
|
|
|
this.callArgAt = useLeftMostCallback;
|
|
this.callbackArguments = slice.call(arguments, 2);
|
|
this.callbackContext = context;
|
|
this.callArgProp = prop;
|
|
this.callbackAsync = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
throws: throwsException,
|
|
throwsException: throwsException,
|
|
|
|
returns: function returns(value) {
|
|
this.returnValue = value;
|
|
this.returnValueDefined = true;
|
|
this.exception = undefined;
|
|
|
|
return this;
|
|
},
|
|
|
|
returnsArg: function returnsArg(pos) {
|
|
if (typeof pos !== "number") {
|
|
throw new TypeError("argument index is not number");
|
|
}
|
|
|
|
this.returnArgAt = pos;
|
|
|
|
return this;
|
|
},
|
|
|
|
returnsThis: function returnsThis() {
|
|
this.returnThis = true;
|
|
|
|
return this;
|
|
}
|
|
};
|
|
|
|
function createAsyncVersion(syncFnName) {
|
|
return function () {
|
|
var result = this[syncFnName].apply(this, arguments);
|
|
this.callbackAsync = true;
|
|
return result;
|
|
};
|
|
}
|
|
|
|
// create asynchronous versions of callsArg* and yields* methods
|
|
for (var method in proto) {
|
|
// need to avoid creating anotherasync versions of the newly added async methods
|
|
if (proto.hasOwnProperty(method) && method.match(/^(callsArg|yields)/) && !method.match(/Async/)) {
|
|
proto[method + "Async"] = createAsyncVersion(method);
|
|
}
|
|
}
|
|
|
|
sinon.behavior = proto;
|
|
return proto;
|
|
}
|
|
|
|
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("./extend");
|
|
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
|
|
));
|