sinon
Version:
JavaScript test spies, stubs and mocks.
195 lines (162 loc) • 4.39 kB
JavaScript
;
var commons = require('@sinonjs/commons');
var proxy = require('./proxy.js');
var nextTick = require('./util/core/next-tick.js');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var commons__default = /*#__PURE__*/_interopDefault(commons);
const { prototypes } = commons__default.default;
const { slice } = prototypes.array;
/**
* @callback SinonFunction
* @param {...unknown} args
* @returns {unknown}
*/
/**
* Returns a `fake` that records all calls, arguments and return values.
*
* When an `f` argument is supplied, this implementation will be used.
*
* @param {SinonFunction|undefined} [f]
* @returns {SinonFunction}
* @namespace
*/
function fake(f) {
if (arguments.length > 0 && typeof f !== "function") {
throw new TypeError("Expected f argument to be a Function");
}
return wrapFunc(f);
}
/**
* Creates a `fake` that returns the provided `value`, as well as recording all
* calls, arguments and return values.
*
* @memberof fake
* @param {unknown} value
* @returns {SinonFunction}
*/
fake.returns = function returns(value) {
function f() {
return value;
}
return wrapFunc(f);
};
/**
* Creates a `fake` that throws an Error.
*
* @memberof fake
* @param {unknown|Error} value
* @returns {SinonFunction}
*/
fake.throws = function throws(value) {
function f() {
throw getError(value);
}
return wrapFunc(f);
};
/**
* Creates a `fake` that returns a promise that resolves to the passed `value`
*
* @memberof fake
* @param {unknown} value
* @returns {SinonFunction}
*/
fake.resolves = function resolves(value) {
function f() {
return Promise.resolve(value);
}
return wrapFunc(f);
};
/**
* Creates a `fake` that returns a promise that rejects to the passed `value`
*
* @memberof fake
* @param {unknown} value
* @returns {SinonFunction}
*/
fake.rejects = function rejects(value) {
function f() {
return Promise.reject(getError(value));
}
return wrapFunc(f);
};
/**
* Returns a `fake` that calls the callback with the defined arguments.
*
* @memberof fake
* @returns {SinonFunction}
*/
fake.yields = function yields() {
const values = slice(arguments);
function f() {
const callback = arguments[arguments.length - 1];
if (typeof callback !== "function") {
throw new TypeError("Expected last argument to be a function");
}
callback.apply(null, values);
}
return wrapFunc(f);
};
/**
* Returns a `fake` that calls the callback **asynchronously** with the
* defined arguments.
*
* @memberof fake
* @returns {SinonFunction}
*/
fake.yieldsAsync = function yieldsAsync() {
const values = slice(arguments);
function f() {
const callback = arguments[arguments.length - 1];
if (typeof callback !== "function") {
throw new TypeError("Expected last argument to be a function");
}
nextTick(function () {
callback.apply(null, values);
});
}
return wrapFunc(f);
};
let uuid = 0;
/**
* Creates a proxy (sinon concept) from the passed function.
*
* @private
* @param {SinonFunction} f
* @returns {SinonFunction}
*/
function wrapFunc(f) {
const fakeInstance = function () {
let firstArg, lastArg;
if (arguments.length > 0) {
firstArg = arguments[0];
lastArg = arguments[arguments.length - 1];
}
const callback =
lastArg && typeof lastArg === "function" ? lastArg : undefined;
/* eslint-disable no-use-before-define */
proxy$1.firstArg = firstArg;
proxy$1.lastArg = lastArg;
proxy$1.callback = callback;
return f && f.apply(this, arguments);
};
const proxy$1 = proxy(fakeInstance, f || fakeInstance);
Object.defineProperty(proxy$1, "name", {
value: "fake",
configurable: true,
});
proxy$1.displayName = "fake";
proxy$1.id = `fake#${uuid++}`;
return proxy$1;
}
/**
* Returns an Error instance from the passed value, if the value is not
* already an Error instance.
*
* @private
* @param {unknown} value [description]
* @returns {Error} [description]
*/
function getError(value) {
return value instanceof Error ? value : new Error(value);
}
module.exports = fake;