From 22bdb2d980a9e89fa9717160ad42b06237069d67 Mon Sep 17 00:00:00 2001 From: Viktor Luft Date: Wed, 1 Nov 2017 08:20:04 +0100 Subject: [PATCH] Fixed all flow errors --- .eslintrc.json | 2 +- .flowconfig | 1 - .prettierrc | 2 +- README.md | 13 +- dist/registry.js | 6 +- dist/registry.js.flow | 15 +- dist/spy.js | 5 +- dist/spy.js.flow | 49 ++++- dist/utils.js.flow | 19 +- src/registry.js | 15 +- src/spy.js | 49 ++++- src/utils.js | 19 +- test/facts.test.js | 31 +-- test/spy.test.js | 467 ++++++++++++++++++++++++------------------ test/utils.test.js | 69 +++++-- 15 files changed, 500 insertions(+), 262 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 2e49dbf..ab09fb4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -17,7 +17,7 @@ "rules": { "prettier/prettier": ["error", { "useTabs": false, - "printWidth": 120, + "printWidth": 80, "tabWidth": 4, "singleQuote": true, "trailingComma": "es5", diff --git a/.flowconfig b/.flowconfig index a2722f4..5bc0b88 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,5 +1,4 @@ [ignore] -/test/.* [include] diff --git a/.prettierrc b/.prettierrc index f4a76d2..205358e 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,6 @@ { "useTabs": false, - "printWidth": 120, + "printWidth": 80, "tabWidth": 4, "singleQuote": true, "trailingComma": "es5", diff --git a/README.md b/README.md index 30efb9c..ec9a033 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,14 @@ fits more to the rest of the written code. are treated as class instances and come with a lot of useful features. See below for more. ### Installation - -Like every other npm package. You may `npm install spy4js --save-dev` to save the -latest version to your dev dependencies. +##### With yarn +``` +yarn add --dev spy4js +``` +##### With npm +``` +npm install --save-dev spy4js +``` ### Interface @@ -425,6 +430,8 @@ const differentNumber = callArgs[2]['attr2']; ## Changes +* **1.2.2** + * Updated development environment and fixed a comparison issue with functions. * **1.2.1** * Updated flow to latest version and fixed production errors. * **1.2.0** diff --git a/dist/registry.js b/dist/registry.js index 396056c..f96b0af 100644 --- a/dist/registry.js +++ b/dist/registry.js @@ -81,7 +81,11 @@ SpyRegistry.prototype.restore = function (index) { */ SpyRegistry.prototype.push = function (obj, methodName) { this.registerCount += 1; - this.register[this.registerCount] = { obj: obj, method: obj[methodName], methodName: methodName }; + this.register[this.registerCount] = { + obj: obj, + method: obj[methodName], + methodName: methodName + }; return this.registerCount; }; diff --git a/dist/registry.js.flow b/dist/registry.js.flow index 1a870f0..fa571fb 100644 --- a/dist/registry.js.flow +++ b/dist/registry.js.flow @@ -25,7 +25,9 @@ const restoreAttributeForEntry = (value: Object): void => { */ function SpyRegistry() { if (!(this instanceof SpyRegistry)) { - throw new Error('\n\nPlease make sure to use this constructor only with "new" keyword.\n\n'); + throw new Error( + '\n\nPlease make sure to use this constructor only with "new" keyword.\n\n' + ); } this.register = {}; this.persReg = {}; @@ -73,7 +75,11 @@ SpyRegistry.prototype.restore = function(index: number): void { */ SpyRegistry.prototype.push = function(obj: Object, methodName: string): number { this.registerCount += 1; - this.register[this.registerCount] = { obj, method: obj[methodName], methodName }; + this.register[this.registerCount] = { + obj, + method: obj[methodName], + methodName, + }; return this.registerCount; }; @@ -103,7 +109,10 @@ SpyRegistry.prototype.getOriginalMethod = function(index: number): any { * @param {boolean} intoPersReg -> boolean to determine the moving * direction. */ -SpyRegistry.prototype.persist = function(index: number, intoPersReg: boolean): void { +SpyRegistry.prototype.persist = function( + index: number, + intoPersReg: boolean +): void { const fromReg = intoPersReg ? this.register : this.persReg; const toReg = intoPersReg ? this.persReg : this.register; const entry = fromReg[index]; diff --git a/dist/spy.js b/dist/spy.js index 7f92ac6..a3e6257 100644 --- a/dist/spy.js +++ b/dist/spy.js @@ -30,6 +30,9 @@ 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: (0, _symbol2.default)('__Spy_name__'), isSpy: (0, _symbol2.default)('__Spy_isSpy__'), @@ -160,7 +163,7 @@ Spy.on = function on(obj, methodName) { 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 }); + var spy = new Spy('the spy on \'' + methodName + '\'', { obj: obj, methodName: methodName }); __LOCK__ = true; obj[methodName] = spy; return spy; diff --git a/dist/spy.js.flow b/dist/spy.js.flow index c012c58..3484f8c 100644 --- a/dist/spy.js.flow +++ b/dist/spy.js.flow @@ -16,7 +16,10 @@ const registry = new SpyRegistry(); let __LOCK__ = true; -const Symbols = { +/** + * Those symbols are used to protect the private spy properties from outer manipulation by mistake. + */ +const Symbols: any = { name: Symbol('__Spy_name__'), isSpy: Symbol('__Spy_isSpy__'), func: Symbol('__Spy_func__'), @@ -64,7 +67,9 @@ const DefaultSettings = { */ function Spy(name: string = 'the spy', __mock: any) { if (!(this instanceof Spy)) { - throw new Error('\n\nPlease make sure to use this constructor only with "new" keyword.\n\n'); + throw new Error( + '\n\nPlease make sure to use this constructor only with "new" keyword.\n\n' + ); } let spy: any = function(...args: Array) { spy[Symbols.calls].push({ arguments: args }); @@ -147,7 +152,7 @@ Spy.on = function on(obj: Object, methodName: string): Spy { ); } __LOCK__ = false; - const spy = new Spy("the spy on '" + methodName + "'", { obj, methodName }); + const spy = new Spy(`the spy on '${methodName}'`, { obj, methodName }); __LOCK__ = true; obj[methodName] = spy; return spy; @@ -174,7 +179,10 @@ Spy.on = function on(obj: Object, methodName: string): Spy { * * @return {Array} */ -Spy.onMany = function onMany(obj: Object, ...methodNames: Array): Array { +Spy.onMany = function onMany( + obj: Object, + ...methodNames: Array +): Array { const spies = []; for (let i = 0; i < methodNames.length; i++) { const spy = Spy.on(obj, methodNames[i]); @@ -213,7 +221,10 @@ Spy.restoreAll = function restoreAll(): void { * for special configuration * @return {Spy} <- BuilderPattern. */ -Spy.prototype.configure = function(config: { useOwnEquals?: boolean, persistent?: boolean }): Spy { +Spy.prototype.configure = function(config: { + useOwnEquals?: boolean, + persistent?: boolean, +}): Spy { if (config.useOwnEquals !== undefined) { this[Symbols.config].useOwnEquals = config.useOwnEquals; } @@ -292,7 +303,9 @@ Spy.prototype.returns = function(...args: Array): Spy { */ Spy.prototype.throws = function(message: ?string): Spy { this[Symbols.func] = () => { - throw new Error(message || `${this[Symbols.name]} was requested to throw`); + throw new Error( + message || `${this[Symbols.name]} was requested to throw` + ); }; return this; }; @@ -324,7 +337,10 @@ Spy.prototype.reset = function(): Spy { */ Spy.prototype.restore = function(): Spy { if (this[Symbols.config].persistent) { - throw new Error(`\n\n${this[Symbols.name]} can not be restored!` + ' It was configured to be 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; @@ -380,7 +396,9 @@ Spy.prototype.transparentAfter = function(callCount: number): Spy { // are more than the call count were we // need to modify the behavior if (this[Symbols.calls].length > callCount) { - const originalMethod = registry.getOriginalMethod(this[Symbols.index]); + const originalMethod = registry.getOriginalMethod( + this[Symbols.index] + ); if (originalMethod) { return originalMethod(...args); } @@ -454,7 +472,11 @@ Spy.prototype.wasCalledWith = function(...args: Array) { } const diffInfo = []; for (let i = 0; i < madeCalls.length; i++) { - const diff = differenceOf(madeCalls[i].arguments, args, this[Symbols.config]); + const diff = differenceOf( + madeCalls[i].arguments, + args, + this[Symbols.config] + ); if (!diff) { return; } @@ -560,7 +582,10 @@ Spy.prototype.getCallArguments = function(callNr: number = 0): Array { * @return {any} -> the (argNr + 1)'th call argument * of the (callNr + 1)'th call. */ -Spy.prototype.getCallArgument = function(callNr: number = 0, argNr: number = 0): any { +Spy.prototype.getCallArgument = function( + callNr: number = 0, + argNr: number = 0 +): any { return this.getCallArguments(callNr)[argNr]; }; @@ -605,7 +630,9 @@ Spy.prototype.getCallCount = function(): number { * * @return {string} -> The information about made calls. */ -Spy.prototype.showCallArguments = function(additionalInformation: Array = []): string { +Spy.prototype.showCallArguments = function( + additionalInformation: Array = [] +): string { const madeCalls = this[Symbols.calls]; if (madeCalls.length === 0) { return `${this[Symbols.name]} was never called!\n`; diff --git a/dist/utils.js.flow b/dist/utils.js.flow index 044aeb2..05a6720 100644 --- a/dist/utils.js.flow +++ b/dist/utils.js.flow @@ -19,7 +19,10 @@ * @param {Function} handler <- Handler function to process all values. * */ -const forEach = (arrOrObj: any, handler: (key: string, value: any) => any): void => { +const forEach = ( + arrOrObj: any, + handler: (key: string, value: any) => any +): void => { for (let key in arrOrObj) { if (arrOrObj.hasOwnProperty(key)) { handler(key, arrOrObj[key]); @@ -136,7 +139,13 @@ const __diff = ( alreadyComparedArray.push(a); for (let i = 0; i < aKeys.length; i++) { const key = aKeys[i]; - const diffStr = __diff(a[key], b[key], false, useOwnEquals, alreadyComparedArray); + const diffStr = __diff( + a[key], + b[key], + false, + useOwnEquals, + alreadyComparedArray + ); if (diffStr !== undefined) { return `${initial ? `--> ${key}` : `${key}`} / ${diffStr}`; } @@ -177,7 +186,11 @@ const __diff = ( * @return {string|void} <- information about the difference * of the provided arguments. */ -const differenceOf = (a: any, b: any, config: { useOwnEquals: boolean } = { useOwnEquals: true }): string | void => { +const differenceOf = ( + a: any, + b: any, + config: { useOwnEquals: boolean } = { useOwnEquals: true } +): string | void => { return __diff(a, b, true, config.useOwnEquals); }; diff --git a/src/registry.js b/src/registry.js index 1a870f0..fa571fb 100644 --- a/src/registry.js +++ b/src/registry.js @@ -25,7 +25,9 @@ const restoreAttributeForEntry = (value: Object): void => { */ function SpyRegistry() { if (!(this instanceof SpyRegistry)) { - throw new Error('\n\nPlease make sure to use this constructor only with "new" keyword.\n\n'); + throw new Error( + '\n\nPlease make sure to use this constructor only with "new" keyword.\n\n' + ); } this.register = {}; this.persReg = {}; @@ -73,7 +75,11 @@ SpyRegistry.prototype.restore = function(index: number): void { */ SpyRegistry.prototype.push = function(obj: Object, methodName: string): number { this.registerCount += 1; - this.register[this.registerCount] = { obj, method: obj[methodName], methodName }; + this.register[this.registerCount] = { + obj, + method: obj[methodName], + methodName, + }; return this.registerCount; }; @@ -103,7 +109,10 @@ SpyRegistry.prototype.getOriginalMethod = function(index: number): any { * @param {boolean} intoPersReg -> boolean to determine the moving * direction. */ -SpyRegistry.prototype.persist = function(index: number, intoPersReg: boolean): void { +SpyRegistry.prototype.persist = function( + index: number, + intoPersReg: boolean +): void { const fromReg = intoPersReg ? this.register : this.persReg; const toReg = intoPersReg ? this.persReg : this.register; const entry = fromReg[index]; diff --git a/src/spy.js b/src/spy.js index c012c58..3484f8c 100644 --- a/src/spy.js +++ b/src/spy.js @@ -16,7 +16,10 @@ const registry = new SpyRegistry(); let __LOCK__ = true; -const Symbols = { +/** + * Those symbols are used to protect the private spy properties from outer manipulation by mistake. + */ +const Symbols: any = { name: Symbol('__Spy_name__'), isSpy: Symbol('__Spy_isSpy__'), func: Symbol('__Spy_func__'), @@ -64,7 +67,9 @@ const DefaultSettings = { */ function Spy(name: string = 'the spy', __mock: any) { if (!(this instanceof Spy)) { - throw new Error('\n\nPlease make sure to use this constructor only with "new" keyword.\n\n'); + throw new Error( + '\n\nPlease make sure to use this constructor only with "new" keyword.\n\n' + ); } let spy: any = function(...args: Array) { spy[Symbols.calls].push({ arguments: args }); @@ -147,7 +152,7 @@ Spy.on = function on(obj: Object, methodName: string): Spy { ); } __LOCK__ = false; - const spy = new Spy("the spy on '" + methodName + "'", { obj, methodName }); + const spy = new Spy(`the spy on '${methodName}'`, { obj, methodName }); __LOCK__ = true; obj[methodName] = spy; return spy; @@ -174,7 +179,10 @@ Spy.on = function on(obj: Object, methodName: string): Spy { * * @return {Array} */ -Spy.onMany = function onMany(obj: Object, ...methodNames: Array): Array { +Spy.onMany = function onMany( + obj: Object, + ...methodNames: Array +): Array { const spies = []; for (let i = 0; i < methodNames.length; i++) { const spy = Spy.on(obj, methodNames[i]); @@ -213,7 +221,10 @@ Spy.restoreAll = function restoreAll(): void { * for special configuration * @return {Spy} <- BuilderPattern. */ -Spy.prototype.configure = function(config: { useOwnEquals?: boolean, persistent?: boolean }): Spy { +Spy.prototype.configure = function(config: { + useOwnEquals?: boolean, + persistent?: boolean, +}): Spy { if (config.useOwnEquals !== undefined) { this[Symbols.config].useOwnEquals = config.useOwnEquals; } @@ -292,7 +303,9 @@ Spy.prototype.returns = function(...args: Array): Spy { */ Spy.prototype.throws = function(message: ?string): Spy { this[Symbols.func] = () => { - throw new Error(message || `${this[Symbols.name]} was requested to throw`); + throw new Error( + message || `${this[Symbols.name]} was requested to throw` + ); }; return this; }; @@ -324,7 +337,10 @@ Spy.prototype.reset = function(): Spy { */ Spy.prototype.restore = function(): Spy { if (this[Symbols.config].persistent) { - throw new Error(`\n\n${this[Symbols.name]} can not be restored!` + ' It was configured to be 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; @@ -380,7 +396,9 @@ Spy.prototype.transparentAfter = function(callCount: number): Spy { // are more than the call count were we // need to modify the behavior if (this[Symbols.calls].length > callCount) { - const originalMethod = registry.getOriginalMethod(this[Symbols.index]); + const originalMethod = registry.getOriginalMethod( + this[Symbols.index] + ); if (originalMethod) { return originalMethod(...args); } @@ -454,7 +472,11 @@ Spy.prototype.wasCalledWith = function(...args: Array) { } const diffInfo = []; for (let i = 0; i < madeCalls.length; i++) { - const diff = differenceOf(madeCalls[i].arguments, args, this[Symbols.config]); + const diff = differenceOf( + madeCalls[i].arguments, + args, + this[Symbols.config] + ); if (!diff) { return; } @@ -560,7 +582,10 @@ Spy.prototype.getCallArguments = function(callNr: number = 0): Array { * @return {any} -> the (argNr + 1)'th call argument * of the (callNr + 1)'th call. */ -Spy.prototype.getCallArgument = function(callNr: number = 0, argNr: number = 0): any { +Spy.prototype.getCallArgument = function( + callNr: number = 0, + argNr: number = 0 +): any { return this.getCallArguments(callNr)[argNr]; }; @@ -605,7 +630,9 @@ Spy.prototype.getCallCount = function(): number { * * @return {string} -> The information about made calls. */ -Spy.prototype.showCallArguments = function(additionalInformation: Array = []): string { +Spy.prototype.showCallArguments = function( + additionalInformation: Array = [] +): string { const madeCalls = this[Symbols.calls]; if (madeCalls.length === 0) { return `${this[Symbols.name]} was never called!\n`; diff --git a/src/utils.js b/src/utils.js index 044aeb2..05a6720 100644 --- a/src/utils.js +++ b/src/utils.js @@ -19,7 +19,10 @@ * @param {Function} handler <- Handler function to process all values. * */ -const forEach = (arrOrObj: any, handler: (key: string, value: any) => any): void => { +const forEach = ( + arrOrObj: any, + handler: (key: string, value: any) => any +): void => { for (let key in arrOrObj) { if (arrOrObj.hasOwnProperty(key)) { handler(key, arrOrObj[key]); @@ -136,7 +139,13 @@ const __diff = ( alreadyComparedArray.push(a); for (let i = 0; i < aKeys.length; i++) { const key = aKeys[i]; - const diffStr = __diff(a[key], b[key], false, useOwnEquals, alreadyComparedArray); + const diffStr = __diff( + a[key], + b[key], + false, + useOwnEquals, + alreadyComparedArray + ); if (diffStr !== undefined) { return `${initial ? `--> ${key}` : `${key}`} / ${diffStr}`; } @@ -177,7 +186,11 @@ const __diff = ( * @return {string|void} <- information about the difference * of the provided arguments. */ -const differenceOf = (a: any, b: any, config: { useOwnEquals: boolean } = { useOwnEquals: true }): string | void => { +const differenceOf = ( + a: any, + b: any, + config: { useOwnEquals: boolean } = { useOwnEquals: true } +): string | void => { return __diff(a, b, true, config.useOwnEquals); }; diff --git a/test/facts.test.js b/test/facts.test.js index 17fe6a2..b406f6e 100644 --- a/test/facts.test.js +++ b/test/facts.test.js @@ -6,28 +6,28 @@ import { differenceOf } from '../src/utils'; import { equals, equalsNot, throws } from '../util/facts'; describe('Test-Utils', () => { - it('does throw no exception if an exception' + 'will be thrown in "throws"', () => { + it('does throw no exception if an exception will be thrown in "throws"', () => { const throwingFunc = () => { throw new Error('here it comes'); }; throws(throwingFunc); }); - it('does throw no exception if an exception' + 'with correct message will be thrown in "throws"', () => { + it('does throw no exception if an exception with correct message will be thrown in "throws"', () => { const throwingFunc = () => { throw new Error('here it comes'); }; throws(throwingFunc, { message: 'here it comes' }); }); - it('does throw no exception if an exception' + 'with correct message part will be thrown in "throws"', () => { + it('does throw no exception if an exception with correct message part will be thrown in "throws"', () => { const throwingFunc = () => { throw new Error('here it comes'); }; throws(throwingFunc, { partOfMessage: 'comes' }); }); - it('does throw an exception if an exception' + 'will not be thrown in "throws"', done => { + it('does throw an exception if an exception will not be thrown in "throws"', done => { const notThrowingFunc = () => 'hello'; try { throws(notThrowingFunc); @@ -36,7 +36,7 @@ describe('Test-Utils', () => { } }); - it('does throw an exception if an exception' + 'with incorrect message will be thrown in "throws"', done => { + it('does throw an exception if an exception with incorrect message will be thrown in "throws"', done => { const throwingFunc = () => { throw new Error('here it comes'); }; @@ -47,7 +47,7 @@ describe('Test-Utils', () => { } }); - it('does throw an exception if an exception' + 'without message part will be thrown in "throws"', done => { + it('does throw an exception if an exception without message part will be thrown in "throws"', done => { const throwingFunc = () => { throw new Error('here it comes'); }; @@ -58,15 +58,17 @@ describe('Test-Utils', () => { } }); - it('does throw no exception if an comparison' + 'returns no difference in "equals"', () => { + it('does throw no exception if an comparison returns no difference in "equals"', () => { const firstObj = { attr1: 'string', attr2: 12 }; const secondObj = { attr1: 'string', attr2: 12 }; equals(firstObj, secondObj); // but does throw using "equalsNot" - throws(() => equalsNot(firstObj, secondObj), { message: 'The given inputs were equal!' }); + throws(() => equalsNot(firstObj, secondObj), { + message: 'The given inputs were equal!', + }); }); - it('does throw an exception if an comparison' + 'returns a difference in "equals"', done => { + it('does throw an exception if an comparison returns a difference in "equals"', done => { const firstObj = { attr1: 'string', attr2: 12 }; const secondObj = { attr1: 'string', attr2: 13 }; try { @@ -78,12 +80,17 @@ describe('Test-Utils', () => { } }); - it('does not consider any own equals function' + 'when comparing with "equals"', done => { + it('does not consider any own equals function when comparing with "equals"', done => { const eqFunc = () => true; const firstObj = { equals: eqFunc, attr1: 'string', attr2: 12 }; const secondObj = { equals: eqFunc, attr1: 'string', attr2: 13 }; - if (differenceOf(firstObj, secondObj, { useOwnEquals: true }) !== undefined) { - throw new Error('"differenceOf was expected to' + ' use the own equals functions!"'); + if ( + differenceOf(firstObj, secondObj, { useOwnEquals: true }) !== + undefined + ) { + throw new Error( + '"differenceOf was expected to use the own equals functions!"' + ); } try { equals(firstObj, secondObj); diff --git a/test/spy.test.js b/test/spy.test.js index 336fe19..33667d1 100644 --- a/test/spy.test.js +++ b/test/spy.test.js @@ -8,6 +8,12 @@ import { Spy } from '../src/spy'; describe('Spy - Utils', () => { afterEach(Spy.restoreAll); + const errorThrower: any = () => { + throw new Error('never call this func directly'); + }; + + const noop: any = () => {}; + it('should not allow to use the constructor of the Spy without new', () => { throws(Spy, { partOfMessage: 'only with "new" keyword' }); }); @@ -21,22 +27,18 @@ describe('Spy - Utils', () => { spy.wasCalledWith(9, 'test', someDate); }); - it( - 'throws an exception that the spy was never called if not called' + - ' when wasCalledWith or wasCalled gets called', - () => { - const spy = new Spy(); - throws(() => spy.wasCalled(), { partOfMessage: 'was never called!' }); - throws(() => spy.wasCalledWith(), { partOfMessage: 'was never called!' }); - } - ); + it('throws an exception that the spy was never called if not called when wasCalledWith or wasCalled gets called', () => { + const spy = new Spy(); + throws(() => spy.wasCalled(), { + partOfMessage: 'was never called!', + }); + throws(() => spy.wasCalledWith(), { + partOfMessage: 'was never called!', + }); + }); - it('should place the Spy on an object and ' + 'record the call arguments', () => { - const testObject = { - someFunc: () => { - throw new Error('never call this func directly'); - }, - }; + it('should place the Spy on an object and record the call arguments', () => { + const testObject = { someFunc: errorThrower }; const spy = Spy.on(testObject, 'someFunc'); const someDate = new Date(); testObject.someFunc('test', 6, someDate); @@ -45,7 +47,7 @@ describe('Spy - Utils', () => { spy.wasCalledWith('test', 6, someDate); }); - it('should throw if trying to spy other attributes ' + 'than functions', () => { + it('should throw if trying to spy other attributes than functions', () => { const testObject = { attrString: 'string', attrNumber: 12, @@ -53,66 +55,95 @@ describe('Spy - Utils', () => { attrDate: new Date(), attrObject: {}, }; - throws(() => Spy.on(testObject, 'attrString'), { partOfMessage: 'only spy on functions!' }); - throws(() => Spy.on(testObject, 'attrNumber'), { partOfMessage: 'only spy on functions!' }); - throws(() => Spy.on(testObject, 'attrNull'), { partOfMessage: 'only spy on functions!' }); - throws(() => Spy.on(testObject, 'attrDate'), { partOfMessage: 'only spy on functions!' }); - throws(() => Spy.on(testObject, 'attrObject'), { partOfMessage: 'only spy on functions!' }); - throws(() => Spy.on(testObject, 'attrUnknown'), { partOfMessage: 'only spy on functions!' }); + throws(() => Spy.on(testObject, 'attrString'), { + partOfMessage: 'only spy on functions!', + }); + throws(() => Spy.on(testObject, 'attrNumber'), { + partOfMessage: 'only spy on functions!', + }); + throws(() => Spy.on(testObject, 'attrNull'), { + partOfMessage: 'only spy on functions!', + }); + throws(() => Spy.on(testObject, 'attrDate'), { + partOfMessage: 'only spy on functions!', + }); + throws(() => Spy.on(testObject, 'attrObject'), { + partOfMessage: 'only spy on functions!', + }); + throws(() => Spy.on(testObject, 'attrUnknown'), { + partOfMessage: 'only spy on functions!', + }); }); it('should throw if trying to spy on already spied attributes.', () => { const testObject = { attr: () => {} }; const firstSpy = Spy.on(testObject, 'attr'); // spying again does throw now - throws(() => Spy.on(testObject, 'attr'), { partOfMessage: 'was already spied' }); + throws(() => Spy.on(testObject, 'attr'), { + partOfMessage: 'was already spied', + }); // after restoring the spy, we can spy there again firstSpy.restore(); Spy.on(testObject, 'attr'); }); - it('should place many Spies on an object and ' + 'record different call arguments', cb => { - const errorThrower = () => { - throw new Error('never call this func directly'); - }; - const testObject = { - func1: errorThrower, - func2: errorThrower, - func3: () => cb(), - func4: errorThrower, - }; - const [spy1, spy2, spy3] = Spy.onMany(testObject, 'func1', 'func2', 'func4'); - testObject.func1('test', 6); - equals(spy1.getCallArguments(), ['test', 6]); - spy1.wasCalledWith('test', 6); - testObject.func2('', 7); - equals(spy2.getCallArguments(), ['', 7]); - spy2.wasCalledWith('', 7); - testObject.func4(); - equals(spy3.getCallArguments(), []); - spy3.wasCalledWith(); - // if this would get spied, the test callback - // would never be called which would make the test fail - testObject.func3(); - }); + it( + 'should place many Spies on an object and ' + + 'record different call arguments', + cb => { + const testObject = { + func1: errorThrower, + func2: errorThrower, + func3: () => cb(), + func4: errorThrower, + }; + + const [spy1, spy2, spy3] = Spy.onMany( + testObject, + 'func1', + 'func2', + 'func4' + ); + testObject.func1('test', 6); + equals(spy1.getCallArguments(), ['test', 6]); + spy1.wasCalledWith('test', 6); + testObject.func2('', 7); + equals(spy2.getCallArguments(), ['', 7]); + spy2.wasCalledWith('', 7); + testObject.func4(); + equals(spy3.getCallArguments(), []); + spy3.wasCalledWith(); + // if this would get spied, the test callback + // would never be called which would make the test fail + testObject.func3(); + } + ); it('throws an exception if getCallArguments gets called with float', () => { const spy = new Spy(); spy(123); - throws(() => spy.getCallArguments(0.5), { partOfMessage: 'callNr "0.5" was not valid' }); + throws(() => spy.getCallArguments(0.5), { + partOfMessage: 'callNr "0.5" was not valid', + }); }); it('should restore all Spies', cb => { - const errorThrower = () => { - throw new Error('never call this func directly'); - }; const testObject = { - func1: () => {}, + func1: noop, func2: errorThrower, - func3: () => cb(), + func3: (arg: string) => { + equals(arg, 'testCall8'); + cb(); + }, func4: errorThrower, }; - const [spy1, spy2] = Spy.onMany(testObject, 'func1', 'func2', 'func3', 'func4'); + const [spy1, spy2] = Spy.onMany( + testObject, + 'func1', + 'func2', + 'func3', + 'func4' + ); testObject.func1('testCall1'); testObject.func2('testCall2'); testObject.func3('testCall3'); @@ -139,16 +170,22 @@ describe('Spy - Utils', () => { }); it('should restore single Spies', cb => { - const errorThrower = () => { - throw new Error('never call this func directly'); - }; const testObject = { - func1: () => {}, + func1: noop, func2: errorThrower, - func3: () => cb(), + func3: (arg: string) => { + equals(arg, 'testCall8'); + cb(); + }, func4: errorThrower, }; - const [spy1, , spy3] = Spy.onMany(testObject, 'func1', 'func2', 'func3', 'func4'); + const [spy1, , spy3] = Spy.onMany( + testObject, + 'func1', + 'func2', + 'func3', + 'func4' + ); testObject.func1('testCall1'); testObject.func2('testCall2'); testObject.func3('testCall3'); @@ -176,7 +213,9 @@ describe('Spy - Utils', () => { spy.wasNotCalled(); spy({ _key: 'test' }); spy.wasCalledWith({ _key: 'test' }); - throws(() => spy.wasNotCalled(), { partOfMessage: 'was not considered to be called' }); + throws(() => spy.wasNotCalled(), { + partOfMessage: 'was not considered to be called', + }); }); it('should inspect calls for given arguments of the Spy correctly', () => { @@ -285,16 +324,19 @@ describe('Spy - Utils', () => { equals(spy({ _key: 'callParams2' }), testObj); }); - it('should return given inputs sequentially' + ' after the spy was called', () => { - const testObj1 = { _key: 'testObj1' }; - const testObj2 = { _key: 'testObj2' }; - const testObj3 = { _key: 'testObj3' }; - const spy = new Spy().returns(testObj1, testObj2, testObj3); - equals(spy({ _key: 'callParams1' }), testObj1); - equals(spy({ _key: 'callParams2' }), testObj2); - equals(spy({ _key: 'callParams3' }), testObj3); - equals(spy({ _key: 'callParams4' }), testObj3); - }); + it( + 'should return given inputs sequentially' + ' after the spy was called', + () => { + const testObj1 = { _key: 'testObj1' }; + const testObj2 = { _key: 'testObj2' }; + const testObj3 = { _key: 'testObj3' }; + const spy = new Spy().returns(testObj1, testObj2, testObj3); + equals(spy({ _key: 'callParams1' }), testObj1); + equals(spy({ _key: 'callParams2' }), testObj2); + equals(spy({ _key: 'callParams3' }), testObj3); + equals(spy({ _key: 'callParams4' }), testObj3); + } + ); it('should reset the call arguments', () => { const spy = new Spy(); @@ -312,11 +354,21 @@ describe('Spy - Utils', () => { const spy = new Spy().throws('errorMessage'); throws(() => spy({ _key: 'callParams1' }), { message: 'errorMessage' }); spy.throws(null); - throws(() => spy({ _key: 'callParams2' }, { partOfMessage: 'was requested to throw' })); + throws(() => + spy( + { _key: 'callParams2' }, + { partOfMessage: 'was requested to throw' } + ) + ); }); - it('should reset the call arguments on an object' + ' spy and NOT removing it (LIKE RESTORE)', cb => { - const testObject = { func: () => cb() }; + it('should reset the call arguments on an object spy and NOT removing it (LIKE RESTORE)', cb => { + const testObject = { + func: (allowed: string) => { + equals(allowed, 'testCall3'); + cb(); + }, + }; const spy = Spy.on(testObject, 'func'); testObject.func('testCall1'); @@ -354,70 +406,79 @@ describe('Spy - Utils', () => { equals(testObj._key, 'callParams1'); }); - it('should call the given input-functions ' + 'sequentially after the spy was called', () => { - const testObj = { _key: 'testObj' }; - const spy = new Spy().calls( - arg => { - testObj._key = arg; - return null; - }, - arg => { - testObj._key = 'some other ' + arg; - return 42; - } - ); - equals(spy('callParams1'), null); - equals(testObj._key, 'callParams1'); - equals(spy('callParams2'), 42); - equals(testObj._key, 'some other callParams2'); - equals(spy('callParams3'), 42); - equals(testObj._key, 'some other callParams3'); - }); - - it('should make the spy transparent' + ' (mainly for spies on object properties)', () => { - const testObject = { - someFunc: () => { - throw new Error('never call this func directly'); - }, - }; - const spy = Spy.on(testObject, 'someFunc').transparent(); - throws(() => testObject.someFunc('test', 6), { message: 'never call this func directly' }); - spy.wasCalledWith('test', 6); - }); + it( + 'should call the given input-functions ' + + 'sequentially after the spy was called', + () => { + const testObj = { _key: 'testObj' }; + const spy = new Spy().calls( + arg => { + testObj._key = arg; + return null; + }, + arg => { + testObj._key = 'some other ' + arg; + return 42; + } + ); + equals(spy('callParams1'), null); + equals(testObj._key, 'callParams1'); + equals(spy('callParams2'), 42); + equals(testObj._key, 'some other callParams2'); + equals(spy('callParams3'), 42); + equals(testObj._key, 'some other callParams3'); + } + ); - it('should make the spy transparent after' + ' a certain amount of calls', () => { - const testObject = { - someFunc: () => { - throw new Error('never call this func directly'); - }, - }; - const spy = Spy.on(testObject, 'someFunc') - .returns(12, 13) - .transparentAfter(2); - equals(testObject.someFunc('test1', 42), 12); - equals(testObject.someFunc('test2'), 13); - throws(() => testObject.someFunc('test3', { testProp: 'test' }), { message: 'never call this func directly' }); - throws(() => testObject.someFunc('test4'), { message: 'never call this func directly' }); + it( + 'should make the spy transparent' + + ' (mainly for spies on object properties)', + () => { + const testObject = { someFunc: errorThrower }; + const spy = Spy.on(testObject, 'someFunc').transparent(); + throws(() => testObject.someFunc('test', 6), { + message: 'never call this func directly', + }); + spy.wasCalledWith('test', 6); + } + ); - spy.wasCalled(4); - spy.wasCalledWith('test1', 42); - spy.wasCalledWith('test2'); - spy.wasCalledWith('test3', { testProp: 'test' }); - spy.wasCalledWith('test4'); - }); + it( + 'should make the spy transparent after' + ' a certain amount of calls', + () => { + const testObject = { someFunc: errorThrower }; + const spy = Spy.on(testObject, 'someFunc') + .returns(12, 13) + .transparentAfter(2); + equals(testObject.someFunc('test1', 42), 12); + equals(testObject.someFunc('test2'), 13); + throws(() => testObject.someFunc('test3', { testProp: 'test' }), { + message: 'never call this func directly', + }); + throws(() => testObject.someFunc('test4'), { + message: 'never call this func directly', + }); + + spy.wasCalled(4); + spy.wasCalledWith('test1', 42); + spy.wasCalledWith('test2'); + spy.wasCalledWith('test3', { testProp: 'test' }); + spy.wasCalledWith('test4'); + } + ); it('should do nothing after for transparent restored spy', () => { - const testObject = { - someFunc: () => { - throw new Error('never call this func directly'); - }, - }; + const testObject = { someFunc: errorThrower }; const spy: any = Spy.on(testObject, 'someFunc').transparentAfter(3); testObject.someFunc('test1', 42); testObject.someFunc(); testObject.someFunc(); - throws(() => testObject.someFunc('test4'), { message: 'never call this func directly' }); - throws(() => testObject.someFunc('test5'), { message: 'never call this func directly' }); + throws(() => testObject.someFunc('test4'), { + message: 'never call this func directly', + }); + throws(() => testObject.someFunc('test5'), { + message: 'never call this func directly', + }); spy.wasCalled(5); spy.wasCalledWith('test1', 42); @@ -427,7 +488,9 @@ describe('Spy - Utils', () => { spy.restore(); - throws(() => testObject.someFunc('test6'), { message: 'never call this func directly' }); + throws(() => testObject.someFunc('test6'), { + message: 'never call this func directly', + }); spy.wasCalled(5); @@ -455,82 +518,90 @@ describe('Spy - Utils', () => { const testInstance3 = new TestClass(4); const testInstance4 = new TestClass(5); - it('should use own "equals" implementations as default, ' + 'but is able to reconfigure this behaviour', () => { - const spy = new Spy(); - - spy(testInstance1); - - // default config - spy.wasCalledWith(testInstance1); - spy.wasCalledWith(testInstance2); - spy.wasCalledWith(testInstance3); - spy.wasNotCalledWith(testInstance4); + it( + 'should use own "equals" implementations as default, ' + + 'but is able to reconfigure this behaviour', + () => { + const spy = new Spy(); - spy.configure({ useOwnEquals: false }); + spy(testInstance1); - // after configuration - spy.wasCalledWith(testInstance1); - spy.wasCalledWith(testInstance2); - spy.wasNotCalledWith(testInstance3); - spy.wasNotCalledWith(testInstance4); - }); - - it('does override the default behaviour for the use of' + 'own "equals" implementations. ', () => { - const testObj1 = { func1: () => {} }; - const testObj2 = { func2: () => {} }; - const testObj3 = { func3: () => {} }; - // still the initial default config - const defaultSpy1 = new Spy('defaultSpy1'); - // using configure without the "useOwnEquals"-config - // does not effect the behaviour - Spy.configure({}); - const defaultSpy2 = Spy.on(testObj1, 'func1'); - - // make the new configuration for all spies - Spy.configure({ useOwnEquals: false }); - const configuredSpy1 = new Spy('configuredSpy1'); - const configuredSpy2 = Spy.on(testObj2, 'func2'); - - // configure it back to the initial config - Spy.configure({ useOwnEquals: true }); - const reconfiguredSpy1 = new Spy('reconfiguredSpy1'); - const reconfiguredSpy2 = Spy.on(testObj3, 'func3'); - - // call all spies with the same object - defaultSpy1(testInstance1); - testObj1.func1(testInstance1); - configuredSpy1(testInstance1); - testObj2.func2(testInstance1); - reconfiguredSpy1(testInstance1); - testObj3.func3(testInstance1); - - const wasCalledChecksForOwnEquals = (spy: Spy) => { // default config spy.wasCalledWith(testInstance1); spy.wasCalledWith(testInstance2); spy.wasCalledWith(testInstance3); spy.wasNotCalledWith(testInstance4); - }; - const wasCalledChecksForNotOwnEquals = (spy: Spy) => { + spy.configure({ useOwnEquals: false }); + // after configuration spy.wasCalledWith(testInstance1); spy.wasCalledWith(testInstance2); spy.wasNotCalledWith(testInstance3); spy.wasNotCalledWith(testInstance4); - }; - - wasCalledChecksForOwnEquals(defaultSpy1); - wasCalledChecksForOwnEquals(defaultSpy2); - - wasCalledChecksForNotOwnEquals(configuredSpy1); - wasCalledChecksForNotOwnEquals(configuredSpy2); + } + ); - wasCalledChecksForOwnEquals(reconfiguredSpy1); - wasCalledChecksForOwnEquals(reconfiguredSpy2); - }); + it( + 'does override the default behaviour for the use of' + + 'own "equals" implementations. ', + () => { + const testObj1 = { func1: noop }; + const testObj2 = { func2: noop }; + const testObj3 = { func3: noop }; + // still the initial default config + const defaultSpy1 = new Spy('defaultSpy1'); + // using configure without the "useOwnEquals"-config + // does not effect the behaviour + Spy.configure({}); + const defaultSpy2 = Spy.on(testObj1, 'func1'); + + // make the new configuration for all spies + Spy.configure({ useOwnEquals: false }); + const configuredSpy1 = new Spy('configuredSpy1'); + const configuredSpy2 = Spy.on(testObj2, 'func2'); + + // configure it back to the initial config + Spy.configure({ useOwnEquals: true }); + const reconfiguredSpy1 = new Spy('reconfiguredSpy1'); + const reconfiguredSpy2 = Spy.on(testObj3, 'func3'); + + // call all spies with the same object + defaultSpy1(testInstance1); + testObj1.func1(testInstance1); + configuredSpy1(testInstance1); + testObj2.func2(testInstance1); + reconfiguredSpy1(testInstance1); + testObj3.func3(testInstance1); + + const wasCalledChecksForOwnEquals = (spy: Spy) => { + // default config + spy.wasCalledWith(testInstance1); + spy.wasCalledWith(testInstance2); + spy.wasCalledWith(testInstance3); + spy.wasNotCalledWith(testInstance4); + }; + + const wasCalledChecksForNotOwnEquals = (spy: Spy) => { + // after configuration + spy.wasCalledWith(testInstance1); + spy.wasCalledWith(testInstance2); + spy.wasNotCalledWith(testInstance3); + spy.wasNotCalledWith(testInstance4); + }; + + wasCalledChecksForOwnEquals(defaultSpy1); + wasCalledChecksForOwnEquals(defaultSpy2); + + wasCalledChecksForNotOwnEquals(configuredSpy1); + wasCalledChecksForNotOwnEquals(configuredSpy2); + + wasCalledChecksForOwnEquals(reconfiguredSpy1); + wasCalledChecksForOwnEquals(reconfiguredSpy2); + } + ); - it('does not allow direct access to the internal ' + 'properties of each Spy', () => { + it('does not allow direct access to the internal properties of each Spy', () => { const testObj = { myFunc: () => {} }; const spy = Spy.on(testObj, 'myFunc'); @@ -570,15 +641,21 @@ describe('Spy - Utils', () => { it('does not allow to configure not mocking spies to be persistent', () => { const spy = new Spy('spy that does not mock any object'); - throws(() => spy.configure({ persistent: true }), { partOfMessage: 'does not mock any object' }); - throws(() => spy.configure({ persistent: false }), { partOfMessage: 'does not mock any object' }); + throws(() => spy.configure({ persistent: true }), { + partOfMessage: 'does not mock any object', + }); + throws(() => spy.configure({ persistent: false }), { + partOfMessage: 'does not mock any object', + }); }); it('does not allow to restore persistent spies', () => { const testObj = { myFunc: () => 'originalFunc' }; const spy = Spy.on(testObj, 'myFunc').configure({ persistent: true }); - throws(() => spy.restore(), { partOfMessage: 'was configured to be persistent' }); + throws(() => spy.restore(), { + partOfMessage: 'was configured to be persistent', + }); spy.configure({ persistent: false }); equals(testObj.myFunc(), undefined); diff --git a/test/utils.test.js b/test/utils.test.js index a108ed4..5ede22c 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -25,7 +25,9 @@ const isNot = (p1: any, p2: any): void => { describe('Spy - Equality', () => { it('foreach iterates over arrays', () => { const results = []; - forEach([123, 'someString', { attr: 456 }], (key, value) => results.push([key, value])); + forEach([123, 'someString', { attr: 456 }], (key, value) => + results.push([key, value]) + ); equals(results.length, 3); equals(results[0], ['0', 123]); equals(results[1], ['1', 'someString']); @@ -34,7 +36,9 @@ describe('Spy - Equality', () => { it('foreach iterates over objects', () => { const results = []; - forEach({ attr1: 'someString', attr2: 123 }, (key, value) => results.push([key, value])); + forEach({ attr1: 'someString', attr2: 123 }, (key, value) => + results.push([key, value]) + ); equals(results.length, 2); equals(results[0], ['attr1', 'someString']); equals(results[1], ['attr2', 123]); @@ -42,8 +46,9 @@ describe('Spy - Equality', () => { it('foreach ignores not own properties on objects', () => { const results = []; - forEach({ attr1: 'someString', attr2: 123, hasOwnProperty: () => false }, (key, value) => - results.push([key, value]) + forEach( + { attr1: 'someString', attr2: 123, hasOwnProperty: () => false }, + (key, value) => results.push([key, value]) ); equals(results.length, 0); }); @@ -63,17 +68,32 @@ describe('Spy - Equality', () => { method(): string { // eslint-disable-line require-jsdoc - return this.attr1 + this.attr2.toString() + this.attr3.toDateString(); + return ( + this.attr1 + + this.attr2.toString() + + this.attr3.toDateString() + ); } }; const someInstance = new TestClass('test', 42, new Date(2016, 12, 24)); - const someOtherInstance = new TestClass('test', 42, new Date(2016, 12, 24)); - const someDifferentInstance = new TestClass('test', 42, new Date(2016, 12, 23)); + const someOtherInstance = new TestClass( + 'test', + 42, + new Date(2016, 12, 24) + ); + const someDifferentInstance = new TestClass( + 'test', + 42, + new Date(2016, 12, 23) + ); isNot(someInstance, someOtherInstance); is(differenceOf(someInstance, someOtherInstance), undefined); - is(differenceOf(someInstance, someDifferentInstance), '--> attr3 / different date'); + is( + differenceOf(someInstance, someDifferentInstance), + '--> attr3 / different date' + ); }); it('should detect flat differences correctly', () => { @@ -100,8 +120,14 @@ describe('Spy - Equality', () => { is(differenceOf(NaN, 123), 'different number'); is(differenceOf(12, -13), 'different number'); // date - is(differenceOf(new Date(2016, 12, 24), new Date(2016, 12, 24)), undefined); - is(differenceOf(new Date(2016, 12, 24), new Date(2017, 12, 24)), 'different date'); + is( + differenceOf(new Date(2016, 12, 24), new Date(2016, 12, 24)), + undefined + ); + is( + differenceOf(new Date(2016, 12, 24), new Date(2017, 12, 24)), + 'different date' + ); // boolean is(differenceOf(true, true), undefined); is(differenceOf(true, false), 'different bool'); @@ -122,8 +148,20 @@ describe('Spy - Equality', () => { this.attr = attr; } }; - is(differenceOf(new TestClass1('some String'), new TestClass1('some String')), undefined); - is(differenceOf(new TestClass1('some String'), new TestClass2('some String')), 'different constructor'); + is( + differenceOf( + new TestClass1('some String'), + new TestClass1('some String') + ), + undefined + ); + is( + differenceOf( + new TestClass1('some String'), + new TestClass2('some String') + ), + 'different constructor' + ); }); it('should flatly detect different keys length correctly', () => { @@ -148,7 +186,12 @@ describe('Spy - Equality', () => { // we want to use substr, so return a string for flow const diff = differenceOf(new TestClass(2), new TestClass(5)) || ''; is(diff.substr(0, 24), 'own equals method failed'); - is(differenceOf(new TestClass(2), new TestClass(4), { useOwnEquals: false }), '--> attr / different number'); + is( + differenceOf(new TestClass(2), new TestClass(4), { + useOwnEquals: false, + }), + '--> attr / different number' + ); }); it('should default circular structures as compared without failure', () => {