UNPKG

sinon

Version:

JavaScript test spies, stubs and mocks.

1,715 lines (1,454 loc) 419 kB
/* Sinon.JS 20.0.0, 2025-03-24, @license BSD-3 */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.sinon = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ "use strict"; const behavior = require("./sinon/behavior"); const createSandbox = require("./sinon/create-sandbox"); const extend = require("./sinon/util/core/extend"); const fakeTimers = require("./sinon/util/fake-timers"); const Sandbox = require("./sinon/sandbox"); const stub = require("./sinon/stub"); const promise = require("./sinon/promise"); /** * @returns {object} a configured sandbox */ module.exports = function createApi() { const apiMethods = { createSandbox: createSandbox, match: require("@sinonjs/samsam").createMatcher, restoreObject: require("./sinon/restore-object"), expectation: require("./sinon/mock-expectation"), // fake timers timers: fakeTimers.timers, addBehavior: function (name, fn) { behavior.addBehavior(stub, name, fn); }, // fake promise promise: promise, }; const sandbox = new Sandbox(); return extend(sandbox, apiMethods); }; },{"./sinon/behavior":4,"./sinon/create-sandbox":7,"./sinon/mock-expectation":11,"./sinon/promise":13,"./sinon/restore-object":18,"./sinon/sandbox":19,"./sinon/stub":22,"./sinon/util/core/extend":25,"./sinon/util/fake-timers":39,"@sinonjs/samsam":86}],2:[function(require,module,exports){ "use strict"; const createApi = require("./create-sinon-api"); module.exports = createApi(); },{"./create-sinon-api":1}],3:[function(require,module,exports){ "use strict"; /** @module */ const arrayProto = require("@sinonjs/commons").prototypes.array; const calledInOrder = require("@sinonjs/commons").calledInOrder; const createMatcher = require("@sinonjs/samsam").createMatcher; const orderByFirstCall = require("@sinonjs/commons").orderByFirstCall; const timesInWords = require("./util/core/times-in-words"); const inspect = require("util").inspect; const stringSlice = require("@sinonjs/commons").prototypes.string.slice; const globalObject = require("@sinonjs/commons").global; const arraySlice = arrayProto.slice; const concat = arrayProto.concat; const forEach = arrayProto.forEach; const join = arrayProto.join; const splice = arrayProto.splice; function applyDefaults(obj, defaults) { for (const key of Object.keys(defaults)) { const val = obj[key]; if (val === null || typeof val === "undefined") { obj[key] = defaults[key]; } } } /** * @typedef {object} CreateAssertOptions * @global * * @property {boolean} [shouldLimitAssertionLogs] default is false * @property {number} [assertionLogLimit] default is 10K */ /** * Create an assertion object that exposes several methods to invoke * * @param {CreateAssertOptions} [opts] options bag * @returns {object} object with multiple assertion methods */ function createAssertObject(opts) { const cleanedAssertOptions = opts || {}; applyDefaults(cleanedAssertOptions, { shouldLimitAssertionLogs: false, assertionLogLimit: 1e4, }); const assert = { failException: "AssertError", fail: function fail(message) { let msg = message; if (cleanedAssertOptions.shouldLimitAssertionLogs) { msg = message.substring( 0, cleanedAssertOptions.assertionLogLimit, ); } const error = new Error(msg); error.name = this.failException || assert.failException; throw error; }, pass: function pass() { return; }, callOrder: function assertCallOrder() { verifyIsStub.apply(null, arguments); let expected = ""; let actual = ""; if (!calledInOrder(arguments)) { try { expected = join(arguments, ", "); const calls = arraySlice(arguments); let i = calls.length; while (i) { if (!calls[--i].called) { splice(calls, i, 1); } } actual = join(orderByFirstCall(calls), ", "); } catch (e) { // If this fails, we'll just fall back to the blank string } failAssertion( this, `expected ${expected} to be called in order but were called as ${actual}`, ); } else { assert.pass("callOrder"); } }, callCount: function assertCallCount(method, count) { verifyIsStub(method); let msg; if (typeof count !== "number") { msg = `expected ${inspect(count)} to be a number ` + `but was of type ${typeof count}`; failAssertion(this, msg); } else if (method.callCount !== count) { msg = `expected %n to be called ${timesInWords(count)} ` + `but was called %c%C`; failAssertion(this, method.printf(msg)); } else { assert.pass("callCount"); } }, expose: function expose(target, options) { if (!target) { throw new TypeError("target is null or undefined"); } const o = options || {}; const prefix = (typeof o.prefix === "undefined" && "assert") || o.prefix; const includeFail = typeof o.includeFail === "undefined" || Boolean(o.includeFail); const instance = this; forEach(Object.keys(instance), function (method) { if ( method !== "expose" && (includeFail || !/^(fail)/.test(method)) ) { target[exposedName(prefix, method)] = instance[method]; } }); return target; }, match: function match(actual, expectation) { const matcher = createMatcher(expectation); if (matcher.test(actual)) { assert.pass("match"); } else { const formatted = [ "expected value to match", ` expected = ${inspect(expectation)}`, ` actual = ${inspect(actual)}`, ]; failAssertion(this, join(formatted, "\n")); } }, }; function verifyIsStub() { const args = arraySlice(arguments); forEach(args, function (method) { if (!method) { assert.fail("fake is not a spy"); } if (method.proxy && method.proxy.isSinonProxy) { verifyIsStub(method.proxy); } else { if (typeof method !== "function") { assert.fail(`${method} is not a function`); } if (typeof method.getCall !== "function") { assert.fail(`${method} is not stubbed`); } } }); } function verifyIsValidAssertion(assertionMethod, assertionArgs) { switch (assertionMethod) { case "notCalled": case "called": case "calledOnce": case "calledTwice": case "calledThrice": if (assertionArgs.length !== 0) { assert.fail( `${assertionMethod} takes 1 argument but was called with ${ assertionArgs.length + 1 } arguments`, ); } break; default: break; } } function failAssertion(object, msg) { const obj = object || globalObject; const failMethod = obj.fail || assert.fail; failMethod.call(obj, msg); } function mirrorPropAsAssertion(name, method, message) { let msg = message; let meth = method; if (arguments.length === 2) { msg = method; meth = name; } assert[name] = function (fake) { verifyIsStub(fake); const args = arraySlice(arguments, 1); let failed = false; verifyIsValidAssertion(name, args); if (typeof meth === "function") { failed = !meth(fake); } else { failed = typeof fake[meth] === "function" ? !fake[meth].apply(fake, args) : !fake[meth]; } if (failed) { failAssertion( this, (fake.printf || fake.proxy.printf).apply( fake, concat([msg], args), ), ); } else { assert.pass(name); } }; } function exposedName(prefix, prop) { return !prefix || /^fail/.test(prop) ? prop : prefix + stringSlice(prop, 0, 1).toUpperCase() + stringSlice(prop, 1); } mirrorPropAsAssertion( "called", "expected %n to have been called at least once but was never called", ); mirrorPropAsAssertion( "notCalled", function (spy) { return !spy.called; }, "expected %n to not have been called but was called %c%C", ); mirrorPropAsAssertion( "calledOnce", "expected %n to be called once but was called %c%C", ); mirrorPropAsAssertion( "calledTwice", "expected %n to be called twice but was called %c%C", ); mirrorPropAsAssertion( "calledThrice", "expected %n to be called thrice but was called %c%C", ); mirrorPropAsAssertion( "calledOn", "expected %n to be called with %1 as this but was called with %t", ); mirrorPropAsAssertion( "alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t", ); mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new"); mirrorPropAsAssertion( "alwaysCalledWithNew", "expected %n to always be called with new", ); mirrorPropAsAssertion( "calledWith", "expected %n to be called with arguments %D", ); mirrorPropAsAssertion( "calledWithMatch", "expected %n to be called with match %D", ); mirrorPropAsAssertion( "alwaysCalledWith", "expected %n to always be called with arguments %D", ); mirrorPropAsAssertion( "alwaysCalledWithMatch", "expected %n to always be called with match %D", ); mirrorPropAsAssertion( "calledWithExactly", "expected %n to be called with exact arguments %D", ); mirrorPropAsAssertion( "calledOnceWithExactly", "expected %n to be called once and with exact arguments %D", ); mirrorPropAsAssertion( "calledOnceWithMatch", "expected %n to be called once and with match %D", ); mirrorPropAsAssertion( "alwaysCalledWithExactly", "expected %n to always be called with exact arguments %D", ); mirrorPropAsAssertion( "neverCalledWith", "expected %n to never be called with arguments %*%C", ); mirrorPropAsAssertion( "neverCalledWithMatch", "expected %n to never be called with match %*%C", ); mirrorPropAsAssertion("threw", "%n did not throw exception%C"); mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C"); return assert; } module.exports = createAssertObject(); module.exports.createAssertObject = createAssertObject; },{"./util/core/times-in-words":35,"@sinonjs/commons":46,"@sinonjs/samsam":86,"util":90}],4:[function(require,module,exports){ "use strict"; const arrayProto = require("@sinonjs/commons").prototypes.array; const extend = require("./util/core/extend"); const functionName = require("@sinonjs/commons").functionName; const nextTick = require("./util/core/next-tick"); const valueToString = require("@sinonjs/commons").valueToString; const exportAsyncBehaviors = require("./util/core/export-async-behaviors"); const concat = arrayProto.concat; const join = arrayProto.join; const reverse = arrayProto.reverse; const slice = arrayProto.slice; const useLeftMostCallback = -1; const useRightMostCallback = -2; function getCallback(behavior, args) { const callArgAt = behavior.callArgAt; if (callArgAt >= 0) { return args[callArgAt]; } let argumentList; if (callArgAt === useLeftMostCallback) { argumentList = args; } if (callArgAt === useRightMostCallback) { argumentList = reverse(slice(args)); } const callArgProp = behavior.callArgProp; for (let 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 getCallbackError(behavior, func, args) { if (behavior.callArgAt < 0) { let msg; if (behavior.callArgProp) { msg = `${functionName( behavior.stub, )} expected to yield to '${valueToString( behavior.callArgProp, )}', but no object with such a property was passed.`; } else { msg = `${functionName( behavior.stub, )} expected to yield, but no callback was passed.`; } if (args.length > 0) { msg += ` Received [${join(args, ", ")}]`; } return msg; } return `argument at index ${behavior.callArgAt} is not a function: ${func}`; } function ensureArgs(name, behavior, args) { // map function name to internal property // callsArg => callArgAt const property = name.replace(/sArg/, "ArgAt"); const index = behavior[property]; if (index >= args.length) { throw new TypeError( `${name} failed: ${index + 1} arguments required but only ${ args.length } present`, ); } } function callCallback(behavior, args) { if (typeof behavior.callArgAt === "number") { ensureArgs("callsArg", behavior, args); const 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 { return func.apply( behavior.callbackContext, behavior.callbackArguments, ); } } return undefined; } const proto = { create: function create(stub) { const behavior = extend({}, proto); delete behavior.create; delete behavior.addBehavior; delete behavior.createBehavior; behavior.stub = stub; if (stub.defaultBehavior && stub.defaultBehavior.promiseLibrary) { behavior.promiseLibrary = stub.defaultBehavior.promiseLibrary; } return behavior; }, isPresent: function isPresent() { return ( typeof this.callArgAt === "number" || this.exception || this.exceptionCreator || typeof this.returnArgAt === "number" || this.returnThis || typeof this.resolveArgAt === "number" || this.resolveThis || typeof this.throwArgAt === "number" || this.fakeFn || this.returnValueDefined ); }, /*eslint complexity: ["error", 20]*/ invoke: function invoke(context, args) { /* * callCallback (conditionally) calls ensureArgs * * Note: callCallback intentionally happens before * everything else and cannot be moved lower */ const returnValue = callCallback(this, args); if (this.exception) { throw this.exception; } else if (this.exceptionCreator) { this.exception = this.exceptionCreator(); this.exceptionCreator = undefined; throw this.exception; } else if (typeof this.returnArgAt === "number") { ensureArgs("returnsArg", this, args); return args[this.returnArgAt]; } else if (this.returnThis) { return context; } else if (typeof this.throwArgAt === "number") { ensureArgs("throwsArg", this, args); throw args[this.throwArgAt]; } else if (this.fakeFn) { return this.fakeFn.apply(context, args); } else if (typeof this.resolveArgAt === "number") { ensureArgs("resolvesArg", this, args); return (this.promiseLibrary || Promise).resolve( args[this.resolveArgAt], ); } else if (this.resolveThis) { return (this.promiseLibrary || Promise).resolve(context); } else if (this.resolve) { return (this.promiseLibrary || Promise).resolve(this.returnValue); } else if (this.reject) { return (this.promiseLibrary || Promise).reject(this.returnValue); } else if (this.callsThrough) { const wrappedMethod = this.effectiveWrappedMethod(); return wrappedMethod.apply(context, args); } else if (this.callsThroughWithNew) { // Get the original method (assumed to be a constructor in this case) const WrappedClass = this.effectiveWrappedMethod(); // Turn the arguments object into a normal array const argsArray = slice(args); // Call the constructor const F = WrappedClass.bind.apply( WrappedClass, concat([null], argsArray), ); return new F(); } else if (typeof this.returnValue !== "undefined") { return this.returnValue; } else if (typeof this.callArgAt === "number") { return returnValue; } return this.returnValue; }, effectiveWrappedMethod: function effectiveWrappedMethod() { for (let stubb = this.stub; stubb; stubb = stubb.parent) { if (stubb.wrappedMethod) { return stubb.wrappedMethod; } } throw new Error("Unable to find wrapped method"); }, 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.", ); }, }; function createBehavior(behaviorMethod) { return function () { this.defaultBehavior = this.defaultBehavior || proto.create(this); this.defaultBehavior[behaviorMethod].apply( this.defaultBehavior, arguments, ); return this; }; } function addBehavior(stub, name, fn) { proto[name] = function () { fn.apply(this, concat([this], slice(arguments))); return this.stub || this; }; stub[name] = createBehavior(name); } proto.addBehavior = addBehavior; proto.createBehavior = createBehavior; const asyncBehaviors = exportAsyncBehaviors(proto); module.exports = extend.nonEnum({}, proto, asyncBehaviors); },{"./util/core/export-async-behaviors":24,"./util/core/extend":25,"./util/core/next-tick":33,"@sinonjs/commons":46}],5:[function(require,module,exports){ "use strict"; const walk = require("./util/core/walk"); const getPropertyDescriptor = require("./util/core/get-property-descriptor"); const hasOwnProperty = require("@sinonjs/commons").prototypes.object.hasOwnProperty; const push = require("@sinonjs/commons").prototypes.array.push; function collectMethod(methods, object, prop, propOwner) { if ( typeof getPropertyDescriptor(propOwner, prop).value === "function" && hasOwnProperty(object, prop) ) { push(methods, object[prop]); } } // This function returns an array of all the own methods on the passed object function collectOwnMethods(object) { const methods = []; walk(object, collectMethod.bind(null, methods, object)); return methods; } module.exports = collectOwnMethods; },{"./util/core/get-property-descriptor":28,"./util/core/walk":37,"@sinonjs/commons":46}],6:[function(require,module,exports){ "use strict"; module.exports = class Colorizer { constructor(supportsColor = require("supports-color")) { this.supportsColor = supportsColor; } /** * Should be renamed to true #privateField * when we can ensure ES2022 support * * @private */ colorize(str, color) { if (this.supportsColor.stdout === false) { return str; } return `\x1b[${color}m${str}\x1b[0m`; } red(str) { return this.colorize(str, 31); } green(str) { return this.colorize(str, 32); } cyan(str) { return this.colorize(str, 96); } white(str) { return this.colorize(str, 39); } bold(str) { return this.colorize(str, 1); } }; },{"supports-color":93}],7:[function(require,module,exports){ "use strict"; const arrayProto = require("@sinonjs/commons").prototypes.array; const Sandbox = require("./sandbox"); const forEach = arrayProto.forEach; const push = arrayProto.push; function prepareSandboxFromConfig(config) { const sandbox = new Sandbox({ assertOptions: config.assertOptions }); if (config.useFakeTimers) { if (typeof config.useFakeTimers === "object") { sandbox.useFakeTimers(config.useFakeTimers); } else { sandbox.useFakeTimers(); } } return sandbox; } function exposeValue(sandbox, config, key, value) { if (!value) { return; } if (config.injectInto && !(key in config.injectInto)) { config.injectInto[key] = value; push(sandbox.injectedKeys, key); } else { push(sandbox.args, value); } } /** * Options to customize a sandbox * * The sandbox's methods can be injected into another object for * convenience. The `injectInto` configuration option can name an * object to add properties to. * * @typedef {object} SandboxConfig * @property {string[]} properties The properties of the API to expose on the sandbox. Examples: ['spy', 'fake', 'restore'] * @property {object} injectInto an object in which to inject properties from the sandbox (a facade). This is mostly an integration feature (sinon-test being one). * @property {boolean} useFakeTimers whether timers are faked by default * @property {object} [assertOptions] see CreateAssertOptions in ./assert * * This type def is really suffering from JSDoc not having standardized * how to reference types defined in other modules :( */ /** * A configured sinon sandbox (private type) * * @typedef {object} ConfiguredSinonSandboxType * @private * @augments Sandbox * @property {string[]} injectedKeys the keys that have been injected (from config.injectInto) * @property {*[]} args the arguments for the sandbox */ /** * Create a sandbox * * As of Sinon 5 the `sinon` instance itself is a Sandbox, so you * hardly ever need to create additional instances for the sake of testing * * @param config {SandboxConfig} * @returns {Sandbox} */ function createSandbox(config) { if (!config) { return new Sandbox(); } const configuredSandbox = prepareSandboxFromConfig(config); configuredSandbox.args = configuredSandbox.args || []; configuredSandbox.injectedKeys = []; configuredSandbox.injectInto = config.injectInto; const exposed = configuredSandbox.inject({}); if (config.properties) { forEach(config.properties, function (prop) { const value = exposed[prop] || (prop === "sandbox" && configuredSandbox); exposeValue(configuredSandbox, config, prop, value); }); } else { exposeValue(configuredSandbox, config, "sandbox"); } return configuredSandbox; } module.exports = createSandbox; },{"./sandbox":19,"@sinonjs/commons":46}],8:[function(require,module,exports){ "use strict"; const stub = require("./stub"); const sinonType = require("./util/core/sinon-type"); const forEach = require("@sinonjs/commons").prototypes.array.forEach; function isStub(value) { return sinonType.get(value) === "stub"; } module.exports = function createStubInstance(constructor, overrides) { if (typeof constructor !== "function") { throw new TypeError("The constructor should be a function."); } const stubInstance = Object.create(constructor.prototype); sinonType.set(stubInstance, "stub-instance"); const stubbedObject = stub(stubInstance); forEach(Object.keys(overrides || {}), function (propertyName) { if (propertyName in stubbedObject) { const value = overrides[propertyName]; if (isStub(value)) { stubbedObject[propertyName] = value; } else { stubbedObject[propertyName].returns(value); } } else { throw new Error( `Cannot stub ${propertyName}. Property does not exist!`, ); } }); return stubbedObject; }; },{"./stub":22,"./util/core/sinon-type":34,"@sinonjs/commons":46}],9:[function(require,module,exports){ "use strict"; const arrayProto = require("@sinonjs/commons").prototypes.array; const isPropertyConfigurable = require("./util/core/is-property-configurable"); const exportAsyncBehaviors = require("./util/core/export-async-behaviors"); const extend = require("./util/core/extend"); const slice = arrayProto.slice; const useLeftMostCallback = -1; const useRightMostCallback = -2; function throwsException(fake, error, message) { if (typeof error === "function") { fake.exceptionCreator = error; } else if (typeof error === "string") { fake.exceptionCreator = function () { const newException = new Error( message || `Sinon-provided ${error}`, ); newException.name = error; return newException; }; } else if (!error) { fake.exceptionCreator = function () { return new Error("Error"); }; } else { fake.exception = error; } } const defaultBehaviors = { callsFake: function callsFake(fake, fn) { fake.fakeFn = fn; fake.exception = undefined; fake.exceptionCreator = undefined; fake.callsThrough = false; }, callsArg: function callsArg(fake, index) { if (typeof index !== "number") { throw new TypeError("argument index is not number"); } fake.callArgAt = index; fake.callbackArguments = []; fake.callbackContext = undefined; fake.callArgProp = undefined; fake.callbackAsync = false; fake.callsThrough = false; }, callsArgOn: function callsArgOn(fake, index, context) { if (typeof index !== "number") { throw new TypeError("argument index is not number"); } fake.callArgAt = index; fake.callbackArguments = []; fake.callbackContext = context; fake.callArgProp = undefined; fake.callbackAsync = false; fake.callsThrough = false; }, callsArgWith: function callsArgWith(fake, index) { if (typeof index !== "number") { throw new TypeError("argument index is not number"); } fake.callArgAt = index; fake.callbackArguments = slice(arguments, 2); fake.callbackContext = undefined; fake.callArgProp = undefined; fake.callbackAsync = false; fake.callsThrough = false; }, callsArgOnWith: function callsArgWith(fake, index, context) { if (typeof index !== "number") { throw new TypeError("argument index is not number"); } fake.callArgAt = index; fake.callbackArguments = slice(arguments, 3); fake.callbackContext = context; fake.callArgProp = undefined; fake.callbackAsync = false; fake.callsThrough = false; }, yields: function (fake) { fake.callArgAt = useLeftMostCallback; fake.callbackArguments = slice(arguments, 1); fake.callbackContext = undefined; fake.callArgProp = undefined; fake.callbackAsync = false; fake.fakeFn = undefined; fake.callsThrough = false; }, yieldsRight: function (fake) { fake.callArgAt = useRightMostCallback; fake.callbackArguments = slice(arguments, 1); fake.callbackContext = undefined; fake.callArgProp = undefined; fake.callbackAsync = false; fake.callsThrough = false; fake.fakeFn = undefined; }, yieldsOn: function (fake, context) { fake.callArgAt = useLeftMostCallback; fake.callbackArguments = slice(arguments, 2); fake.callbackContext = context; fake.callArgProp = undefined; fake.callbackAsync = false; fake.callsThrough = false; fake.fakeFn = undefined; }, yieldsTo: function (fake, prop) { fake.callArgAt = useLeftMostCallback; fake.callbackArguments = slice(arguments, 2); fake.callbackContext = undefined; fake.callArgProp = prop; fake.callbackAsync = false; fake.callsThrough = false; fake.fakeFn = undefined; }, yieldsToOn: function (fake, prop, context) { fake.callArgAt = useLeftMostCallback; fake.callbackArguments = slice(arguments, 3); fake.callbackContext = context; fake.callArgProp = prop; fake.callbackAsync = false; fake.fakeFn = undefined; }, throws: throwsException, throwsException: throwsException, returns: function returns(fake, value) { fake.callsThrough = false; fake.returnValue = value; fake.resolve = false; fake.reject = false; fake.returnValueDefined = true; fake.exception = undefined; fake.exceptionCreator = undefined; fake.fakeFn = undefined; }, returnsArg: function returnsArg(fake, index) { if (typeof index !== "number") { throw new TypeError("argument index is not number"); } fake.callsThrough = false; fake.returnArgAt = index; }, throwsArg: function throwsArg(fake, index) { if (typeof index !== "number") { throw new TypeError("argument index is not number"); } fake.callsThrough = false; fake.throwArgAt = index; }, returnsThis: function returnsThis(fake) { fake.returnThis = true; fake.callsThrough = false; }, resolves: function resolves(fake, value) { fake.returnValue = value; fake.resolve = true; fake.resolveThis = false; fake.reject = false; fake.returnValueDefined = true; fake.exception = undefined; fake.exceptionCreator = undefined; fake.fakeFn = undefined; fake.callsThrough = false; }, resolvesArg: function resolvesArg(fake, index) { if (typeof index !== "number") { throw new TypeError("argument index is not number"); } fake.resolveArgAt = index; fake.returnValue = undefined; fake.resolve = true; fake.resolveThis = false; fake.reject = false; fake.returnValueDefined = false; fake.exception = undefined; fake.exceptionCreator = undefined; fake.fakeFn = undefined; fake.callsThrough = false; }, rejects: function rejects(fake, error, message) { let reason; if (typeof error === "string") { reason = new Error(message || ""); reason.name = error; } else if (!error) { reason = new Error("Error"); } else { reason = error; } fake.returnValue = reason; fake.resolve = false; fake.resolveThis = false; fake.reject = true; fake.returnValueDefined = true; fake.exception = undefined; fake.exceptionCreator = undefined; fake.fakeFn = undefined; fake.callsThrough = false; return fake; }, resolvesThis: function resolvesThis(fake) { fake.returnValue = undefined; fake.resolve = false; fake.resolveThis = true; fake.reject = false; fake.returnValueDefined = false; fake.exception = undefined; fake.exceptionCreator = undefined; fake.fakeFn = undefined; fake.callsThrough = false; }, callThrough: function callThrough(fake) { fake.callsThrough = true; }, callThroughWithNew: function callThroughWithNew(fake) { fake.callsThroughWithNew = true; }, get: function get(fake, getterFunction) { const rootStub = fake.stub || fake; Object.defineProperty(rootStub.rootObj, rootStub.propName, { get: getterFunction, configurable: isPropertyConfigurable( rootStub.rootObj, rootStub.propName, ), }); return fake; }, set: function set(fake, setterFunction) { const rootStub = fake.stub || fake; Object.defineProperty( rootStub.rootObj, rootStub.propName, // eslint-disable-next-line accessor-pairs { set: setterFunction, configurable: isPropertyConfigurable( rootStub.rootObj, rootStub.propName, ), }, ); return fake; }, value: function value(fake, newVal) { const rootStub = fake.stub || fake; Object.defineProperty(rootStub.rootObj, rootStub.propName, { value: newVal, enumerable: true, writable: true, configurable: rootStub.shadowsPropOnPrototype || isPropertyConfigurable(rootStub.rootObj, rootStub.propName), }); return fake; }, }; const asyncBehaviors = exportAsyncBehaviors(defaultBehaviors); module.exports = extend({}, defaultBehaviors, asyncBehaviors); },{"./util/core/export-async-behaviors":24,"./util/core/extend":25,"./util/core/is-property-configurable":31,"@sinonjs/commons":46}],10:[function(require,module,exports){ "use strict"; const arrayProto = require("@sinonjs/commons").prototypes.array; const createProxy = require("./proxy"); const nextTick = require("./util/core/next-tick"); const slice = arrayProto.slice; module.exports = fake; /** * Returns a `fake` that records all calls, arguments and return values. * * When an `f` argument is supplied, this implementation will be used. * * @example * // create an empty fake * var f1 = sinon.fake(); * * f1(); * * f1.calledOnce() * // true * * @example * function greet(greeting) { * console.log(`Hello ${greeting}`); * } * * // create a fake with implementation * var f2 = sinon.fake(greet); * * // Hello world * f2("world"); * * f2.calledWith("world"); * // true * * @param {Function|undefined} f * @returns {Function} * @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. * * @example * var f1 = sinon.fake.returns(42); * * f1(); * // 42 * * @memberof fake * @param {*} value * @returns {Function} */ fake.returns = function returns(value) { // eslint-disable-next-line jsdoc/require-jsdoc function f() { return value; } return wrapFunc(f); }; /** * Creates a `fake` that throws an Error. * If the `value` argument does not have Error in its prototype chain, it will * be used for creating a new error. * * @example * var f1 = sinon.fake.throws("hello"); * * f1(); * // Uncaught Error: hello * * @example * var f2 = sinon.fake.throws(new TypeError("Invalid argument")); * * f2(); * // Uncaught TypeError: Invalid argument * * @memberof fake * @param {*|Error} value * @returns {Function} */ fake.throws = function throws(value) { // eslint-disable-next-line jsdoc/require-jsdoc function f() { throw getError(value); } return wrapFunc(f); }; /** * Creates a `fake` that returns a promise that resolves to the passed `value` * argument. * * @example * var f1 = sinon.fake.resolves("apple pie"); * * await f1(); * // "apple pie" * * @memberof fake * @param {*} value * @returns {Function} */ fake.resolves = function resolves(value) { // eslint-disable-next-line jsdoc/require-jsdoc function f() { return Promise.resolve(value); } return wrapFunc(f); }; /** * Creates a `fake` that returns a promise that rejects to the passed `value` * argument. When `value` does not have Error in its prototype chain, it will be * wrapped in an Error. * * @example * var f1 = sinon.fake.rejects(":("); * * try { * await f1(); * } catch (error) { * console.log(error); * // ":(" * } * * @memberof fake * @param {*} value * @returns {Function} */ fake.rejects = function rejects(value) { // eslint-disable-next-line jsdoc/require-jsdoc function f() { return Promise.reject(getError(value)); } return wrapFunc(f); }; /** * Returns a `fake` that calls the callback with the defined arguments. * * @example * function callback() { * console.log(arguments.join("*")); * } * * const f1 = sinon.fake.yields("apple", "pie"); * * f1(callback); * // "apple*pie" * * @memberof fake * @returns {Function} */ fake.yields = function yields() { const values = slice(arguments); // eslint-disable-next-line jsdoc/require-jsdoc 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. * * @example * function callback() { * console.log(arguments.join("*")); * } * * const f1 = sinon.fake.yields("apple", "pie"); * * f1(callback); * * setTimeout(() => { * // "apple*pie" * }); * * @memberof fake * @returns {Function} */ fake.yieldsAsync = function yieldsAsync() { const values = slice(arguments); // eslint-disable-next-line jsdoc/require-jsdoc 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 {Function} f * @returns {Function} */ 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.firstArg = firstArg; proxy.lastArg = lastArg; proxy.callback = callback; return f && f.apply(this, arguments); }; const proxy = createProxy(fakeInstance, f || fakeInstance); proxy.displayName = "fake"; proxy.id = `fake#${uuid++}`; return proxy; } /** * Returns an Error instance from the passed value, if the value is not * already an Error instance. * * @private * @param {*} value [description] * @returns {Error} [description] */ function getError(value) { return value instanceof Error ? value : new Error(value); } },{"./proxy":17,"./util/core/next-tick":33,"@sinonjs/commons":46}],11:[function(require,module,exports){ "use strict"; const arrayProto = require("@sinonjs/commons").prototypes.array; const proxyInvoke = require("./proxy-invoke"); const proxyCallToString = require("./proxy-call").toString; const timesInWords = require("./util/core/times-in-words"); const extend = require("./util/core/extend"); const match = require("@sinonjs/samsam").createMatcher; const stub = require("./stub"); const assert = require("./assert"); const deepEqual = require("@sinonjs/samsam").deepEqual; const inspect = require("util").inspect; const valueToString = require("@sinonjs/commons").valueToString; const every = arrayProto.every; const forEach = arrayProto.forEach; const push = arrayProto.push; const slice = arrayProto.slice; function callCountInWords(callCount) { if (callCount === 0) { return "never called"; } return `called ${timesInWords(callCount)}`; } function expectedCallCountInWords(expectation) { const min = expectation.minCalls; const max = expectation.maxCalls; if (typeof min === "number" && typeof max === "number") { let str = timesInWords(min); if (min !== max) { str = `at least ${str} and at most ${timesInWords(max)}`; } return str; } if (typeof min === "number") { return `at least ${timesInWords(min)}`; } return `at most ${timesInWords(max)}`; } function receivedMinCalls(expectation) { const hasMinLimit = typeof expectation.minCalls === "number"; return !hasMinLimit || expectation.callCount >= expectation.minCalls; } function receivedMaxCalls(expectation) { if (typeof expectation.maxCalls !== "number") { return false; } return expectation.callCount === expectation.maxCalls; } function verifyMatcher(possibleMatcher, arg) { const isMatcher = match.isMatcher(possibleMatcher); return (isMatcher && possibleMatcher.test(arg)) || true; } const mockExpectation = { minCalls: 1, maxCalls: 1, create: function create(methodName) { const expectation = extend.nonEnum(stub(), mockExpectation); delete expectation.create; expectation.method = methodName; return expectation; }, invoke: function invoke(func, thisValue, args) { this.verifyCallAllowed(thisValue, args); return proxyInvoke.apply(this, arguments); }, atLeast: function atLeast(num) { if (typeof num !== "number") { throw new TypeError(`'${valueToString(num)}' is not number`); } if (!this.limitsSet) { this.maxCalls = null; this.limitsSet = true; } this.minCalls = num; return this; }, atMost: function atMost(num) { if (typeof num !== "number") { throw new TypeError(`'${valueToString(num)}' is not number`); } if (!this.limitsSet) { this.minCalls = null; this.limitsSet = true; } this.maxCalls = num; return this; }, never: function never() { return this.exactly(0); }, once: function once() { return this.exactly(1); }, twice: function twice() { return this.exactly(2); }, thrice: function thrice() { return this.exactly(3); }, exactly: function exactly(num) { if (typeof num !== "number") { throw new TypeError(`'${valueToString(num)}' is not a number`); } this.atLeast(num); return this.atMost(num); }, met: function met() { return !this.failed && receivedMinCalls(this); }, verifyCallAllowed: function verifyCallAllowed(thisValue, args) { const expectedArguments = this.expectedArguments; if (receivedMaxCalls(this)) { this.failed = true; mockExpectation.fail( `${this.method} already called ${timesInWords(this.maxCalls)}`, ); } if ("expectedThis" in this && this.expectedThis !== thisValue) { mockExpectation.fail( `${this.method} called with ${valueToString( thisValue, )} as thisValue, expected ${valueToString(this.expectedThis)}`, ); } if (!("expectedArguments" in this)) { return; } if (!args) { mockExpectation.fail( `${this.method} received no arguments, expected ${inspect( expectedArguments, )}`, ); } if (args.length < expectedArguments.length) { mockExpectation.fail( `${this.method} received too few arguments (${inspect( args, )}), expected ${inspect(expectedArguments)}`, ); } if ( this.expectsExactArgCount && args.length !== expectedArguments.length ) { mockExpectation.fail( `${this.method} received too many arguments (${inspect( args, )}), expected ${inspect(expectedArguments)}`, ); } forEach( expectedArguments, function (expectedArgument, i) { if (!verifyMatcher(expectedArgument, args[i])) { mockExpectation.fail( `${this.method} received wrong arguments ${inspect( args, )}, didn't match ${String(expectedArguments)}`, ); } if (!deepEqual(args[i], expectedArgument)) { mockExpectation.fail( `${this.method} received wrong arguments ${inspect( args, )}, expected ${inspect(expectedArguments)}`, ); } }, this, ); }, allowsCall: function allowsCall(thisValue, args) { const expectedArguments = this.expectedArguments; if (this.met() && receivedMaxCalls(this)) { return false; } if ("expectedThis" in this && this.expectedThis !== thisValue) { return false; } if (!("expectedArguments" in this)) { return true; } // eslint-disable-next-line no-underscore-dangle const _args = args || []; if (_args.length < expectedArguments.length) { return false; } if ( this.expectsExactArgCount && _args.length !== expectedArguments.length ) { return false; } return every(expectedArguments, function (expectedArgument, i) { if (!verifyMatcher(expectedArgument, _args[i])) { return false; } if (!deepEqual(_args[i], expectedArgument)) { return false; } return true; }); }, withArgs: function withArgs() { this.expectedArguments = slice(arguments); return this; }, withExactArgs: function withExactArgs() { this.withArgs.apply(this, arguments); this.expectsExactArgCount = true; return this; }, on: function on(thisValue) { this.expectedThis = thisValue; return this; }, toString: function () { const args = slice(this.expectedArguments