hanbi
Version:
A small javascript library for stubbing and spying on methods/functions.
182 lines (181 loc) • 4.55 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var main_exports = {};
__export(main_exports, {
Stub: () => Stub,
restore: () => restore,
spy: () => spy,
stub: () => stub,
stubMethod: () => stubMethod
});
module.exports = __toCommonJS(main_exports);
class Stub {
/**
* Constructor
* @param fn Function being stubbed
*/
constructor(fn) {
this._calls = /* @__PURE__ */ new Set();
this.original = fn;
const self = this;
this.handler = function handler(...args) {
return self._handleCall.call(self, this, args);
};
}
/**
* Whether or not this stub has been called
*/
get called() {
return this._calls.size > 0;
}
/**
* List of all calls this stub has received
*/
get calls() {
return this._calls;
}
/**
* Retrieves an individual call
* @param index Index of the call to retrieve
* @return Call at the specified index
*/
getCall(index) {
return [...this._calls][index];
}
/**
* Retrieves the first call
* @return Call object
*/
get firstCall() {
return this.getCall(0);
}
/**
* Retrieves the last call
* @return Call object
*/
get lastCall() {
return this.getCall(this.callCount - 1);
}
/**
* Number of times this stub has been called
*/
get callCount() {
return this._calls.size;
}
/**
* Processes an individual call to this stub
* @param thisValue Context of the call (`this`)
* @param args Arguments passed when being called
* @return Return value of this call
*/
_handleCall(thisValue, args) {
const returnValue = this._returnFunction ? this._returnFunction.apply(thisValue, args) : this._returnValue;
this._calls.add({
args,
thisValue,
returnValue
});
return returnValue;
}
/**
* Specifies the value this stub should return
* @param val Value to return
*/
returns(val) {
this._returnFunction = void 0;
this._returnValue = val;
}
/**
* Specifies a function to call to retrieve the return value of this
* stub
* @param fn Function to call
*/
callsFake(fn) {
this._returnValue = void 0;
this._returnFunction = fn;
}
/**
* Enables pass-through, in that the original function is called when
* this stub is called.
*/
passThrough() {
this.callsFake(this.original);
}
/**
* Resets call state (e.g. call count, calls, etc.)
*/
reset() {
this._calls.clear();
}
/**
* Restores this stub.
* This behaviour differs depending on what created the stub.
*/
restore() {
if (this.restoreCallback) {
this.restoreCallback();
}
}
/**
* Asserts that the stub was called with a set of arguments
* @param args Arguments to assert for
* @return Whether they were passed or not
*/
calledWith(...args) {
return [...this.calls].some(
(call) => call.args.length === args.length && call.args.every((arg, idx) => args[idx] === arg)
);
}
/**
* Asserts that the stub returned a given value
* @param val Value to check for
* @return Whether the value was ever returned or not
*/
returned(val) {
return [...this.calls].some((call) => call.returnValue === val);
}
}
const stubbedMethods = /* @__PURE__ */ new Set();
function stubMethod(obj, method) {
const instance = new Stub(
obj[method]
);
obj[method] = instance.handler;
instance.restoreCallback = () => {
obj[method] = instance.original;
stubbedMethods.delete(instance);
};
stubbedMethods.add(instance);
return instance;
}
function stub(fn) {
const result = new Stub(fn);
return result;
}
function spy() {
return new Stub(() => {
return;
});
}
function restore() {
for (const stub2 of stubbedMethods) {
stub2.restore();
}
stubbedMethods.clear();
}