'use strict';
const ErrorLib = require('./ErrorLib');
/**
* @class
*/
class StubObjectMethod {
/**
* object[methodName] will be overridden by overrideFunction, note that the context for overrideFunction will be the same as for object[methodName].
* @constructor
* @param stubClassObject
* @param object {Object} Object which contains the method to be stubbed.
* @param methodName {string} Name of the method inside the object which has to be stubbed.
* @param overrideFunction {function} Function with which object[methodName] has to be stubbed.
*/
constructor (stubClassObject, object, methodName, overrideFunction) {
this._stubClassObject = stubClassObject;
this._object = object;
this._methodName = methodName;
this._overrideFunction = overrideFunction;
this._restoreMethod = object[methodName];
this._callCount = 0;
this._args = [];
const self = this;
this._object[this._methodName] = function () {
self._callCount++;
const args = [];
for (let i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
self._args.push(args);
return self._overrideFunction.call(this, ...self._args[self._callCount - 1]);
}
}
/**
* Returns list of arguments passed to object[methodName] for every function call.
* @returns {Array}
*/
get callingArgs () {
return this._args;
}
/**
* Returns total number of times object[methodName] is called.
* @returns {number}
*/
get callCount () {
return this._callCount;
}
/**
* Restores object[methodName] to its original state.
*/
restore () {
if (this._object && this._methodName) {
this._object[this._methodName] = this._restoreMethod;
this._stubClassObject._remove(this._object, this._methodName);
this._object = null;
this._methodName = null;
this._overrideFunction = null;
this._restoreMethod = null;
this._callCount = 0;
this._args = [];
}
}
}
/**
* @class
*/
class Stub {
/**
* @constructor
*/
constructor () {
this._stubbedMethods = [];
}
/**
* Call this method to stub over a function of an object with another function.
* @param object {Object} Object which contains the method to be stubbed.
* @param methodName {string} Name of the method inside the object which has to be stubbed.
* @param overrideFunction {function} Function with which object[methodName] has to be stubbed.
* @returns {StubObjectMethod}
*/
stub (object, methodName, overrideFunction) {
for (let i = 0; i < this._stubbedMethods.length; i++) {
if (this._stubbedMethods[i].object === object && this._stubbedMethods[i].methodName === methodName) {
ErrorLib.throwError(ErrorLib.errorMap.ReStubFunctionError);
}
}
this._stubbedMethods.push({
object: object,
methodName: methodName
});
return new StubObjectMethod (this, object, methodName, overrideFunction);
}
_remove (object, methodName) {
this._stubbedMethods = this._stubbedMethods.filter((element) => {
return element.object !== object && element.methodName !== methodName;
});
}
}
module.exports = new Stub();