Comparing version 1.0.4 to 1.0.5
@@ -157,2 +157,3 @@ 'use strict'; | ||
exports.differenceOf = differenceOf; | ||
exports.differenceOf = differenceOf; | ||
exports.objectKeys = objectKeys; |
@@ -30,2 +30,3 @@ 'use strict'; | ||
this.register = {}; | ||
this.persReg = {}; | ||
this.registerCount = 0; | ||
@@ -111,3 +112,22 @@ } | ||
/** | ||
* 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]; | ||
} | ||
}; | ||
return SpyRegistry; | ||
}(); |
@@ -21,2 +21,10 @@ 'use strict'; | ||
var Symbols = { | ||
name: Symbol('__Spy_name__'), | ||
isSpy: Symbol('__Spy_isSpy__'), | ||
func: Symbol('__Spy_func__'), | ||
calls: Symbol('__Spy_calls__'), | ||
config: Symbol('__Spy_config__'), | ||
index: Symbol('__Spy_config__') }; | ||
/** | ||
@@ -66,10 +74,10 @@ * @ModifiedOnly by viktor.luft@freiheit.com | ||
spy._calls.push({ arguments: args }); | ||
return spy._func.apply(spy, args); | ||
spy[Symbols.calls].push({ arguments: args }); | ||
return spy[Symbols.func].apply(spy, args); | ||
}; | ||
spy._name = name; | ||
spy._isSpy = true; | ||
spy._func = function () {}; | ||
spy._calls = []; | ||
spy._config = { useOwnEquals: true }; | ||
spy[Symbols.name] = name; | ||
spy[Symbols.isSpy] = true; | ||
spy[Symbols.func] = function () {}; | ||
spy[Symbols.calls] = []; | ||
spy[Symbols.config] = { useOwnEquals: true }; | ||
for (var key in Spy.prototype) { | ||
@@ -114,6 +122,6 @@ if (Spy.prototype instanceof Object && Spy.prototype.hasOwnProperty(key)) { | ||
} | ||
if (method._isSpy) { | ||
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.'); | ||
} | ||
spy._index = registry.push(obj, methodName); | ||
spy[Symbols.index] = registry.push(obj, methodName); | ||
obj[methodName] = spy; | ||
@@ -180,2 +188,6 @@ return spy; | ||
* | ||
* - 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 | ||
@@ -187,4 +199,11 @@ * for special configuration | ||
if (config.useOwnEquals !== undefined) { | ||
this._config.useOwnEquals = config.useOwnEquals; | ||
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; | ||
@@ -212,3 +231,3 @@ }; | ||
// no arguments provided | ||
this._func = function () {}; | ||
this[Symbols.func] = function () {}; | ||
return this; | ||
@@ -220,3 +239,3 @@ } | ||
this._func = function () { | ||
this[Symbols.func] = function () { | ||
counter++; | ||
@@ -271,4 +290,4 @@ return funcs[max < counter ? max : counter].apply(funcs, arguments); | ||
this._func = function () { | ||
throw new Error(message || _this._name + ' was requested to throw'); | ||
this[Symbols.func] = function () { | ||
throw new Error(message || _this[Symbols.name] + ' was requested to throw'); | ||
}; | ||
@@ -284,3 +303,3 @@ return this; | ||
Spy.prototype.reset = function () { | ||
this._calls = []; | ||
this[Symbols.calls] = []; | ||
return this; | ||
@@ -296,2 +315,5 @@ }; | ||
* | ||
* If the spy was configured persistent, than this | ||
* method will throw an exception. | ||
* | ||
* Other than "Spy.restoreAll" this method only removes | ||
@@ -303,3 +325,6 @@ * a maximum of one mock. | ||
Spy.prototype.restore = function () { | ||
registry.restore(this._index); | ||
if (this[Symbols.config].persistent) { | ||
throw new Error('\n\n' + this[Symbols.name] + ' can not be restored!' + ' It was configured to be persistent.'); | ||
} | ||
registry.restore(this[Symbols.index]); | ||
return this; | ||
@@ -352,4 +377,4 @@ }; | ||
var oldFunc = this._func; | ||
this._func = function () { | ||
var oldFunc = this[Symbols.func]; | ||
this[Symbols.func] = function () { | ||
// before the function call is executed, | ||
@@ -360,4 +385,4 @@ // the call arguments were already saved | ||
// need to modify the behavior | ||
if (_this2._calls.length > callCount) { | ||
var originalMethod = registry.getOriginalMethod(_this2._index); | ||
if (_this2[Symbols.calls].length > callCount) { | ||
var originalMethod = registry.getOriginalMethod(_this2[Symbols.index]); | ||
if (originalMethod) { | ||
@@ -386,9 +411,9 @@ return originalMethod.apply(undefined, arguments); | ||
var madeCalls = this._calls.length; | ||
var madeCalls = this[Symbols.calls].length; | ||
if (callCount) { | ||
if (madeCalls !== callCount) { | ||
throw new Error('\n\n' + this._name + ' was called ' + madeCalls + ' times,' + (' but there were expected ' + callCount + ' calls.\n\n')); | ||
throw new Error('\n\n' + this[Symbols.name] + ' was called ' + madeCalls + ' times,' + (' but there were expected ' + callCount + ' calls.\n\n')); | ||
} | ||
} else if (madeCalls === 0) { | ||
throw new Error('\n\n' + this._name + ' was never called!\n\n'); | ||
throw new Error('\n\n' + this[Symbols.name] + ' was never called!\n\n'); | ||
} | ||
@@ -402,5 +427,5 @@ }; | ||
Spy.prototype.wasNotCalled = function () { | ||
var madeCalls = this._calls; | ||
var madeCalls = this[Symbols.calls]; | ||
if (madeCalls.length !== 0) { | ||
throw new Error('\n\nExpected no calls for ' + this._name + '.\n\n' + 'Actually there were:\n\n' + this.showCallArguments()); | ||
throw new Error('\n\nExpected no calls for ' + this[Symbols.name] + '.\n\n' + 'Actually there were:\n\n' + this.showCallArguments()); | ||
} | ||
@@ -426,5 +451,5 @@ }; | ||
Spy.prototype.wasCalledWith = function () { | ||
var madeCalls = this._calls; | ||
var madeCalls = this[Symbols.calls]; | ||
if (madeCalls.length === 0) { | ||
throw new Error('\n\n' + this._name + ' was never called!\n\n'); | ||
throw new Error('\n\n' + this[Symbols.name] + ' was never called!\n\n'); | ||
} | ||
@@ -438,3 +463,3 @@ var diffInfo = []; | ||
for (var i = 0; i < madeCalls.length; i++) { | ||
var diff = (0, _equality.differenceOf)(madeCalls[i].arguments, args, this._config); | ||
var diff = (0, _equality.differenceOf)(madeCalls[i].arguments, args, this[Symbols.config]); | ||
if (!diff) { | ||
@@ -445,3 +470,3 @@ return; | ||
} | ||
throw new Error('\n\nFor ' + this._name + ' did not find call arguments:\n\n' + (' --> ' + JSON.stringify(args) + '\n\n') + 'Actually there were:\n\n' + this.showCallArguments(diffInfo)); | ||
throw new Error('\n\nFor ' + this[Symbols.name] + ' did not find call arguments:\n\n' + (' --> ' + JSON.stringify(args) + '\n\n') + 'Actually there were:\n\n' + this.showCallArguments(diffInfo)); | ||
}; | ||
@@ -480,3 +505,3 @@ | ||
if (!errorOccurred) { | ||
throw new Error('\n\nFor ' + this._name + ' did find call arguments:\n\n' + (' --> ' + JSON.stringify(args) + '\n\n') + 'Actually they were not expected!\n\n'); | ||
throw new Error('\n\nFor ' + this[Symbols.name] + ' did find call arguments:\n\n' + (' --> ' + JSON.stringify(args) + '\n\n') + 'Actually they were not expected!\n\n'); | ||
} | ||
@@ -505,5 +530,5 @@ }; | ||
var madeCalls = this._calls; | ||
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._name + ':\n\n') + this.showCallArguments()); | ||
throw new Error('\n\nThe provided callNr "' + callNr + '" was not valid.\n\n' + ('Made calls for ' + this[Symbols.name] + ':\n\n') + this.showCallArguments()); | ||
} | ||
@@ -571,5 +596,5 @@ return madeCalls[callNr].arguments; | ||
var madeCalls = this._calls; | ||
var madeCalls = this[Symbols.calls]; | ||
if (madeCalls.length === 0) { | ||
return this._name + ' was never called!\n'; | ||
return this[Symbols.name] + ' was never called!\n'; | ||
} | ||
@@ -576,0 +601,0 @@ var response = ''; |
{ | ||
"name": "spy4js", | ||
"version": "1.0.4", | ||
"version": "1.0.5", | ||
"description": "Use new Spy() to optimize your tests with helpful debug messages.", | ||
@@ -5,0 +5,0 @@ "main": "dist/spy.js", |
@@ -128,15 +128,16 @@ | ||
// in fact: you never want to call a spy directly for any purpose (therefore using flow this will complain) | ||
// in fact: you never want to call a spy directly for any purpose | ||
// -> therefore using flow this line would complain | ||
spy([1, 'test', {attr: [4]}]); | ||
spy.wasCalled(); // called at least once | ||
spy.wasCalled(1); // called exctly once | ||
spy.wasCalled(); // called at least once | ||
spy.wasCalled(1); // called exactly once | ||
spy('with this text'); | ||
spy.wasCalled(2); // called extactly 2 times | ||
spy.wasCalled(2); // called exactly 2 times | ||
spy.wasCalledWith([1, 'test', {attr: [4]}]); // the spy was called at least once with equal params | ||
spy.wasCalledWith([1, 'test', {attr: [4]}]); // the spy was called at least once with equal params | ||
spy.wasNotCalledWith([1, 'test', {attr: [3]}]); // the spy was not called with those params (do you see the difference?) | ||
spy.wasNotCalledWith([1, 'test', {attr: [3]}]); // the spy was not called with those params | ||
``` | ||
@@ -169,16 +170,16 @@ | ||
spy.getCallArguments(/* default = 0 */); // returns ['string', 1] | ||
spy.getCallArguments(/* default = 0 */); // returns ['string', 1] | ||
spy.getFirstCallArgument(/* default = 0 */); // returns 'string' | ||
spy.getCallArguments(1); // returns [[1, 2, 3]] | ||
spy.getFirstCallArgument(1); // returns [1, 2, 3] | ||
spy.getCallArguments(1); // returns [[1, 2, 3]] | ||
spy.getFirstCallArgument(1); // returns [1, 2, 3] | ||
spy.getCallArguments(2); // returns [] | ||
spy.getFirstCallArgument(2); // returns undefined | ||
spy.getCallArguments(2); // returns [] | ||
spy.getFirstCallArgument(2); // returns undefined | ||
spy.getCallArguments(3); // returns [null] | ||
spy.getFirstCallArgument(3); // returns null | ||
spy.getCallArguments(3); // returns [null] | ||
spy.getFirstCallArgument(3); // returns null | ||
spy.getCallArguments(4); // throws Exception because less calls were made | ||
spy.getFirstCallArgument(4); // throws same Exception | ||
spy.getCallArguments(4); // throws Exception because less calls were made | ||
spy.getFirstCallArgument(4); // throws same Exception | ||
``` | ||
@@ -224,9 +225,14 @@ | ||
``` | ||
spy.configure(config:{useOwnEquals:boolean|void}) => (this) Spy | ||
spy.configure(config:{useOwnEquals?: boolean, persistent?: boolean}) => (this) Spy | ||
``` | ||
With `configure` the spy can be configured. For now the only configuration possibility | ||
With `configure` the spy can be configured. One configuration possibility | ||
is to ignore any `equals` methods while comparing objects. There might be libraries which | ||
come with those methods, but do not support ES6 classes or anything else. By default this | ||
configuration is set to favor own `equals` implementations while comparing objects. | ||
configuration is set to favor own `equals` implementations while comparing objects. | ||
Another possible configuration is to make the spy persist while other spies have to restore | ||
when ["restoreAll"](#restoreall) was called. This spy can ONLY RESTORE the mocked object when | ||
you configure it back to be NOT PERSISTENT. This configuration can only be applied to mocking | ||
spies. For Spies created with `new Spy()` this configuration will throw an exception. | ||
### calls | ||
@@ -269,2 +275,4 @@ ``` | ||
If the spy was configured to be persistent this method will throw an error. | ||
### transparent | ||
@@ -392,2 +400,15 @@ ``` | ||
const differentNumber = callArgs[2]['attr2']; | ||
``` | ||
``` | ||
## Changes | ||
* **1.0.5:** | ||
* Switched to es6-Symbols to make the access of private spy properties less accessible. | ||
* Added a persistence layer for spies. | ||
* **1.0.4:** | ||
## Planned | ||
* *After*-methods for `calls`, `returns` and `throws`. | ||
* Update of Dev-dependencies. | ||
* Upgrade of Dev-environment. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83788
812
409