Socket
Socket
Sign inDemoInstall

spy4js

Package Overview
Dependencies
1
Maintainers
1
Versions
75
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.9.1 to 2.0.0

dist/mock.js

155

dist/registry.js

@@ -1,134 +0,73 @@

'use strict';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
value: true
});
exports.SpyRegistry = undefined;
exports.SpyRegistry = SpyRegistry;
var _utils = require('./utils');
var _utils = require("./utils");
var restoreAttributeForEntry = function restoreAttributeForEntry(value) {
var obj = value.obj,
method = value.method,
methodName = value.methodName;
var obj = value.obj,
method = value.method,
methodName = value.methodName;
if (obj) {
obj[methodName] = method;
}
if (obj) {
obj[methodName] = method;
}
};
/**
* The SpyRegistry is a class to handle the
* correct restoration of spied objects.
*
* You may push an objects information about
* a spied method to store it and be able to
* restore it at any time.
* Consider the SpyRegistry as information storage
* for spied objects.
*
* @constructor
*/
/**
* This file is part of spy4js which is released under MIT license.
*
* The LICENSE file can be found in the root directory of this project.
*
*
*/
function SpyRegistry() {
if (!(this instanceof SpyRegistry)) {
throw new Error('\n\nPlease make sure to use this constructor only with "new" keyword.\n\n');
}
function SpyRegistry() {
if (!(this instanceof SpyRegistry)) {
throw new Error('\n\nPlease make sure to use this constructor only with "new" keyword.\n\n');
}
this.register = {};
this.persReg = {};
this.registerCount = 0;
this.register = {};
this.persReg = {};
this.registerCount = 0;
}
/**
* If called, the SypRegistry will be resetting to its initial state.
* Exception: the unique register count will not be touched.
* Meaning that all stored object information will be restored
* to their individual previous state.
*/
SpyRegistry.prototype.restoreAll = function () {
(0, _utils.forEach)(this.register, function (ignored, entry) {
restoreAttributeForEntry(entry);
});
this.register = {};
(0, _utils.forEach)(this.register, function (ignored, entry) {
restoreAttributeForEntry(entry);
});
this.register = {};
};
/**
* If called, the SpyRegistry will restore the object,
* which was registered at given index and is getting lose
* of the stored information.
*
* If the registry entry for the given index does not exist,
* nothing will happen.
*
* @param {number} index -> the unique identifier of stored information.
*/
SpyRegistry.prototype.restore = function (index) {
var entry = this.register[index];
if (entry) {
restoreAttributeForEntry(entry);
delete this.register[index];
}
var entry = this.register[index];
if (entry) {
restoreAttributeForEntry(entry);
delete this.register[index];
}
};
/**
* If called, the SpyRegistry will store the given information.
* The unique identifier index will be returned.
*
* @param {Object} obj -> The related object, which will be spied.
* @param {string} methodName -> The name of the mocked method.
* @return {number} -> The unique store index.
*/
SpyRegistry.prototype.push = function (obj, methodName) {
this.registerCount += 1;
this.register[this.registerCount] = {
obj: obj,
method: obj[methodName],
methodName: methodName
};
return this.registerCount;
this.registerCount += 1;
this.register[this.registerCount] = {
obj: obj,
method: obj[methodName],
methodName: methodName
};
return this.registerCount;
};
/**
* If called, the stored method for the corresponding index
* will be returned. If the registry entry does not exist,
* undefined will be returned.
*
* @param {number} index -> the unique identifier of stored information.
* @return {any} -> Any stored information can be returned.
* BUT: Usually this method returns a function or
* undefined.
*/
SpyRegistry.prototype.getOriginalMethod = function (index) {
var entry = this.register[index];
if (entry) {
return entry.method;
}
var entry = this.register[index];
if (entry) {
return entry.method;
}
};
/**
* If called, the stored method will be moved from the standard
* registry into the persistent registry or vice versa.
* This can make restore and restoreAll having no effect anymore.
*
* @param {number} index -> the unique identifier of stored information.
* @param {boolean} intoPersReg -> boolean to determine the moving
* direction.
*/
SpyRegistry.prototype.persist = function (index, intoPersReg) {
var fromReg = intoPersReg ? this.register : this.persReg;
var toReg = intoPersReg ? this.persReg : this.register;
var entry = fromReg[index];
if (entry) {
toReg[index] = entry;
delete fromReg[index];
}
};
var fromReg = intoPersReg ? this.register : this.persReg;
var toReg = intoPersReg ? this.persReg : this.register;
var entry = fromReg[index];
exports.SpyRegistry = SpyRegistry;
if (entry) {
toReg[index] = entry;
delete fromReg[index];
}
};

@@ -1,2 +0,2 @@

'use strict';
"use strict";

@@ -6,18 +6,12 @@ Object.defineProperty(exports, "__esModule", {

});
exports.serialize = undefined;
exports.serialize = void 0;
var _utils = require('./utils');
var _utils = require("./utils");
var _serializeAsCode = require('serialize-as-code');
var _serializeAsCode = require("serialize-as-code");
/**
* This file is part of spy4js which is released under MIT license.
*
* The LICENSE file can be found in the root directory of this project.
*
*
*/
var serialize = _serializeAsCode.Serializer.create(function (o) {
return o === _utils.IGNORE && '>IGNORED<' || undefined;
});
var serialize = exports.serialize = _serializeAsCode.Serializer.create(function (o) {
return o === _utils.IGNORE && '>IGNORED<' || undefined;
});
exports.serialize = serialize;

@@ -1,788 +0,400 @@

'use strict';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
value: true
});
exports.Spy = undefined;
exports.Spy = void 0;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _utils = require("./utils");
var _utils = require('./utils');
var _registry = require("./registry");
var _registry = require('./registry');
var _serializer = require("./serializer");
var _serializer = require('./serializer');
var _mock = require("./mock");
var _testSuite = require("./test-suite");
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /**
* This file is part of spy4js which is released under MIT license.
*
* The LICENSE file can be found in the root directory of this project.
*
*
*/
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
/**
*
* Instantiating the SpyRegistry to handle all
* mocked object relative information and
* restore their functionality if requested.
*
*/
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
var registry = new _registry.SpyRegistry();
var __LOCK__ = true;
/**
* Those symbols are used to protect the private spy properties from outer manipulation by mistake.
*/
var Symbols = {
name: Symbol.for('__Spy_name__'),
isSpy: Symbol.for('__Spy_isSpy__'),
func: Symbol.for('__Spy_func__'),
calls: Symbol.for('__Spy_calls__'),
config: Symbol.for('__Spy_config__'),
index: Symbol.for('__Spy_index__')
name: Symbol.for('__Spy_name__'),
isSpy: Symbol.for('__Spy_isSpy__'),
func: Symbol.for('__Spy_func__'),
calls: Symbol.for('__Spy_calls__'),
config: Symbol.for('__Spy_config__'),
index: Symbol.for('__Spy_index__')
};
/**
* Initial default settings for every
* spy instance. Can be modified only
* implicitly by "Spy.configure".
*
* @type {{useOwnEquals: boolean}}
*/
var DefaultSettings = {
useOwnEquals: true
useOwnEquals: true
};
var SpyFunctions = {
/**
* Configures this spy behaviour in a special
* way. Passing in an object that contains
* meaningful attributes can configure:
*
* - useOwnEquals:boolean -> toggles the usage of own
* implementation of "equals"
* matcher, e.g. for comparing
* call params with "wasCalledWith".
*
* - persistent:boolean -> toggles the persistence of the spy.
* I.e. making it restorable or not.
* Throws for not mocking spies.
*
* @param {Object} config <- An object containing attributes
* for special configuration
* @return {SpyInstance} <- BuilderPattern.
*/
configure: function configure(config) {
if (config.useOwnEquals !== undefined) {
this[Symbols.config].useOwnEquals = config.useOwnEquals;
}
if (config.persistent !== undefined) {
if (!this[Symbols.index]) {
throw new Error('\n\n' + this[Symbols.name] + ' can not' + ' be configured to be persistent!' + ' It does not mock any object.');
}
this[Symbols.config].persistent = config.persistent;
registry.persist(this[Symbols.index], this[Symbols.config].persistent);
}
return this;
},
configure: function configure(config) {
if (config.useOwnEquals !== undefined) {
this[Symbols.config].useOwnEquals = config.useOwnEquals;
}
if (config.persistent !== undefined) {
if (!this[Symbols.index]) {
throw new Error("\n\n".concat(this[Symbols.name], " can not") + ' be configured to be persistent!' + ' It does not mock any object.');
}
/**
* Accepts multiple functions. If called more often,
* calling always the last supplied function.
*
* @param {Array<Function>} funcs
* -> The iterative provided functions
* can be accessed as array.
* And will be called one by one
* for each made call on the spy.
*
* @return {SpyInstance} <- BuilderPattern.
*/
calls: function calls() {
for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {
funcs[_key] = arguments[_key];
}
this[Symbols.config].persistent = config.persistent;
registry.persist(this[Symbols.index], this[Symbols.config].persistent);
}
if (funcs.length === 0) {
// no arguments provided
this[Symbols.func] = function () {};
return this;
}
return this;
},
calls: function calls() {
for (var _len = arguments.length, funcs = new Array(_len), _key = 0; _key < _len; _key++) {
funcs[_key] = arguments[_key];
}
var max = funcs.length - 1;
var counter = -1;
if (funcs.length === 0) {
this[Symbols.func] = function () {};
this[Symbols.func] = function () {
counter++;
return funcs[max < counter ? max : counter].apply(funcs, arguments);
};
return this;
}
return this;
},
var max = funcs.length - 1;
var counter = -1;
this[Symbols.func] = function () {
counter++;
return funcs[max < counter ? max : counter].apply(funcs, arguments);
};
/**
* Accepts multiple return values. If called more often,
* returns always the last supplied return value.
*
* @param {Array<any>} args -> The iterative provided arguments
* can be accessed as array.
* And will be returned one by one
* for each made call.
*
* @return {SpyInstance} <- BuilderPattern.
*/
returns: function returns() {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return this;
},
returns: function returns() {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return this.calls.apply(this, _toConsumableArray(args.map(function (arg) {
return function () {
return arg;
};
})));
},
return this.calls.apply(this, _toConsumableArray(args.map(function (arg) {
return function () {
return arg;
};
})));
},
resolves: function resolves() {
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
return this.returns.apply(this, _toConsumableArray(args.map(function (arg) {
return Promise.resolve(arg);
})));
},
rejects: function rejects() {
var _this = this;
/**
* Accepts multiple values, which will be resolved sequentially.
* If called more often, resolves always the last supplied value.
*
* @param {Array<any>} args -> The iterative provided arguments
* can be accessed as array.
* And will be resolved one by one
* for each made call.
*
* @return {SpyInstance} <- BuilderPattern.
*/
resolves: function resolves() {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
for (var _len4 = arguments.length, msgOrErrors = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
msgOrErrors[_key4] = arguments[_key4];
}
return this.returns.apply(this, _toConsumableArray(args.map(function (arg) {
return Promise.resolve(arg);
})));
},
return this.calls.apply(this, _toConsumableArray(msgOrErrors.map(function (msgOrError) {
return function () {
return Promise.reject((0, _utils.toError)(msgOrError, _this[Symbols.name]));
};
})));
},
throws: function throws(msgOrError) {
var _this2 = this;
this[Symbols.func] = function () {
throw (0, _utils.toError)(msgOrError, _this2[Symbols.name]);
};
/**
* Accepts multiple values, which will be rejected sequentially.
* If called more often, rejects always the last supplied value.
*
* @param {Array<OptionalMessageOrError>} msgOrErrors
* -> The iterative provided arguments
* can be accessed as array.
* And will be rejected one by one
* for each made call.
*
* @return {SpyInstance} <- BuilderPattern.
*/
rejects: function rejects() {
var _this = this;
return this;
},
reset: function reset() {
this[Symbols.calls] = [];
return this;
},
restore: function restore() {
if (this[Symbols.config].persistent) {
throw new Error("\n\n".concat(this[Symbols.name], " can not be restored!") + ' It was configured to be persistent.');
}
for (var _len4 = arguments.length, msgOrErrors = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
msgOrErrors[_key4] = arguments[_key4];
}
registry.restore(this[Symbols.index]);
return this;
},
transparent: function transparent() {
return this.transparentAfter(0);
},
transparentAfter: function transparentAfter(callCount) {
var _this3 = this;
return this.calls.apply(this, _toConsumableArray(msgOrErrors.map(function (msgOrError) {
return function () {
return Promise.reject((0, _utils.toError)(msgOrError, _this[Symbols.name]));
};
})));
},
var oldFunc = this[Symbols.func];
this[Symbols.func] = function () {
if (_this3[Symbols.calls].length > callCount) {
var originalMethod = registry.getOriginalMethod(_this3[Symbols.index]);
/**
* Will make the spy throw an Error, if called next time.
* The error message can be provided as parameter.
*
* @param {OptionalMessageOrError} msgOrError -> Will be the error message.
*
* @return {SpyInstance} <- BuilderPattern
*/
throws: function throws(msgOrError) {
var _this2 = this;
this[Symbols.func] = function () {
throw (0, _utils.toError)(msgOrError, _this2[Symbols.name]);
};
return this;
},
/**
* Deletes all notices of made calls with this spy.
*
* @return {SpyInstance} <- BuilderPattern
*/
reset: function reset() {
this[Symbols.calls] = [];
return this;
},
/**
* Restores the last by this spy manipulated object
* and removes this special mock.
*
* Restoring objects does not disable any
* other behaviours/features of the spies.
*
* If the spy was configured persistent, than this
* method will throw an exception.
*
* Other than "Spy.restoreAll" this method only removes
* a maximum of one mock.
*
* @return {SpyInstance} <- BuilderPattern
*/
restore: function restore() {
if (this[Symbols.config].persistent) {
throw new Error('\n\n' + this[Symbols.name] + ' can not be restored!' + ' It was configured to be persistent.');
if (originalMethod) {
return originalMethod.apply(void 0, arguments);
}
registry.restore(this[Symbols.index]);
return this;
},
return;
}
/**
* Makes the spy behave like the mocked
* function. If no function was mocked by
* this spy, it will do nothing if called.
*
* This function works exactly like
* spy.transparentAfter(0).
*
* For example:
* const spy = Spy.on(someObject, 'someFunc');
* someObject.someFunc(); // calls only the spy
* spy.transparent();
* someObject.someFunc(); // behaves like calling the original method
*
* @return {SpyInstance} <- BuilderPattern
*/
transparent: function transparent() {
return this.transparentAfter(0);
},
return oldFunc.apply(void 0, arguments);
};
return this;
},
wasCalled: function wasCalled(callCount) {
var madeCalls = this[Symbols.calls].length;
/**
* If called with n as callCount this will make
* the spy call the mocked function after called
* the n'th time. For any spy that does not mock
* any objects attribute, this will make the spy
* do nothing if called after the n'th time.
*
* If the mocked function will get called again,
* the made calls will still be registered.
*
* For example:
* Spy.on(someObject, 'someFunc').transparentAfter(2);
* someObject.someFunc(); // calls only the spy
* someObject.someFunc(); // calls only the spy
* someObject.someFunc(); // behaves like calling the original method
*
* @param {number} callCount <- The number after which the mocked function
* should be called again.
*
* @return {SpyInstance} <- BuilderPattern
*/
transparentAfter: function transparentAfter(callCount) {
var _this3 = this;
if (typeof callCount === 'number') {
if (madeCalls !== callCount) {
throw new Error("\n\n".concat(this[Symbols.name], " was called ").concat(madeCalls, " times,") + " but there were expected ".concat(callCount, " calls.\n\n") + 'Actually there were:\n\n' + this.showCallArguments());
}
} else if (madeCalls === 0) {
throw new Error("\n\n".concat(this[Symbols.name], " was never called!\n\n"));
}
},
hasCallHistory: function hasCallHistory() {
var _this4 = this;
var oldFunc = this[Symbols.func];
this[Symbols.func] = function () {
// before the function call is executed,
// the call arguments were already saved
// -> so we are interested if the made calls
// are more than the call count were we
// need to modify the behavior
if (_this3[Symbols.calls].length > callCount) {
var originalMethod = registry.getOriginalMethod(_this3[Symbols.index]);
if (originalMethod) {
return originalMethod.apply(undefined, arguments);
}
return;
}
return oldFunc.apply(undefined, arguments);
};
return this;
},
var madeCalls = this[Symbols.calls];
for (var _len5 = arguments.length, callHistory = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
callHistory[_key5] = arguments[_key5];
}
/**
* Checks if the spy was called callCount times often.
*
* If callCount is not provided then it only
* checks if the spy was called at least once.
*
* Throws an error if the expectation is wrong.
*
* @param {?number} callCount -> Is the number of expected calls made.
*/
wasCalled: function wasCalled(callCount) {
var madeCalls = this[Symbols.calls].length;
if (typeof callCount === 'number') {
if (madeCalls !== callCount) {
throw new Error('\n\n' + this[Symbols.name] + ' was called ' + madeCalls + ' times,' + (' but there were expected ' + callCount + ' calls.\n\n') + 'Actually there were:\n\n' + this.showCallArguments());
}
} else if (madeCalls === 0) {
throw new Error('\n\n' + this[Symbols.name] + ' was never called!\n\n');
}
},
var callCount = callHistory.length;
if (madeCalls.length !== callCount) {
throw new Error("\n\n".concat(this[Symbols.name], " was called ").concat(madeCalls.length, " times,") + " but the expected call history includes exactly ".concat(callHistory.length, " calls.\n\n") + 'Actually there were:\n\n' + this.showCallArguments());
}
/**
* Checks if the spy was call history matches the expectation.
*
* The call history has to match the call count and order.
* Single arguments will be automatically wrapped as array, e.g.:
* 1, 2, 3 -> [1], [2], [3]
* ** Inspired by jest test.each **
*
* Throws an error if the expectation is wrong.
*
* @param {Array<Array<any> | any>} callHistory
* -> Are the expected made call arguments in correct order.
*/
hasCallHistory: function hasCallHistory() {
var _this4 = this;
var modifiedCallHistory = callHistory.map(function (arg) {
return Array.isArray(arg) ? arg : [arg];
});
var hasErrors = false;
var diffInfo = madeCalls.map(function (call, index) {
var diff = (0, _utils.differenceOf)(call.args, modifiedCallHistory[index], _this4[Symbols.config]);
if (diff) hasErrors = true;
return diff;
});
if (hasErrors) throw new Error("\n\n".concat(this[Symbols.name], " was considered") + ' to be called with the following arguments in the given order:\n\n' + "".concat(modifiedCallHistory.map(function (entry, index) {
return "call ".concat(index, ": ").concat((0, _serializer.serialize)(entry));
}).join('\n'), "\n\n") + 'Actually there were:\n\n' + this.showCallArguments(diffInfo));
},
wasNotCalled: function wasNotCalled() {
var madeCalls = this[Symbols.calls];
var madeCalls = this[Symbols.calls];
if (madeCalls.length !== 0) {
throw new Error("\n\n".concat(this[Symbols.name], " was not") + ' considered to be called.\n\n' + 'Actually there were:\n\n' + this.showCallArguments());
}
},
wasCalledWith: function wasCalledWith() {
var madeCalls = this[Symbols.calls];
for (var _len5 = arguments.length, callHistory = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
callHistory[_key5] = arguments[_key5];
}
if (madeCalls.length === 0) {
throw new Error("\n\n".concat(this[Symbols.name], " was never called!\n\n"));
}
var callCount = callHistory.length;
if (madeCalls.length !== callCount) {
throw new Error('\n\n' + this[Symbols.name] + ' was called ' + madeCalls.length + ' times,' + (' but the expected call history includes exactly ' + callHistory.length + ' calls.\n\n') + 'Actually there were:\n\n' + this.showCallArguments());
}
var modifiedCallHistory = callHistory.map(function (arg) {
return Array.isArray(arg) ? arg : [arg];
});
var hasErrors = false;
var diffInfo = madeCalls.map(function (call, index) {
var diff = (0, _utils.differenceOf)(call.args, modifiedCallHistory[index], _this4[Symbols.config]);
if (diff) hasErrors = true;
return diff;
});
if (hasErrors) throw new Error('\n\n' + this[Symbols.name] + ' was considered' + ' to be called with the following arguments in the given order:\n\n' + (modifiedCallHistory.map(function (entry, index) {
return 'call ' + index + ': ' + (0, _serializer.serialize)(entry);
}).join('\n') + '\n\n') + 'Actually there were:\n\n' + this.showCallArguments(diffInfo));
},
var diffInfo = [];
for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
args[_key6] = arguments[_key6];
}
/**
* Checks that the spy was never called.
* Throws an error if the spy was called at least once.
*/
wasNotCalled: function wasNotCalled() {
var madeCalls = this[Symbols.calls];
if (madeCalls.length !== 0) {
throw new Error('\n\n' + this[Symbols.name] + ' was not' + ' considered to be called.\n\n' + 'Actually there were:\n\n' + this.showCallArguments());
}
},
for (var i = 0; i < madeCalls.length; i++) {
var diff = (0, _utils.differenceOf)(madeCalls[i].args, args, this[Symbols.config]);
if (!diff) {
return;
}
/**
* Checks if the spy was called with the provided arguments.
*
* Throws an error if the expectation is wrong.
*
* For example:
* const spy = new Spy();
* spy(arg1, arg2, arg3);
* spy(arg4, arg5);
* spy.wasCalledWith(arg1, arg2, arg3); // no error
* spy.wasCalledWith(arg4, arg5); // no error
* spy.wasCalledWith(arg1); // error!!!
*
* @param {Array<any>} args -> The expected arguments
* for any made call.
*/
wasCalledWith: function wasCalledWith() {
var madeCalls = this[Symbols.calls];
if (madeCalls.length === 0) {
throw new Error('\n\n' + this[Symbols.name] + ' was never called!\n\n');
}
var diffInfo = [];
diffInfo.push(diff);
}
for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
args[_key6] = arguments[_key6];
}
throw new Error("\n\n".concat(this[Symbols.name], " was considered") + ' to be called with the following arguments:\n\n' + " --> ".concat((0, _serializer.serialize)(args), "\n\n") + 'Actually there were:\n\n' + this.showCallArguments(diffInfo));
},
wasNotCalledWith: function wasNotCalledWith() {
var errorOccurred = false;
for (var i = 0; i < madeCalls.length; i++) {
var diff = (0, _utils.differenceOf)(madeCalls[i].args, args, this[Symbols.config]);
if (!diff) {
return;
}
diffInfo.push(diff);
}
throw new Error('\n\n' + this[Symbols.name] + ' was considered' + ' to be called with the following arguments:\n\n' + (' --> ' + (0, _serializer.serialize)(args) + '\n\n') + 'Actually there were:\n\n' + this.showCallArguments(diffInfo));
},
for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
args[_key7] = arguments[_key7];
}
try {
this.wasCalledWith.apply(this, args);
} catch (e) {
errorOccurred = true;
}
/**
* Checks if the spy was NOT called with the provided arguments.
* This method checks the direct opposite of the method
* spy.wasCalledWith.
*
* It throws an error if the upper method would not.
*
* For example:
* const spy = new Spy();
* spy(arg1, arg2, arg3);
* spy(arg4, arg5);
* spy.wasCalledWith(arg1); // no error
* spy.wasCalledWith(arg4, arg3); // no error
* spy.wasCalledWith(arg4, arg5); // error!!!
*
* @param {Array<any>} args -> The not expected arguments
* for any made call.
*/
wasNotCalledWith: function wasNotCalledWith() {
var errorOccurred = false;
if (!errorOccurred) {
throw new Error("\n\n".concat(this[Symbols.name], " was called") + ' unexpectedly with the following arguments:\n\n' + " --> ".concat((0, _serializer.serialize)(args), "\n\n"));
}
},
getCallArguments: function getCallArguments() {
var callNr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var madeCalls = this[Symbols.calls];
for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
args[_key7] = arguments[_key7];
}
if (callNr % 1 !== 0 || callNr >= madeCalls.length) {
throw new Error("\n\nThe provided callNr \"".concat(callNr, "\" was not valid.\n\n") + "Made calls for ".concat(this[Symbols.name], ":\n\n") + this.showCallArguments());
}
try {
this.wasCalledWith.apply(this, _toConsumableArray(args));
} catch (e) {
errorOccurred = true;
}
if (!errorOccurred) {
throw new Error('\n\n' + this[Symbols.name] + ' was called' + ' unexpectedly with the following arguments:\n\n' + (' --> ' + (0, _serializer.serialize)(args) + '\n\n'));
}
},
return madeCalls[callNr].args;
},
getCallArgument: function getCallArgument() {
var callNr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var argNr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return this.getCallArguments(callNr)[argNr];
},
getCallCount: function getCallCount() {
return this[Symbols.calls].length;
},
showCallArguments: function showCallArguments() {
var additionalInformation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var madeCalls = this[Symbols.calls];
if (madeCalls.length === 0) {
return "".concat(this[Symbols.name], " was never called!\n");
}
/**
* This method returns the call arguments of the
* n'th made call as array. If less than n calls were made,
* it will throw an error.
*
* By default n = 1. This corresponds to callNr = 0.
*
* For example:
* const spy = new Spy();
* spy(arg1, arg2, arg3);
* spy.getCallArguments(); // returns [arg1, arg2, arg3]
*
* @param {number} callNr -> represents the callNr for which
* the call argument should be returned.
*
* @return {Array<any>} -> the call arguments of the (callNr + 1)'th call.
*/
getCallArguments: function getCallArguments() {
var callNr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var response = '';
var madeCalls = this[Symbols.calls];
if (callNr % 1 !== 0 || callNr >= madeCalls.length) {
throw new Error('\n\nThe provided callNr "' + callNr + '" was not valid.\n\n' + ('Made calls for ' + this[Symbols.name] + ':\n\n') + this.showCallArguments());
}
return madeCalls[callNr].args;
},
for (var i = 0; i < madeCalls.length; i++) {
var _args = (0, _serializer.serialize)(madeCalls[i].args);
response += "call ".concat(i, ": ").concat(_args, "\n");
/**
* This method returns the m'th call argument of the
* n'th made call. If less than n calls were made, it will throw
* an error.
*
* By default n = 1. This corresponds to callNr = 0.
* By default m = 1. This corresponds to argNr = 0.
*
* For example:
* const spy = new Spy();
* spy(arg1, arg2, arg3);
* spy(arg4, arg5, arg6);
* spy.getCallArgument() === arg1; // true
* spy.getCallArgument(1) === arg4; // true
* spy.getCallArgument(0, 2) === arg3; // true
* spy.getCallArgument(1, 1) === arg5; // true
*
* spy.getCallArgument(1, 5) === undefined; // true
* spy.getCallArgument(2); // throws an exception
*
* @param {number} callNr -> represents the callNr for which
* a call argument should be returned.
* @param {number} argNr -> represents position of the argument
* when the corresponding call was made.
*
* @return {any} -> the (argNr + 1)'th call argument
* of the (callNr + 1)'th call.
*/
getCallArgument: function getCallArgument() {
var callNr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var argNr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
if (additionalInformation[i]) {
response += " ".concat(additionalInformation[i], "\n");
}
}
return this.getCallArguments(callNr)[argNr];
},
/**
* This method returns the number of made calls on the spy.
*
* @return {number} -> the number of made calls.
*/
getCallCount: function getCallCount() {
return this[Symbols.calls].length;
},
/**
* This method returns a formatted text string for debugging
* made calls with the given Spy. It is used also internally
* if some wrong assertions were made on the Spy.
* Some sample:
*
* call 0: [{"_key":"test1"}]
* call 1: [{"_key":"test1"},{"_key":"test2"}]
* call 2: [{"_key":"test3"},{"_key":"test2"},{"_key":"test1"}]
* call 3: [{"_key":"test2"}]
*
* If an array of strings is provided, the given strings will
* be printed just below params of each call.
*
* Some sample: additionalInformation = [
* '-> 0 / _key / different string',
* '-> 1 / _key / different object types'
* ]
*
* call 0: [{"_key":"test1"}]
* -> 0 / _key / different string
* call 1: [{"_key":"test1"},{"_key":"test2"}]
* -> 1 / _key / different object types
* call 2: [{"_key":"test3"},{"_key":"test2"},{"_key":"test1"}]
* call 3: [{"_key":"test2"}]
*
* @param {Array<string>} additionalInformation
* -> will be displayed below each call information
* as additional information.
*
* @return {string} -> The information about made calls.
*/
showCallArguments: function showCallArguments() {
var additionalInformation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var madeCalls = this[Symbols.calls];
if (madeCalls.length === 0) {
return this[Symbols.name] + ' was never called!\n';
}
var response = '';
for (var i = 0; i < madeCalls.length; i++) {
var _args = (0, _serializer.serialize)(madeCalls[i].args);
response += 'call ' + i + ': ' + _args + '\n';
if (additionalInformation[i]) {
response += ' ' + additionalInformation[i] + '\n';
}
}
return response;
}
return response;
}
};
var Spy = function () {
/**
* This constructor does instantiate a new spy
* object.
*
* This spy is callable.
* It does inherit all Spy specific methods below.
* It holds additional (private) fields:
* _name:string -> Will be displayed in all displayed
* error messages.
* _isSpy:boolean -> Always true for spies.
* _func:Function -> The internal function, that will
* actually we called, when calling
* the spy.
* _calls:Array<{arguments:Array<any>}>
* -> Stores the arguments with whom the spy was called.
* Each call adds another entry in the calls array.
* _config = {useOwnEquals: boolean} -> internal spy config.
*
*
* @param {string} name -> the identifier of the spy.
* Useful for debugging issues.
* @param {string} __mock -> DO NOT USE.
*
* @constructor
*/
function Spy() {
var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'the spy';
var __mock = arguments[1];
function Spy() {
var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'the spy';
_classCallCheck(this, Spy);
var __mock = arguments.length > 1 ? arguments[1] : undefined;
var spy = function spy() {
for (var _len8 = arguments.length, args = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
args[_key8] = arguments[_key8];
}
_classCallCheck(this, Spy);
spy[Symbols.calls].push({ args: args });
return spy[Symbols.func].apply(spy, args);
};
if (__mock && !__LOCK__) {
spy[Symbols.index] = registry.push(__mock.obj, __mock.methodName);
} else {
spy[Symbols.index] = null;
}
spy[Symbols.name] = name;
spy[Symbols.isSpy] = true;
spy[Symbols.func] = function () {};
spy[Symbols.calls] = [];
spy[Symbols.config] = { useOwnEquals: DefaultSettings.useOwnEquals };
(0, _utils.forEach)(SpyFunctions, function (key, value) {
spy[key] = value;
});
return spy;
}
var spy = function spy() {
for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
args[_key8] = arguments[_key8];
}
/**
* This static method can be used to configure
* the default behaviour of created spy instances.
*
* For example,
*
* Spy.configure({useOwnEquals: false});
*
* would initially configure every spy to not
* favor own "equals" implementation while
* comparing any objects.
*
* @param {Object} config <- Holds the configuration params.
*/
spy[Symbols.calls].push({
args: args
});
return spy[Symbols.func].apply(spy, args);
};
if (__mock && !__LOCK__) {
spy[Symbols.index] = registry.push(__mock.obj, __mock.methodName);
} else {
spy[Symbols.index] = null;
}
_createClass(Spy, null, [{
key: 'configure',
value: function configure(config) {
if (config.useOwnEquals !== undefined) {
DefaultSettings.useOwnEquals = config.useOwnEquals;
}
}
spy[Symbols.name] = name;
spy[Symbols.isSpy] = true;
/**
* This static attribute can be used to ignore the match
* of a specific argument when using "wasCalledWith".
*/
spy[Symbols.func] = function () {};
spy[Symbols.calls] = [];
spy[Symbols.config] = {
useOwnEquals: DefaultSettings.useOwnEquals
};
(0, _utils.forEach)(SpyFunctions, function (key, value) {
spy[key] = value;
});
return spy;
}
/**
* This static attribute can be called with a custom
* comparator that returns a boolean indicating if the
* comparison holds. Can be used when calling e.g. "wasCalledWith".
*/
_createClass(Spy, null, [{
key: "configure",
value: function configure(config) {
if (config.useOwnEquals !== undefined) {
DefaultSettings.useOwnEquals = config.useOwnEquals;
}
}, {
key: 'on',
(0, _testSuite.configureTestSuite)({
afterEach: config.afterEach,
beforeEach: config.beforeEach
});
}
}, {
key: "on",
value: function on(obj, methodName) {
var method = obj[methodName];
if (!(method instanceof Function)) {
throw new Error("The object attribute '".concat(methodName, "' ") + "was: ".concat((0, _serializer.serialize)(method), "\n\n") + 'You should only spy on functions!');
}
/**
* This static method is an alternative way to
* create a Spy which mocks the an objects attribute.
*
* The attribute of the object "obj[methodName]" will
* be replaced by the spy and the previous attribute
* will be stored in the spy registry.
* Therefore this information is always restorable.
* The most common use case, will be to mock
* another function as attribute of the object.
*
* The method has to met the following conditions:
*
* - The attribute to spy has to be function itself.
* - The attribute to spy should not be spied already.
*
* If the upper conditions are not fulfilled, this
* method will throw to avoid unexpected behaviour.
*
* @param {Object} obj -> The manipulated object.
* @param {string} methodName -> The mocked attributes name.
*
* @return {SpyInstance}
*/
value: function on(obj, methodName) {
var method = obj[methodName];
if (!(method instanceof Function)) {
throw new Error('The object attribute \'' + methodName + '\' ' + ('was: ' + (0, _serializer.serialize)(method) + '\n\n') + 'You should only spy on functions!');
}
if (method[Symbols.isSpy]) {
throw new Error('The objects attribute \'' + methodName + '\'' + ' was already spied. Please make sure to spy' + ' only once at a time at any attribute.');
}
__LOCK__ = false;
var spy = new Spy('the spy on \'' + methodName + '\'', { obj: obj, methodName: methodName });
__LOCK__ = true;
obj[methodName] = spy;
return spy;
}
if (method[Symbols.isSpy]) {
throw new Error("The objects attribute '".concat(methodName, "'") + ' was already spied. Please make sure to spy' + ' only once at a time at any attribute.');
}
/**
* This static method is shortcut for applying multiple
* spies on one object at (different) attributes.
*
* For example:
*
* const spy1 = Spy.on(obj, 'methodName1');
* const spy2 = Spy.on(obj, 'methodName2');
* const spy3 = Spy.on(obj, 'methodName3');
*
* Is equivalent to:
*
* const [spy1, spy2, spy3] =
* Spy.onMany(obj, 'methodName1', 'methodName2', 'methodName3')
*
* @param {Object} obj -> The manipulated object.
* @param {Array<string>} methodNames -> Iterative provided attribute
* names that will be mocked.
*
* @return {Array<SpyInstance>}
*/
__LOCK__ = false;
var spy = new Spy("the spy on '".concat(methodName, "'"), {
obj: obj,
methodName: methodName
});
__LOCK__ = true;
obj[methodName] = spy;
return spy;
}
}, {
key: "mock",
value: function mock(obj) {
for (var _len9 = arguments.length, methodNames = new Array(_len9 > 1 ? _len9 - 1 : 0), _key9 = 1; _key9 < _len9; _key9++) {
methodNames[_key9 - 1] = arguments[_key9];
}
}, {
key: 'onMany',
value: function onMany(obj) {
var spies = [];
return (0, _mock.createMock)(obj, methodNames);
}
}, {
key: "initMocks",
value: function initMocks() {
(0, _mock.initMocks)(Spy.on);
}
}, {
key: "restoreAll",
value: function restoreAll() {
registry.restoreAll();
}
}]);
for (var _len9 = arguments.length, methodNames = Array(_len9 > 1 ? _len9 - 1 : 0), _key9 = 1; _key9 < _len9; _key9++) {
methodNames[_key9 - 1] = arguments[_key9];
}
return Spy;
}();
for (var i = 0; i < methodNames.length; i++) {
var spy = Spy.on(obj, methodNames[i]);
spies.push(spy);
}
return spies;
}
exports.Spy = Spy;
/**
* This static method does restore all
* manipulated objects and remove therefore
* all mocks.
*
* Restoring objects does not disable any
* other behaviours/features of the spies.
*/
_defineProperty(Spy, "IGNORE", _utils.IGNORE);
}, {
key: 'restoreAll',
value: function restoreAll() {
registry.restoreAll();
}
}]);
_defineProperty(Spy, "COMPARE", _utils.COMPARE);
return Spy;
}();
Spy.IGNORE = _utils.IGNORE;
Spy.COMPARE = _utils.COMPARE;
exports.Spy = Spy;
(0, _testSuite.configureTestSuite)({
beforeEach: Spy.initMocks,
afterEach: Spy.restoreAll
});

@@ -1,252 +0,183 @@

'use strict';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
value: true
});
exports.toError = exports.COMPARE = exports.IGNORE = exports.objectKeys = exports.forEach = exports.differenceOf = void 0;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
/**
* This file is part of spy4js which is released under MIT license.
*
* The LICENSE file can be found in the root directory of this project.
*
*
*/
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
/**
* This function takes a handler as second argument to process
* all key-value-pairs of the given object through this handler.
*
* For example:
*
* forEach({attr1: 'str1', attr2: 123}, (k, v) => {
* console.log(k + 'has value: ' + v);
* });
*
* @param {Array<any>|Object} arrOrObj <- Array or Object to iterate.
* (Flow does not want to iterate
* over arrays with for-in, so we
* have to write here any.)
* @param {Function} handler <- Handler function to process all values.
*
*/
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
var forEach = function forEach(arrOrObj, handler) {
for (var _key in arrOrObj) {
if (arrOrObj.hasOwnProperty(_key)) {
handler(_key, arrOrObj[_key]);
}
for (var _key in arrOrObj) {
if (arrOrObj.hasOwnProperty(_key)) {
handler(_key, arrOrObj[_key]);
}
}
};
/**
* This function returns all own keys for the given
* object or array as array.
*
* For example:
*
* objectKeys({attr1: 'something', attr2: 123, attr3: {deepAttr: 42}})
* === ['attr1', 'attr2', 'attr3']
*
* objectKeys(['something', 123, {attr: 42}]) === ['0', '1', '2']
*
* @param {Array<any>|Object} arrOrObj <- Array or Object to iterate.
* (Flow does not want to iterate
* over arrays with for-in, so we
* have to write here any.
* @return {Array} <- containing all keys for the input object.
*/
exports.forEach = forEach;
var objectKeys = function objectKeys(arrOrObj) {
var keys = [];
forEach(arrOrObj, function (key) {
return keys.push(key);
});
return keys;
var keys = [];
forEach(arrOrObj, function (key) {
return keys.push(key);
});
return keys;
};
exports.objectKeys = objectKeys;
var mergeArrays = function mergeArrays(arr1, arr2) {
var result = [].concat(_toConsumableArray(arr1));
forEach(arr2, function (key, val) {
if (arr1.indexOf(val) === -1) {
result.push(val);
}
});
return result;
var result = _toConsumableArray(arr1);
forEach(arr2, function (key, val) {
if (arr1.indexOf(val) === -1) {
result.push(val);
}
});
return result;
};
/**
* This symbol serves as replacement to ignore any
* inequality and skip further comparisons.
*/
var IGNORE = Symbol.for('__Spy_IGNORE__');
exports.IGNORE = IGNORE;
/**
* Uniquely identifiable container for spy relevant comparators.
*/
var SpyComparator = function () {
function SpyComparator(comparator) {
_classCallCheck(this, SpyComparator);
function SpyComparator(comparator) {
_classCallCheck(this, SpyComparator);
this._func = comparator;
_defineProperty(this, "_func", void 0);
this._func = comparator;
}
_createClass(SpyComparator, [{
key: "compare",
value: function compare(arg) {
if (!this._func(arg)) return 'custom comparison failed';
}
}]);
_createClass(SpyComparator, [{
key: 'compare',
value: function compare(arg) {
if (!this._func(arg)) return 'custom comparison failed';
}
}]);
return SpyComparator;
return SpyComparator;
}();
/**
* This function may create individual comparators
* to define argument based comparison for arbitrary
* nested objects.
*/
var COMPARE = function COMPARE(comparator) {
return new SpyComparator(comparator);
return new SpyComparator(comparator);
};
/**
* This function is the internal representation of
* "differenceOf". It does recursively call itself.
* Read more below.
*
* @param {any} a <- any param.
* @param {any} b <- any param to compare with the first param.
* @param {boolean} initial <- is responsible for result
* string building for deep equal checks.
* @param {boolean} useOwnEquals <- enables/disables the usage
* of own "equals" implementations.
* @param {Array<any>} alreadyComparedArray
* <- All flatly compared objects
* will be temporarily stored
* in this array to resolve
* circular structures.
*
* @return {string|void} <- information about the difference
* of the provided arguments.
*/
exports.COMPARE = COMPARE;
var __diff = function __diff(a, b, initial, useOwnEquals) {
var alreadyComparedArray = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
var alreadyComparedArray = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
if (a === IGNORE || b === IGNORE) return;
if (a instanceof SpyComparator) return a.compare(b);
if (b instanceof SpyComparator) return b.compare(a);
if (a === b) return;
if (a === undefined || b === undefined) return 'one was undefined';
if (a === null || b === null) return 'one was null';
var aClass = Object.prototype.toString.call(a);
var bClass = Object.prototype.toString.call(b);
if (aClass !== bClass) return "different object types: ".concat(aClass, " <-> ").concat(bClass);
if (a === IGNORE || b === IGNORE) return;
if (a instanceof SpyComparator) return a.compare(b);
if (b instanceof SpyComparator) return b.compare(a);
if (a === b) return;
if (a === undefined || b === undefined) return 'one was undefined';
if (a === null || b === null) return 'one was null';
var aClass = Object.prototype.toString.call(a);
var bClass = Object.prototype.toString.call(b);
if (aClass !== bClass) return 'different object types: ' + aClass + ' <-> ' + bClass;
switch (aClass) {
case '[object RegExp]':
if (String(a) === String(b)) {
return;
}
return 'different regexp';
case '[object String]':
return 'different string';
case '[object Function]':
return 'different function';
case '[object Number]':
if (isNaN(a) && isNaN(b)) {
return;
}
return 'different number';
case '[object Date]':
if (Number(a) === Number(b)) {
return;
}
return 'different date';
case '[object Boolean]':
return 'different bool';
case '[object Symbol]':
return 'different symbols';
case '[object Error]':
if (String(a) === String(b)) {
return;
}
return 'different error';
default:
if (a.constructor !== b.constructor) {
return 'different constructor';
}
}
if (useOwnEquals && a.equals instanceof Function) {
if (a.equals(b)) {
return;
}
return 'own equals method failed <- ' + 'Maybe you want to disable the usage ' + 'of own equals implementation? ' + '[ Use: spy.configure({useOwnEquals: false}) ]';
}
if (alreadyComparedArray.indexOf(a) !== -1) {
switch (aClass) {
case '[object RegExp]':
if (String(a) === String(b)) {
return;
}
return 'different regexp';
case '[object String]':
return 'different string';
case '[object Function]':
return 'different function';
case '[object Number]':
if (isNaN(a) && isNaN(b)) {
return;
}
return 'different number';
case '[object Date]':
if (Number(a) === Number(b)) {
return;
}
return 'different date';
case '[object Boolean]':
return 'different bool';
case '[object Symbol]':
return 'different symbols';
case '[object Error]':
if (String(a) === String(b)) {
return;
}
return 'different error';
default:
if (a.constructor !== b.constructor) {
return 'different constructor';
}
}
if (useOwnEquals && a.equals instanceof Function) {
if (a.equals(b)) {
return;
}
var compared = [].concat(_toConsumableArray(alreadyComparedArray), [a]);
var keys = mergeArrays(objectKeys(a), objectKeys(b));
for (var i = 0; i < keys.length; i++) {
var _key2 = keys[i];
var diffStr = __diff(a[_key2], b[_key2], false, useOwnEquals, compared);
if (diffStr !== undefined) {
return (initial ? '--> ' + _key2 : '' + _key2) + ' / ' + diffStr;
}
return 'own equals method failed <- ' + 'Maybe you want to disable the usage ' + 'of own equals implementation? ' + '[ Use: spy.configure({useOwnEquals: false}) ]';
}
if (alreadyComparedArray.indexOf(a) !== -1) {
return;
}
var compared = _toConsumableArray(alreadyComparedArray).concat([a]);
var keys = mergeArrays(objectKeys(a), objectKeys(b));
for (var i = 0; i < keys.length; i++) {
var _key2 = keys[i];
var diffStr = __diff(a[_key2], b[_key2], false, useOwnEquals, compared);
if (diffStr !== undefined) {
return "".concat(initial ? "--> ".concat(_key2) : "".concat(_key2), " / ").concat(diffStr);
}
}
};
/**
* This function does make a comparison of two provided params.
*
* If found any difference it will return a string containing
* information about the first detected difference.
*
* If the given params were proven "identical" this function
* returns undefined.
*
* In first place the params are flatly checked. The checks are
* in the following order:
*
* - identical objects
* - one param is null or undefined
* - object type
* - regexp/string/number/date/boolean
* - constructor
* - keys length
* - own "equals" implementation
*
* In second place all keys of the params are deeply checked.
* Using the above flat checks for all attributes.
*
* Also all circular structures will be resolved and repeating
* attributes will be assumed to be equal.
*
* @param {any} a <- any param.
* @param {any} b <- any param to compare with the first param.
* @param {{useOwnEquals:boolean}} config <- controls the usage of own
* "equals" implementations.
*
* @return {string|void} <- information about the difference
* of the provided arguments.
*/
var differenceOf = function differenceOf(a, b) {
var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { useOwnEquals: true };
return __diff(a, b, true, config.useOwnEquals);
var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
useOwnEquals: true
};
return __diff(a, b, true, config.useOwnEquals);
};
exports.differenceOf = differenceOf;
var toError = function toError(msgOrError, spyName) {
return msgOrError instanceof Error ? msgOrError : new Error(msgOrError || spyName + ' was requested to throw');
return msgOrError instanceof Error ? msgOrError : new Error(msgOrError || "".concat(spyName, " was requested to throw"));
};
exports.differenceOf = differenceOf;
exports.forEach = forEach;
exports.objectKeys = objectKeys;
exports.IGNORE = IGNORE;
exports.COMPARE = COMPARE;
exports.toError = toError;
{
"name": "spy4js",
"version": "1.9.1",
"version": "2.0.0",
"description": "Smart, compact and powerful spy test framework",

@@ -52,32 +52,34 @@ "jest": {

"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-eslint": "^9.0.0",
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.5",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/plugin-transform-runtime": "^7.1.0",
"@babel/preset-env": "^7.1.5",
"@babel/preset-flow": "^7.0.0",
"@babel/runtime": "^7.1.5",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.7.0",
"babel-preset-flow": "^6.23.0",
"coveralls": "^3.0.2",
"eslint": "^5.5.0",
"eslint-config-prettier": "^3.0.1",
"eslint-plugin-flowtype": "^2.50.0",
"eslint": "^5.9.0",
"eslint-config-prettier": "^3.2.0",
"eslint-plugin-flowtype": "^3.2.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-prettier": "^2.6.2",
"flow-bin": "^0.85.0",
"eslint-plugin-prettier": "^3.0.0",
"flow-bin": "^0.86.0",
"jest": "^23.6.0",
"prettier": "^1.14.2"
"prettier": "^1.15.2"
},
"babel": {
"comments": false,
"presets": [
"env",
"flow"
"@babel/preset-env",
"@babel/preset-flow"
],
"plugins": [
"transform-class-properties",
"@babel/plugin-proposal-class-properties",
[
"transform-runtime",
"@babel/plugin-transform-runtime",
{
"polyfill": false,
"helpers": false,

@@ -88,3 +90,3 @@ "regenerator": true

[
"transform-object-rest-spread",
"@babel/plugin-proposal-object-rest-spread",
{

@@ -91,0 +93,0 @@ "useBuiltIns": true

@@ -27,2 +27,7 @@ [![GitHub license][license-image]][license-url]

**Hint**:
My favorite test framework is [Jest](https://jestjs.io/). If you are using other
frameworks you might get issues related to automatically applied test suite hooks.
To overcome this default behaviour see [here](#configure-static).
### Installation

@@ -54,7 +59,7 @@ ##### With yarn

const spy3 = Spy.on(someObject1, 'toJSON');
// (spy name will be accordingly: 'the spy on \'toJSON\'')
// (spy name will be accordingly: "the spy on 'toJSON'")
// initialize many by mocking another objects attributes
const someObject2 = new Date(2017, 1, 15);
const [spy4, spy5, spy6] = Spy.onMany(someObject2, 'toJSON', 'toString', 'getDate');
const someObject2$Mock = Spy.mock(someObject2, 'toJSON', 'toString', 'getDate');
```

@@ -162,3 +167,3 @@

This is extremely useful to clean up all still existing mocks and also
a very comfortable to this automatically after every test (like in an "afterEach").
a very comfortable to this automatically after every test (this is done by default).

@@ -171,23 +176,2 @@ - `restoreAll` (does restore every existing spy)

**Hint**:
To integrate as default that all spies get restored after each test run,
you can integrate the following snippet to replace the default describe.
For those of you working with
[create-react-app](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#srcsetuptestsjs)
may include the snippet in the `src/setupTests.js`.
```js
import { Spy } from 'spy4js';
const oldDescribe = describe;
window.describe = (string, func) => {
oldDescribe(string, () => {
afterEach(() => {
Spy.restoreAll();
});
return func();
});
};
```
And also sometimes it is necessary to have access to some of the call arguments with

@@ -239,7 +223,13 @@ which the spy was called.

```
Spy.configure(config:{useOwnEquals?:boolean}) => void
Spy.configure(config: {
useOwnEquals?:boolean,
beforeEach?: void => void,
afterEach?: void => void,
}) => void
```
Using this function you may edit the default behaviour of every spy instance. The only
configuration possibility for now is "useOwnEquals". See [configure](#configure) for more
details.
Using this function you may edit the default behaviour spy4js itself.
The configuration possibility are:
- **useOwnEquals**: Applies for all spy instances. See [configure](#configure) for more details.
- **beforeEach**: Let's you override the default beforeEach test suite hook.
- **afterEach**: Let's you override the default afterEach test suite hook.

@@ -257,15 +247,25 @@ ### on (static)

### onMany (static)
### mock (static)
```
Spy.onMany(object:Object, ...methodNames:Array<string>) => Array<SpyInstance>
Spy.mock(object:Object, ...methodNames:Array<string>) => Object (Mock)
```
Initializing as many spies as required for one and the same object. Same as calling
`Spy.on` for each method name.
Creating an object that references spies for all given methodNames.
Initialize as many spies as required for one and the same object. Only
after `Spy.initMocks` gets called, the created mock does affect the given object.
### initMocks (static)
```
Spy.initMocks() => void
```
Does initialize all mocks by applying spies. Mocks can be created with
[mock](#mock). This function has not be called manually, if you rely on
the default test suite hooks.
### restoreAll (static)
```
Spy.restoreAll() => Array<SpyInstance>
Spy.restoreAll() => void
```
Does restore all mocked objects to their original state. See [restore](#restore) for
further information.
further information. This function has not be called manually, if you rely on
the default test suite hooks.

@@ -272,0 +272,0 @@ ### IGNORE (static)

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc