diff --git a/dist/spec/issues/25.test.d.ts b/dist/spec/issues/25.test.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/spec/issues/25.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/spec/issues/25.test.js b/dist/spec/issues/25.test.js new file mode 100644 index 0000000..93e09d1 --- /dev/null +++ b/dist/spec/issues/25.test.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ava_1 = require("ava"); +var Index_1 = require("../../src/Index"); +ava_1.default('issue 25_2', function (t) { + var calc = Index_1.Substitute.for(); + calc.add(Index_1.Arg.all()).returns(1337); + calc.add(2, 5); + t.notThrows(function () { return calc.received().add(2, 5); }); +}); +ava_1.default('issue 25_1: call verification does not work when using Arg.all() to set up return values', function (t) { + var calc = Index_1.Substitute.for(); + calc.add(Index_1.Arg.all()).returns(1337); + calc.add(2, 5); + t.throws(function () { return calc.received().add(3, 4); }); +}); +//# sourceMappingURL=25.test.js.map \ No newline at end of file diff --git a/dist/spec/issues/25.test.js.map b/dist/spec/issues/25.test.js.map new file mode 100644 index 0000000..77c1f0b --- /dev/null +++ b/dist/spec/issues/25.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"25.test.js","sourceRoot":"","sources":["../../../spec/issues/25.test.ts"],"names":[],"mappings":";;AAAA,2BAAuB;AAEvB,yCAAkD;AASlD,aAAI,CAAC,YAAY,EAAE,UAAA,CAAC;IAChB,IAAM,IAAI,GAAG,kBAAU,CAAC,GAAG,EAAuB,CAAC;IACnD,IAAI,CAAC,GAAG,CAAC,WAAG,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEf,CAAC,CAAC,SAAS,CAAC,cAAM,OAAA,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAzB,CAAyB,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,aAAI,CAAC,0FAA0F,EAAE,UAAA,CAAC;IAC9F,IAAM,IAAI,GAAG,kBAAU,CAAC,GAAG,EAAuB,CAAC;IACnD,IAAI,CAAC,GAAG,CAAC,WAAG,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEf,CAAC,CAAC,MAAM,CAAC,cAAM,OAAA,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAzB,CAAyB,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC","sourcesContent":["import test from 'ava';\r\n\r\nimport { Substitute, Arg } from '../../src/Index';\r\n\r\ninterface CalculatorInterface {\r\n add(a: number, b: number): number\r\n subtract(a: number, b: number): number\r\n divide(a: number, b: number): number\r\n isEnabled: boolean\r\n}\r\n\r\ntest('issue 25_2', t => {\r\n const calc = Substitute.for();\r\n calc.add(Arg.all()).returns(1337);\r\n calc.add(2, 5);\r\n\r\n t.notThrows(() => calc.received().add(2, 5));\r\n});\r\n\r\ntest('issue 25_1: call verification does not work when using Arg.all() to set up return values', t => {\r\n const calc = Substitute.for();\r\n calc.add(Arg.all()).returns(1337);\r\n calc.add(2, 5);\r\n\r\n t.throws(() => calc.received().add(3, 4));\r\n});"]} \ No newline at end of file diff --git a/dist/src/Arguments.d.ts b/dist/src/Arguments.d.ts index 7833be9..7694d98 100644 --- a/dist/src/Arguments.d.ts +++ b/dist/src/Arguments.d.ts @@ -11,6 +11,7 @@ export declare class AllArguments extends Argument { constructor(); } export declare class Arg { + private static _all; static all(): AllArguments; static any(): Argument & any; static any(type: T): Argument & string; diff --git a/dist/src/Arguments.js b/dist/src/Arguments.js index a935012..0df4c5f 100644 --- a/dist/src/Arguments.js +++ b/dist/src/Arguments.js @@ -43,7 +43,7 @@ var Arg = /** @class */ (function () { function Arg() { } Arg.all = function () { - return new AllArguments(); + return this._all = (this._all || new AllArguments()); }; Arg.any = function (type) { var description = !type ? '{any arg}' : '{type ' + type + '}'; diff --git a/dist/src/Arguments.js.map b/dist/src/Arguments.js.map index efc5893..d11beac 100644 --- a/dist/src/Arguments.js.map +++ b/dist/src/Arguments.js.map @@ -1 +1 @@ -{"version":3,"file":"Arguments.js","sourceRoot":"","sources":["../../src/Arguments.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;IAGI,kBACY,WAAmB,EACnB,gBAAqC;QADrC,gBAAW,GAAX,WAAW,CAAQ;QACnB,qBAAgB,GAAhB,gBAAgB,CAAqB;QAE7C,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;IAChC,CAAC;IAED,0BAAO,GAAP,UAAQ,GAAM;QACV,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,2BAAQ,GAAR;QACI,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED,0BAAO,GAAP;QACI,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IACL,eAAC;AAAD,CAAC,AArBD,IAqBC;AArBY,4BAAQ;AAuBrB;IAAkC,gCAAa;IAC3C;eACI,kBAAM,OAAO,EAAE,cAAM,OAAA,IAAI,EAAJ,CAAI,CAAC;IAC9B,CAAC;IACL,mBAAC;AAAD,CAAC,AAJD,CAAkC,QAAQ,GAIzC;AAJY,oCAAY;AAMzB;IAAA;IAyCA,CAAC;IAxCU,OAAG,GAAV;QACI,OAAO,IAAI,YAAY,EAAE,CAAC;IAC9B,CAAC;IASM,OAAG,GAAV,UAAW,IAAa;QACpB,IAAM,WAAW,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,GAAG,IAAI,GAAG,GAAG,CAAC;QAChE,OAAO,IAAI,QAAQ,CAAM,WAAW,EAAE,UAAA,CAAC;YACnC,IAAG,CAAC,IAAI;gBACJ,OAAO,IAAI,CAAC;YAEhB,IAAG,OAAO,CAAC,KAAK,WAAW;gBACvB,OAAO,IAAI,CAAC;YAEhB,IAAG,IAAI,KAAK,OAAO;gBACf,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAEjC,OAAO,OAAO,CAAC,KAAK,IAAI,CAAC;QAC7B,CAAC,CAAC,CAAC;IACP,CAAC;IAEM,MAAE,GAAT,UAAa,SAAkC;QAC3C,OAAO,IAAI,QAAQ,CAAI,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,GAAG,EAAE,SAAS,CAAoB,CAAC;IAC5G,CAAC;IAEc,eAAW,GAA1B,UAA2B,GAAQ;QAC/B,IAAG,OAAO,GAAG,CAAC,OAAO,KAAK,UAAU;YAChC,OAAO,GAAG,CAAC,OAAO,EAAE,CAAC;QAEzB,IAAG,OAAO,GAAG,CAAC,QAAQ,KAAK,UAAU;YACjC,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;QAE1B,OAAO,GAAG,CAAC;IACf,CAAC;IACL,UAAC;AAAD,CAAC,AAzCD,IAyCC;AAzCY,kBAAG","sourcesContent":["export class Argument {\r\n encounteredValues: any[];\r\n\r\n constructor(\r\n private description: string,\r\n private matchingFunction: (arg: T) => boolean\r\n ) {\r\n this.encounteredValues = [];\r\n }\r\n\r\n matches(arg: T) {\r\n return this.matchingFunction(arg);\r\n }\r\n\r\n toString() {\r\n return this.description;\r\n }\r\n\r\n inspect() {\r\n return this.description;\r\n }\r\n}\r\n\r\nexport class AllArguments extends Argument {\r\n constructor() {\r\n super('{all}', () => true);\r\n }\r\n}\r\n\r\nexport class Arg {\r\n static all() {\r\n return new AllArguments();\r\n }\r\n\r\n static any(): Argument & any\r\n static any(type: T): Argument & string\r\n static any(type: T): Argument & number\r\n static any(type: T): Argument & boolean\r\n static any(type: T): Argument & any[]\r\n static any(type: T): Argument & Function\r\n static any(type: T): Argument & any\r\n static any(type?: string): Argument & any {\r\n const description = !type ? '{any arg}' : '{type ' + type + '}';\r\n return new Argument(description, x => {\r\n if(!type)\r\n return true;\r\n\r\n if(typeof x === 'undefined')\r\n return true;\r\n\r\n if(type === 'array')\r\n return x && Array.isArray(x);\r\n\r\n return typeof x === type;\r\n });\r\n }\r\n\r\n static is(predicate: (input: any) => boolean): Argument & T {\r\n return new Argument('{predicate ' + this.toStringify(predicate) + '}', predicate) as Argument & T;\r\n }\r\n\r\n private static toStringify(obj: any) {\r\n if(typeof obj.inspect === 'function')\r\n return obj.inspect();\r\n\r\n if(typeof obj.toString === 'function')\r\n return obj.toString();\r\n\r\n return obj;\r\n }\r\n}"]} \ No newline at end of file +{"version":3,"file":"Arguments.js","sourceRoot":"","sources":["../../src/Arguments.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;IAGI,kBACY,WAAmB,EACnB,gBAAqC;QADrC,gBAAW,GAAX,WAAW,CAAQ;QACnB,qBAAgB,GAAhB,gBAAgB,CAAqB;QAE7C,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;IAChC,CAAC;IAED,0BAAO,GAAP,UAAQ,GAAM;QACV,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,2BAAQ,GAAR;QACI,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED,0BAAO,GAAP;QACI,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IACL,eAAC;AAAD,CAAC,AArBD,IAqBC;AArBY,4BAAQ;AAuBrB;IAAkC,gCAAa;IAC3C;eACI,kBAAM,OAAO,EAAE,cAAM,OAAA,IAAI,EAAJ,CAAI,CAAC;IAC9B,CAAC;IACL,mBAAC;AAAD,CAAC,AAJD,CAAkC,QAAQ,GAIzC;AAJY,oCAAY;AAMzB;IAAA;IA2CA,CAAC;IAxCU,OAAG,GAAV;QACI,OAAO,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,YAAY,EAAE,CAAC,CAAC;IACzD,CAAC;IASM,OAAG,GAAV,UAAW,IAAa;QACpB,IAAM,WAAW,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,GAAG,IAAI,GAAG,GAAG,CAAC;QAChE,OAAO,IAAI,QAAQ,CAAM,WAAW,EAAE,UAAA,CAAC;YACnC,IAAG,CAAC,IAAI;gBACJ,OAAO,IAAI,CAAC;YAEhB,IAAG,OAAO,CAAC,KAAK,WAAW;gBACvB,OAAO,IAAI,CAAC;YAEhB,IAAG,IAAI,KAAK,OAAO;gBACf,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAEjC,OAAO,OAAO,CAAC,KAAK,IAAI,CAAC;QAC7B,CAAC,CAAC,CAAC;IACP,CAAC;IAEM,MAAE,GAAT,UAAa,SAAkC;QAC3C,OAAO,IAAI,QAAQ,CAAI,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,GAAG,EAAE,SAAS,CAAoB,CAAC;IAC5G,CAAC;IAEc,eAAW,GAA1B,UAA2B,GAAQ;QAC/B,IAAG,OAAO,GAAG,CAAC,OAAO,KAAK,UAAU;YAChC,OAAO,GAAG,CAAC,OAAO,EAAE,CAAC;QAEzB,IAAG,OAAO,GAAG,CAAC,QAAQ,KAAK,UAAU;YACjC,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;QAE1B,OAAO,GAAG,CAAC;IACf,CAAC;IACL,UAAC;AAAD,CAAC,AA3CD,IA2CC;AA3CY,kBAAG","sourcesContent":["export class Argument {\r\n encounteredValues: any[];\r\n\r\n constructor(\r\n private description: string,\r\n private matchingFunction: (arg: T) => boolean\r\n ) {\r\n this.encounteredValues = [];\r\n }\r\n\r\n matches(arg: T) {\r\n return this.matchingFunction(arg);\r\n }\r\n\r\n toString() {\r\n return this.description;\r\n }\r\n\r\n inspect() {\r\n return this.description;\r\n }\r\n}\r\n\r\nexport class AllArguments extends Argument {\r\n constructor() {\r\n super('{all}', () => true);\r\n }\r\n}\r\n\r\nexport class Arg {\r\n private static _all: AllArguments;\r\n\r\n static all() {\r\n return this._all = (this._all || new AllArguments());\r\n }\r\n\r\n static any(): Argument & any\r\n static any(type: T): Argument & string\r\n static any(type: T): Argument & number\r\n static any(type: T): Argument & boolean\r\n static any(type: T): Argument & any[]\r\n static any(type: T): Argument & Function\r\n static any(type: T): Argument & any\r\n static any(type?: string): Argument & any {\r\n const description = !type ? '{any arg}' : '{type ' + type + '}';\r\n return new Argument(description, x => {\r\n if(!type)\r\n return true;\r\n\r\n if(typeof x === 'undefined')\r\n return true;\r\n\r\n if(type === 'array')\r\n return x && Array.isArray(x);\r\n\r\n return typeof x === type;\r\n });\r\n }\r\n\r\n static is(predicate: (input: any) => boolean): Argument & T {\r\n return new Argument('{predicate ' + this.toStringify(predicate) + '}', predicate) as Argument & T;\r\n }\r\n\r\n private static toStringify(obj: any) {\r\n if(typeof obj.inspect === 'function')\r\n return obj.inspect();\r\n\r\n if(typeof obj.toString === 'function')\r\n return obj.toString();\r\n\r\n return obj;\r\n }\r\n}"]} \ No newline at end of file diff --git a/dist/src/states/FunctionState.js b/dist/src/states/FunctionState.js index b5709a8..39be7fd 100644 --- a/dist/src/states/FunctionState.js +++ b/dist/src/states/FunctionState.js @@ -57,6 +57,7 @@ var FunctionState = /** @class */ (function () { } if (hasExpectations) { callCount = matchingFunctionStates + .filter(function (x) { return x._arguments[0] !== Arguments_1.Arg.all(); }) .map(function (x) { return x.callCount; }) .reduce(function (a, b) { return a + b; }, 0); } @@ -129,6 +130,15 @@ var FunctionState = /** @class */ (function () { } _this.returns = returns; _this._callCount--; + if (_this._callCount === 0) { + var indexOfSelf = _this + ._getPropertyState + .recordedFunctionStates + .indexOf(_this); + _this._getPropertyState + .recordedFunctionStates + .splice(indexOfSelf, 1); + } context.state = context.initialState; }; } diff --git a/dist/src/states/FunctionState.js.map b/dist/src/states/FunctionState.js.map index dfcd85e..16826a8 100644 --- a/dist/src/states/FunctionState.js.map +++ b/dist/src/states/FunctionState.js.map @@ -1 +1 @@ -{"version":3,"file":"FunctionState.js","sourceRoot":"","sources":["../../../src/states/FunctionState.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContextState, PropertyKey } from \"./ContextState\";\r\nimport { Context } from \"src/Context\";\r\nimport { stringifyArguments, stringifyCalls, areArgumentsEqual, areArgumentArraysEqual } from \"../Utilities\";\r\nimport { GetPropertyState } from \"./GetPropertyState\";\r\nimport { Argument } from \"../Arguments\";\r\n\r\nconst Nothing = Symbol();\r\n\r\nexport class FunctionState implements ContextState {\r\n private returns: any[]|Symbol;\r\n private mimicks: Function|null;\r\n\r\n private _callCount: number;\r\n private _arguments: any[];\r\n\r\n public get arguments() {\r\n return this._arguments;\r\n }\r\n\r\n public get callCount() {\r\n return this._callCount;\r\n }\r\n\r\n public get property() {\r\n return this._getPropertyState.property;\r\n }\r\n\r\n constructor(private _getPropertyState: GetPropertyState, ...args: any[]) {\r\n this.returns = Nothing;\r\n this.mimicks = null;\r\n\r\n this._arguments = args;\r\n this._callCount = 0;\r\n }\r\n\r\n apply(context: Context, args: any[], matchingFunctionStates: FunctionState[]) {\r\n let callCount = this._callCount;\r\n const hasExpectations = context.initialState.hasExpectations;\r\n if(!matchingFunctionStates) {\r\n matchingFunctionStates = this._getPropertyState\r\n .recordedFunctionStates\r\n .filter(x => areArgumentArraysEqual(x.arguments, args));\r\n }\r\n\r\n if(hasExpectations) {\r\n callCount = matchingFunctionStates\r\n .map(x => x.callCount)\r\n .reduce((a, b) => a + b, 0);\r\n }\r\n\r\n context.initialState.assertCallCountMatchesExpectations(\r\n this._getPropertyState.recordedFunctionStates,\r\n callCount,\r\n 'method',\r\n this.property,\r\n args);\r\n\r\n if(!hasExpectations) {\r\n this._callCount++;\r\n\r\n for(let matchingFunctionState of matchingFunctionStates)\r\n for(let argument of matchingFunctionState.arguments) {\r\n if(!(argument instanceof Argument))\r\n continue;\r\n\r\n const indexOffset = matchingFunctionState\r\n .arguments\r\n .indexOf(argument);\r\n const myArg = args[indexOffset];\r\n if(myArg instanceof Argument)\r\n continue;\r\n\r\n argument.encounteredValues.push(myArg);\r\n }\r\n }\r\n\r\n if(this.mimicks)\r\n return this.mimicks.apply(this.mimicks, args);\r\n\r\n if(this.returns === Nothing)\r\n return context.proxy;\r\n\r\n var returnsArray = this.returns as any[];\r\n if(returnsArray.length === 1)\r\n return returnsArray[0];\r\n\r\n return returnsArray[this._callCount-1];\r\n }\r\n\r\n set(context: Context, property: PropertyKey, value: any) {\r\n }\r\n\r\n get(context: Context, property: PropertyKey) {\r\n if (property === 'then')\r\n return void 0;\r\n\r\n if(property === 'mimicks') {\r\n return (input: Function) => {\r\n this.mimicks = input;\r\n this._callCount--;\r\n\r\n context.state = context.initialState;\r\n }\r\n }\r\n\r\n if(property === 'returns') {\r\n if(this.returns !== Nothing)\r\n throw new Error('The return value for the function ' + this._getPropertyState.toString() + ' with ' + stringifyArguments(this._arguments) + ' has already been set to ' + this.returns);\r\n\r\n return (...returns: any[]) => {\r\n this.returns = returns;\r\n this._callCount--;\r\n\r\n context.state = context.initialState;\r\n };\r\n }\r\n\r\n return context.proxy;\r\n }\r\n}"]} \ No newline at end of file +{"version":3,"file":"FunctionState.js","sourceRoot":"","sources":["../../../src/states/FunctionState.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,0CAA6G;AAE7G,0CAA6C;AAE7C,IAAM,OAAO,GAAG,MAAM,EAAE,CAAC;AAEzB;IAmBI,uBAAoB,iBAAmC;QAAE,cAAc;aAAd,UAAc,EAAd,qBAAc,EAAd,IAAc;YAAd,6BAAc;;QAAnD,sBAAiB,GAAjB,iBAAiB,CAAkB;QACnD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;IACxB,CAAC;IAlBD,sBAAW,oCAAS;aAApB;YACI,OAAO,IAAI,CAAC,UAAU,CAAC;QAC3B,CAAC;;;OAAA;IAED,sBAAW,oCAAS;aAApB;YACI,OAAO,IAAI,CAAC,UAAU,CAAC;QAC3B,CAAC;;;OAAA;IAED,sBAAW,mCAAQ;aAAnB;YACI,OAAO,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC;QAC3C,CAAC;;;OAAA;IAUD,6BAAK,GAAL,UAAM,OAAgB,EAAE,IAAW,EAAE,sBAAuC;;QACxE,IAAI,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC;QAChC,IAAM,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC;QAC7D,IAAG,CAAC,sBAAsB,EAAE;YACxB,sBAAsB,GAAG,IAAI,CAAC,iBAAiB;iBAC1C,sBAAsB;iBACtB,MAAM,CAAC,UAAA,CAAC,IAAI,OAAA,kCAAsB,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,EAAzC,CAAyC,CAAC,CAAC;SAC/D;QAED,IAAG,eAAe,EAAE;YAChB,SAAS,GAAG,sBAAsB;iBAC7B,MAAM,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,eAAG,CAAC,GAAG,EAAE,EAA7B,CAA6B,CAAC;iBAC1C,GAAG,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,SAAS,EAAX,CAAW,CAAC;iBACrB,MAAM,CAAC,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,CAAC,GAAG,CAAC,EAAL,CAAK,EAAE,CAAC,CAAC,CAAC;SACnC;QAED,OAAO,CAAC,YAAY,CAAC,kCAAkC,CACnD,IAAI,CAAC,iBAAiB,CAAC,sBAAsB,EAC7C,SAAS,EACT,QAAQ,EACR,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,CAAC;QAEV,IAAG,CAAC,eAAe,EAAE;YACjB,IAAI,CAAC,UAAU,EAAE,CAAC;;gBAElB,KAAiC,IAAA,2BAAA,SAAA,sBAAsB,CAAA,8DAAA;oBAAnD,IAAI,qBAAqB,mCAAA;;wBAC7B,KAAoB,IAAA,KAAA,SAAA,qBAAqB,CAAC,SAAS,CAAA,gBAAA,4BAAE;4BAAjD,IAAI,QAAQ,WAAA;4BACZ,IAAG,CAAC,CAAC,QAAQ,YAAY,oBAAQ,CAAC;gCAC9B,SAAS;4BAEb,IAAM,WAAW,GAAG,qBAAqB;iCACpC,SAAS;iCACT,OAAO,CAAC,QAAQ,CAAC,CAAC;4BACvB,IAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;4BAChC,IAAG,KAAK,YAAY,oBAAQ;gCACxB,SAAS;4BAEb,QAAQ,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;yBAC1C;;;;;;;;;iBAAA;;;;;;;;;SACJ;QAED,IAAG,IAAI,CAAC,OAAO;YACX,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAElD,IAAG,IAAI,CAAC,OAAO,KAAK,OAAO;YACvB,OAAO,OAAO,CAAC,KAAK,CAAC;QAEzB,IAAI,YAAY,GAAG,IAAI,CAAC,OAAgB,CAAC;QACzC,IAAG,YAAY,CAAC,MAAM,KAAK,CAAC;YACxB,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;QAE3B,OAAO,YAAY,CAAC,IAAI,CAAC,UAAU,GAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,2BAAG,GAAH,UAAI,OAAgB,EAAE,QAAqB,EAAE,KAAU;IACvD,CAAC;IAED,2BAAG,GAAH,UAAI,OAAgB,EAAE,QAAqB;QAA3C,iBAoCC;QAnCG,IAAI,QAAQ,KAAK,MAAM;YACnB,OAAO,KAAK,CAAC,CAAC;QAElB,IAAG,QAAQ,KAAK,SAAS,EAAE;YACvB,OAAO,UAAC,KAAe;gBACnB,KAAI,CAAC,OAAO,GAAG,KAAK,CAAC;gBACrB,KAAI,CAAC,UAAU,EAAE,CAAC;gBAElB,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC;YACzC,CAAC,CAAA;SACJ;QAED,IAAG,QAAQ,KAAK,SAAS,EAAE;YACvB,IAAG,IAAI,CAAC,OAAO,KAAK,OAAO;gBACvB,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,GAAG,QAAQ,GAAG,8BAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,2BAA2B,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;YAE5L,OAAO;gBAAC,iBAAiB;qBAAjB,UAAiB,EAAjB,qBAAiB,EAAjB,IAAiB;oBAAjB,4BAAiB;;gBACrB,KAAI,CAAC,OAAO,GAAG,OAAO,CAAC;gBACvB,KAAI,CAAC,UAAU,EAAE,CAAC;gBAElB,IAAG,KAAI,CAAC,UAAU,KAAK,CAAC,EAAE;oBACtB,IAAI,WAAW,GAAG,KAAI;yBACjB,iBAAiB;yBACjB,sBAAsB;yBACtB,OAAO,CAAC,KAAI,CAAC,CAAC;oBACnB,KAAI,CAAC,iBAAiB;yBACjB,sBAAsB;yBACtB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;iBAC/B;gBAED,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC;YACzC,CAAC,CAAC;SACL;QAED,OAAO,OAAO,CAAC,KAAK,CAAC;IACzB,CAAC;IACL,oBAAC;AAAD,CAAC,AA1HD,IA0HC;AA1HY,sCAAa","sourcesContent":["import { ContextState, PropertyKey } from \"./ContextState\";\r\nimport { Context } from \"src/Context\";\r\nimport { stringifyArguments, stringifyCalls, areArgumentsEqual, areArgumentArraysEqual } from \"../Utilities\";\r\nimport { GetPropertyState } from \"./GetPropertyState\";\r\nimport { Argument, Arg } from \"../Arguments\";\r\n\r\nconst Nothing = Symbol();\r\n\r\nexport class FunctionState implements ContextState {\r\n private returns: any[]|Symbol;\r\n private mimicks: Function|null;\r\n\r\n private _callCount: number;\r\n private _arguments: any[];\r\n\r\n public get arguments() {\r\n return this._arguments;\r\n }\r\n\r\n public get callCount() {\r\n return this._callCount;\r\n }\r\n\r\n public get property() {\r\n return this._getPropertyState.property;\r\n }\r\n\r\n constructor(private _getPropertyState: GetPropertyState, ...args: any[]) {\r\n this.returns = Nothing;\r\n this.mimicks = null;\r\n\r\n this._arguments = args;\r\n this._callCount = 0;\r\n }\r\n\r\n apply(context: Context, args: any[], matchingFunctionStates: FunctionState[]) {\r\n let callCount = this._callCount;\r\n const hasExpectations = context.initialState.hasExpectations;\r\n if(!matchingFunctionStates) {\r\n matchingFunctionStates = this._getPropertyState\r\n .recordedFunctionStates\r\n .filter(x => areArgumentArraysEqual(x.arguments, args));\r\n }\r\n\r\n if(hasExpectations) {\r\n callCount = matchingFunctionStates\r\n .filter(x => x._arguments[0] !== Arg.all())\r\n .map(x => x.callCount)\r\n .reduce((a, b) => a + b, 0);\r\n }\r\n\r\n context.initialState.assertCallCountMatchesExpectations(\r\n this._getPropertyState.recordedFunctionStates,\r\n callCount,\r\n 'method',\r\n this.property,\r\n args);\r\n\r\n if(!hasExpectations) {\r\n this._callCount++;\r\n\r\n for(let matchingFunctionState of matchingFunctionStates)\r\n for(let argument of matchingFunctionState.arguments) {\r\n if(!(argument instanceof Argument))\r\n continue;\r\n\r\n const indexOffset = matchingFunctionState\r\n .arguments\r\n .indexOf(argument);\r\n const myArg = args[indexOffset];\r\n if(myArg instanceof Argument)\r\n continue;\r\n\r\n argument.encounteredValues.push(myArg);\r\n }\r\n }\r\n\r\n if(this.mimicks)\r\n return this.mimicks.apply(this.mimicks, args);\r\n\r\n if(this.returns === Nothing)\r\n return context.proxy;\r\n\r\n var returnsArray = this.returns as any[];\r\n if(returnsArray.length === 1)\r\n return returnsArray[0];\r\n\r\n return returnsArray[this._callCount-1];\r\n }\r\n\r\n set(context: Context, property: PropertyKey, value: any) {\r\n }\r\n\r\n get(context: Context, property: PropertyKey) {\r\n if (property === 'then')\r\n return void 0;\r\n\r\n if(property === 'mimicks') {\r\n return (input: Function) => {\r\n this.mimicks = input;\r\n this._callCount--;\r\n\r\n context.state = context.initialState;\r\n }\r\n }\r\n\r\n if(property === 'returns') {\r\n if(this.returns !== Nothing)\r\n throw new Error('The return value for the function ' + this._getPropertyState.toString() + ' with ' + stringifyArguments(this._arguments) + ' has already been set to ' + this.returns);\r\n\r\n return (...returns: any[]) => {\r\n this.returns = returns;\r\n this._callCount--;\r\n\r\n if(this._callCount === 0) {\r\n var indexOfSelf = this\r\n ._getPropertyState\r\n .recordedFunctionStates\r\n .indexOf(this);\r\n this._getPropertyState\r\n .recordedFunctionStates\r\n .splice(indexOfSelf, 1);\r\n }\r\n\r\n context.state = context.initialState;\r\n };\r\n }\r\n\r\n return context.proxy;\r\n }\r\n}"]} \ No newline at end of file diff --git a/dist/src/states/GetPropertyState.js b/dist/src/states/GetPropertyState.js index 781b11a..b39c635 100644 --- a/dist/src/states/GetPropertyState.js +++ b/dist/src/states/GetPropertyState.js @@ -54,14 +54,15 @@ var GetPropertyState = /** @class */ (function () { }); Object.defineProperty(GetPropertyState.prototype, "recordedFunctionStates", { get: function () { - return __spread(this._recordedFunctionStates); + return this._recordedFunctionStates; }, enumerable: true, configurable: true }); GetPropertyState.prototype.apply = function (context, args) { this._callCount = 0; - var matchingFunctionStates = this._recordedFunctionStates.filter(function (x) { return Utilities_1.areArgumentArraysEqual(x.arguments, args); }); + var matchingFunctionStates = this._recordedFunctionStates + .filter(function (x) { return Utilities_1.areArgumentArraysEqual(x.arguments, args); }); if (matchingFunctionStates.length > 0) { var matchingFunctionState = matchingFunctionStates[0]; return matchingFunctionState.apply(context, args, matchingFunctionStates); diff --git a/dist/src/states/GetPropertyState.js.map b/dist/src/states/GetPropertyState.js.map index 206444a..a97f68f 100644 --- a/dist/src/states/GetPropertyState.js.map +++ b/dist/src/states/GetPropertyState.js.map @@ -1 +1 @@ -{"version":3,"file":"GetPropertyState.js","sourceRoot":"","sources":["../../../src/states/GetPropertyState.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContextState, PropertyKey } from \"./ContextState\";\r\nimport { Context } from \"src/Context\";\r\nimport { FunctionState } from \"./FunctionState\";\r\nimport { areArgumentsEqual, areArgumentArraysEqual } from \"../Utilities\";\r\n\r\nconst Nothing = Symbol();\r\n\r\nexport class GetPropertyState implements ContextState {\r\n private returns: any[]|Symbol;\r\n private mimicks: Function|null;\r\n\r\n private _callCount: number;\r\n private _recordedFunctionStates: FunctionState[];\r\n\r\n private get isFunction() {\r\n return this._recordedFunctionStates.length > 0;\r\n }\r\n\r\n public get property() {\r\n return this._property;\r\n }\r\n\r\n public get callCount() {\r\n return this._callCount;\r\n }\r\n\r\n public get recordedFunctionStates() {\r\n return [...this._recordedFunctionStates];\r\n }\r\n\r\n constructor(private _property: PropertyKey) {\r\n this.returns = Nothing;\r\n this.mimicks = null;\r\n\r\n this._recordedFunctionStates = [];\r\n this._callCount = 0;\r\n }\r\n\r\n apply(context: Context, args: any[]) {\r\n this._callCount = 0;\r\n\r\n const matchingFunctionStates = this._recordedFunctionStates.filter(x => areArgumentArraysEqual(x.arguments, args));\r\n if(matchingFunctionStates.length > 0) {\r\n const matchingFunctionState = matchingFunctionStates[0];\r\n return matchingFunctionState.apply(\r\n context, \r\n args, \r\n matchingFunctionStates);\r\n }\r\n\r\n var functionState = new FunctionState(this, ...args);\r\n context.state = functionState;\r\n\r\n this._recordedFunctionStates.push(functionState);\r\n\r\n return context.apply(args);\r\n }\r\n\r\n set(context: Context, property: PropertyKey, value: any) {\r\n }\r\n\r\n get(context: Context, property: PropertyKey) {\r\n const hasExpectations = context.initialState.hasExpectations;\r\n\r\n if (property === 'then')\r\n return void 0;\r\n\r\n if(this.isFunction)\r\n return context.proxy;\r\n\r\n if(property === 'mimicks') {\r\n return (input: Function) => {\r\n this.mimicks = input;\r\n this._callCount--;\r\n\r\n context.state = context.initialState;\r\n }\r\n }\r\n\r\n if(property === 'returns') {\r\n if(this.returns !== Nothing)\r\n throw new Error('The return value for the property ' + this._property.toString() + ' has already been set to ' + this.returns);\r\n\r\n return (...returns: any[]) => {\r\n this.returns = returns;\r\n this._callCount--;\r\n\r\n context.state = context.initialState;\r\n };\r\n }\r\n\r\n if(!hasExpectations) {\r\n this._callCount++;\r\n\r\n if(this.mimicks)\r\n return this.mimicks.apply(this.mimicks);\r\n\r\n if(this.returns !== Nothing) {\r\n var returnsArray = this.returns as any[];\r\n if(returnsArray.length === 1)\r\n return returnsArray[0];\r\n \r\n return returnsArray[this._callCount-1];\r\n }\r\n }\r\n\r\n context.initialState.assertCallCountMatchesExpectations(\r\n context.initialState.getPropertyStates,\r\n this.callCount,\r\n 'property',\r\n this.property,\r\n []);\r\n\r\n return context.proxy;\r\n }\r\n}"]} \ No newline at end of file +{"version":3,"file":"GetPropertyState.js","sourceRoot":"","sources":["../../../src/states/GetPropertyState.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContextState, PropertyKey } from \"./ContextState\";\r\nimport { Context } from \"src/Context\";\r\nimport { FunctionState } from \"./FunctionState\";\r\nimport { areArgumentsEqual, areArgumentArraysEqual } from \"../Utilities\";\r\nimport { Arg } from \"../Arguments\";\r\n\r\nconst Nothing = Symbol();\r\n\r\nexport class GetPropertyState implements ContextState {\r\n private returns: any[]|Symbol;\r\n private mimicks: Function|null;\r\n\r\n private _callCount: number;\r\n private _recordedFunctionStates: FunctionState[];\r\n\r\n private get isFunction() {\r\n return this._recordedFunctionStates.length > 0;\r\n }\r\n\r\n public get property() {\r\n return this._property;\r\n }\r\n\r\n public get callCount() {\r\n return this._callCount;\r\n }\r\n\r\n public get recordedFunctionStates() {\r\n return this._recordedFunctionStates;\r\n }\r\n\r\n constructor(private _property: PropertyKey) {\r\n this.returns = Nothing;\r\n this.mimicks = null;\r\n\r\n this._recordedFunctionStates = [];\r\n this._callCount = 0;\r\n }\r\n\r\n apply(context: Context, args: any[]) {\r\n this._callCount = 0;\r\n\r\n const matchingFunctionStates = this._recordedFunctionStates\r\n .filter(x => areArgumentArraysEqual(x.arguments, args));\r\n if(matchingFunctionStates.length > 0) {\r\n const matchingFunctionState = matchingFunctionStates[0];\r\n return matchingFunctionState.apply(\r\n context, \r\n args, \r\n matchingFunctionStates);\r\n }\r\n\r\n var functionState = new FunctionState(this, ...args);\r\n context.state = functionState;\r\n\r\n this._recordedFunctionStates.push(functionState);\r\n\r\n return context.apply(args);\r\n }\r\n\r\n set(context: Context, property: PropertyKey, value: any) {\r\n }\r\n\r\n get(context: Context, property: PropertyKey) {\r\n const hasExpectations = context.initialState.hasExpectations;\r\n\r\n if (property === 'then')\r\n return void 0;\r\n\r\n if(this.isFunction)\r\n return context.proxy;\r\n\r\n if(property === 'mimicks') {\r\n return (input: Function) => {\r\n this.mimicks = input;\r\n this._callCount--;\r\n\r\n context.state = context.initialState;\r\n }\r\n }\r\n\r\n if(property === 'returns') {\r\n if(this.returns !== Nothing)\r\n throw new Error('The return value for the property ' + this._property.toString() + ' has already been set to ' + this.returns);\r\n\r\n return (...returns: any[]) => {\r\n this.returns = returns;\r\n this._callCount--;\r\n\r\n context.state = context.initialState;\r\n };\r\n }\r\n\r\n if(!hasExpectations) {\r\n this._callCount++;\r\n\r\n if(this.mimicks)\r\n return this.mimicks.apply(this.mimicks);\r\n\r\n if(this.returns !== Nothing) {\r\n var returnsArray = this.returns as any[];\r\n if(returnsArray.length === 1)\r\n return returnsArray[0];\r\n \r\n return returnsArray[this._callCount-1];\r\n }\r\n }\r\n\r\n context.initialState.assertCallCountMatchesExpectations(\r\n context.initialState.getPropertyStates,\r\n this.callCount,\r\n 'property',\r\n this.property,\r\n []);\r\n\r\n return context.proxy;\r\n }\r\n}"]} \ No newline at end of file diff --git a/dist/src/states/InitialState.js b/dist/src/states/InitialState.js index 750214f..173fedf 100644 --- a/dist/src/states/InitialState.js +++ b/dist/src/states/InitialState.js @@ -64,7 +64,7 @@ var InitialState = /** @class */ (function () { this.clearExpectations(); if (this.doesCallCountMatchExpectations(expectedCount, callCount)) return; - throw new Error('Expected ' + expectedCount + ' call' + (expectedCount === 1 ? '' : 's') + ' to the ' + type + ' ' + property.toString() + ' with ' + Utilities_1.stringifyArguments(args) + ', but received ' + (callCount === 0 ? 'none' : callCount) + ' of such call' + (callCount === 1 ? '' : 's') + '.\nAll calls received to ' + type + ' ' + property.toString() + ':' + Utilities_1.stringifyCalls(calls)); + throw new Error('Expected ' + (expectedCount === null ? '1 or more' : expectedCount) + ' call' + (expectedCount === 1 ? '' : 's') + ' to the ' + type + ' ' + property.toString() + ' with ' + Utilities_1.stringifyArguments(args) + ', but received ' + (callCount === 0 ? 'none' : callCount) + ' of such call' + (callCount === 1 ? '' : 's') + '.\nAll calls received to ' + type + ' ' + property.toString() + ':' + Utilities_1.stringifyCalls(calls)); }; InitialState.prototype.doesCallCountMatchExpectations = function (expectedCount, actualCount) { if (expectedCount === void 0) diff --git a/dist/src/states/InitialState.js.map b/dist/src/states/InitialState.js.map index 69ca766..cf0d92a 100644 --- a/dist/src/states/InitialState.js.map +++ b/dist/src/states/InitialState.js.map @@ -1 +1 @@ -{"version":3,"file":"InitialState.js","sourceRoot":"","sources":["../../../src/states/InitialState.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContextState, PropertyKey } from \"./ContextState\";\r\nimport { Context } from \"src/Context\";\r\nimport { GetPropertyState } from \"./GetPropertyState\";\r\nimport { SetPropertyState } from \"./SetPropertyState\";\r\nimport { stringifyArguments, stringifyCalls, Call } from \"../Utilities\";\r\nimport { AreProxiesDisabledKey } from \"../Substitute\";\r\n\r\nexport class InitialState implements ContextState {\r\n private recordedGetPropertyStates: Map;\r\n private recordedSetPropertyStates: SetPropertyState[];\r\n \r\n private _expectedCount: number|undefined|null;\r\n private _areProxiesDisabled: boolean;\r\n\r\n public get expectedCount() {\r\n return this._expectedCount;\r\n }\r\n\r\n public get hasExpectations() {\r\n return this._expectedCount !== void 0;\r\n }\r\n\r\n public get setPropertyStates() {\r\n return [...this.recordedSetPropertyStates];\r\n }\r\n\r\n public get getPropertyStates() {\r\n return [...this.recordedGetPropertyStates.values()];\r\n }\r\n\r\n constructor() {\r\n this.recordedGetPropertyStates = new Map();\r\n this.recordedSetPropertyStates = [];\r\n\r\n this._areProxiesDisabled = false;\r\n this._expectedCount = void 0;\r\n }\r\n\r\n assertCallCountMatchesExpectations(calls: Call[], callCount: number, type: string, property: PropertyKey, args: any[]) {\r\n const expectedCount = this._expectedCount;\r\n\r\n this.clearExpectations();\r\n\r\n if(this.doesCallCountMatchExpectations(expectedCount, callCount))\r\n return;\r\n\r\n throw new Error('Expected ' + expectedCount + ' call' + (expectedCount === 1 ? '' : 's') + ' to the ' + type + ' ' + property.toString() + ' with ' + stringifyArguments(args) + ', but received ' + (callCount === 0 ? 'none' : callCount) + ' of such call' + (callCount === 1 ? '' : 's') + '.\\nAll calls received to ' + type + ' ' + property.toString() + ':' + stringifyCalls(calls));\r\n }\r\n\r\n private doesCallCountMatchExpectations(expectedCount: number|undefined|null, actualCount: number) {\r\n if (expectedCount === void 0)\r\n return true;\r\n\r\n if (expectedCount === null && actualCount > 0)\r\n return true;\r\n\r\n return expectedCount === actualCount;\r\n }\r\n\r\n apply(context: Context, args: any[]) {\r\n }\r\n\r\n set(context: Context, property: PropertyKey, value: any) {\r\n if(property === AreProxiesDisabledKey) {\r\n this._areProxiesDisabled = value;\r\n return;\r\n }\r\n\r\n const existingSetState = this.recordedSetPropertyStates.find(x => x.arguments[0] === value);;\r\n if (existingSetState) {\r\n return existingSetState.set(context, property, value);\r\n }\r\n\r\n const setPropertyState = new SetPropertyState(property, value);\r\n context.state = setPropertyState;\r\n\r\n this.recordedSetPropertyStates.push(setPropertyState);\r\n\r\n setPropertyState.set(context, property, value);\r\n }\r\n\r\n get(context: Context, property: PropertyKey) {\r\n if (typeof property === 'symbol') {\r\n if(property === AreProxiesDisabledKey)\r\n return this._areProxiesDisabled;\r\n\r\n if (property === Symbol.toPrimitive)\r\n return () => '{SubstituteJS fake}';\r\n\r\n if (property === Symbol.iterator)\r\n return void 0;\r\n\r\n if (property === Symbol.toStringTag)\r\n return 'Substitute';\r\n\r\n if(property.toString() === 'Symbol(util.inspect.custom)')\r\n return void 0;\r\n }\r\n\r\n if (property === 'valueOf')\r\n return '{SubstituteJS fake}';\r\n\r\n if (property === '$$typeof')\r\n return '{SubstituteJS fake}';\r\n\r\n if (property === 'length')\r\n return '{SubstituteJS fake}';\r\n\r\n if (property === 'toString')\r\n return '{SubstituteJS fake}';\r\n\r\n if (property === 'inspect')\r\n return () => '{SubstituteJS fake}';\r\n\r\n if (property === 'constructor')\r\n return () => context.rootProxy;\r\n\r\n if (property === 'received') {\r\n return (count?: number) => {\r\n this._expectedCount = count === void 0 ? null : count;\r\n return context.proxy;\r\n };\r\n }\r\n\r\n const existingGetState = this.recordedGetPropertyStates.get(property);\r\n if (existingGetState) {\r\n context.state = existingGetState;\r\n return context.get(property);\r\n }\r\n\r\n const getState = new GetPropertyState(property);\r\n context.state = getState;\r\n\r\n this.recordedGetPropertyStates.set(property, getState);\r\n\r\n return context.get(property);\r\n }\r\n\r\n private clearExpectations() {\r\n this._expectedCount = void 0;\r\n }\r\n\r\n onSwitchedTo() {\r\n this.clearExpectations();\r\n }\r\n}"]} \ No newline at end of file +{"version":3,"file":"InitialState.js","sourceRoot":"","sources":["../../../src/states/InitialState.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContextState, PropertyKey } from \"./ContextState\";\r\nimport { Context } from \"src/Context\";\r\nimport { GetPropertyState } from \"./GetPropertyState\";\r\nimport { SetPropertyState } from \"./SetPropertyState\";\r\nimport { stringifyArguments, stringifyCalls, Call } from \"../Utilities\";\r\nimport { AreProxiesDisabledKey } from \"../Substitute\";\r\n\r\nexport class InitialState implements ContextState {\r\n private recordedGetPropertyStates: Map;\r\n private recordedSetPropertyStates: SetPropertyState[];\r\n \r\n private _expectedCount: number|undefined|null;\r\n private _areProxiesDisabled: boolean;\r\n\r\n public get expectedCount() {\r\n return this._expectedCount;\r\n }\r\n\r\n public get hasExpectations() {\r\n return this._expectedCount !== void 0;\r\n }\r\n\r\n public get setPropertyStates() {\r\n return [...this.recordedSetPropertyStates];\r\n }\r\n\r\n public get getPropertyStates() {\r\n return [...this.recordedGetPropertyStates.values()];\r\n }\r\n\r\n constructor() {\r\n this.recordedGetPropertyStates = new Map();\r\n this.recordedSetPropertyStates = [];\r\n\r\n this._areProxiesDisabled = false;\r\n this._expectedCount = void 0;\r\n }\r\n\r\n assertCallCountMatchesExpectations(calls: Call[], callCount: number, type: string, property: PropertyKey, args: any[]) {\r\n const expectedCount = this._expectedCount;\r\n\r\n this.clearExpectations();\r\n\r\n if(this.doesCallCountMatchExpectations(expectedCount, callCount))\r\n return;\r\n\r\n throw new Error('Expected ' + (expectedCount === null ? '1 or more' : expectedCount) + ' call' + (expectedCount === 1 ? '' : 's') + ' to the ' + type + ' ' + property.toString() + ' with ' + stringifyArguments(args) + ', but received ' + (callCount === 0 ? 'none' : callCount) + ' of such call' + (callCount === 1 ? '' : 's') + '.\\nAll calls received to ' + type + ' ' + property.toString() + ':' + stringifyCalls(calls));\r\n }\r\n\r\n private doesCallCountMatchExpectations(expectedCount: number|undefined|null, actualCount: number) {\r\n if (expectedCount === void 0)\r\n return true;\r\n\r\n if (expectedCount === null && actualCount > 0)\r\n return true;\r\n\r\n return expectedCount === actualCount;\r\n }\r\n\r\n apply(context: Context, args: any[]) {\r\n }\r\n\r\n set(context: Context, property: PropertyKey, value: any) {\r\n if(property === AreProxiesDisabledKey) {\r\n this._areProxiesDisabled = value;\r\n return;\r\n }\r\n\r\n const existingSetState = this.recordedSetPropertyStates.find(x => x.arguments[0] === value);;\r\n if (existingSetState) {\r\n return existingSetState.set(context, property, value);\r\n }\r\n\r\n const setPropertyState = new SetPropertyState(property, value);\r\n context.state = setPropertyState;\r\n\r\n this.recordedSetPropertyStates.push(setPropertyState);\r\n\r\n setPropertyState.set(context, property, value);\r\n }\r\n\r\n get(context: Context, property: PropertyKey) {\r\n if (typeof property === 'symbol') {\r\n if(property === AreProxiesDisabledKey)\r\n return this._areProxiesDisabled;\r\n\r\n if (property === Symbol.toPrimitive)\r\n return () => '{SubstituteJS fake}';\r\n\r\n if (property === Symbol.iterator)\r\n return void 0;\r\n\r\n if (property === Symbol.toStringTag)\r\n return 'Substitute';\r\n\r\n if(property.toString() === 'Symbol(util.inspect.custom)')\r\n return void 0;\r\n }\r\n\r\n if (property === 'valueOf')\r\n return '{SubstituteJS fake}';\r\n\r\n if (property === '$$typeof')\r\n return '{SubstituteJS fake}';\r\n\r\n if (property === 'length')\r\n return '{SubstituteJS fake}';\r\n\r\n if (property === 'toString')\r\n return '{SubstituteJS fake}';\r\n\r\n if (property === 'inspect')\r\n return () => '{SubstituteJS fake}';\r\n\r\n if (property === 'constructor')\r\n return () => context.rootProxy;\r\n\r\n if (property === 'received') {\r\n return (count?: number) => {\r\n this._expectedCount = count === void 0 ? null : count;\r\n return context.proxy;\r\n };\r\n }\r\n\r\n const existingGetState = this.recordedGetPropertyStates.get(property);\r\n if (existingGetState) {\r\n context.state = existingGetState;\r\n return context.get(property);\r\n }\r\n\r\n const getState = new GetPropertyState(property);\r\n context.state = getState;\r\n\r\n this.recordedGetPropertyStates.set(property, getState);\r\n\r\n return context.get(property);\r\n }\r\n\r\n private clearExpectations() {\r\n this._expectedCount = void 0;\r\n }\r\n\r\n onSwitchedTo() {\r\n this.clearExpectations();\r\n }\r\n}"]} \ No newline at end of file diff --git a/spec/issues/25.test.ts b/spec/issues/25.test.ts new file mode 100644 index 0000000..3a9fa80 --- /dev/null +++ b/spec/issues/25.test.ts @@ -0,0 +1,26 @@ +import test from 'ava'; + +import { Substitute, Arg } from '../../src/Index'; + +interface CalculatorInterface { + add(a: number, b: number): number + subtract(a: number, b: number): number + divide(a: number, b: number): number + isEnabled: boolean +} + +test('issue 25_2', t => { + const calc = Substitute.for(); + calc.add(Arg.all()).returns(1337); + calc.add(2, 5); + + t.notThrows(() => calc.received().add(2, 5)); +}); + +test('issue 25_1: call verification does not work when using Arg.all() to set up return values', t => { + const calc = Substitute.for(); + calc.add(Arg.all()).returns(1337); + calc.add(2, 5); + + t.throws(() => calc.received().add(3, 4)); +}); \ No newline at end of file diff --git a/src/Arguments.ts b/src/Arguments.ts index e7c0f93..edd2e4f 100644 --- a/src/Arguments.ts +++ b/src/Arguments.ts @@ -28,8 +28,10 @@ export class AllArguments extends Argument { } export class Arg { + private static _all: AllArguments; + static all() { - return new AllArguments(); + return this._all = (this._all || new AllArguments()); } static any(): Argument & any diff --git a/src/states/FunctionState.ts b/src/states/FunctionState.ts index 3989dce..ebf994e 100644 --- a/src/states/FunctionState.ts +++ b/src/states/FunctionState.ts @@ -2,7 +2,7 @@ import { ContextState, PropertyKey } from "./ContextState"; import { Context } from "src/Context"; import { stringifyArguments, stringifyCalls, areArgumentsEqual, areArgumentArraysEqual } from "../Utilities"; import { GetPropertyState } from "./GetPropertyState"; -import { Argument } from "../Arguments"; +import { Argument, Arg } from "../Arguments"; const Nothing = Symbol(); @@ -44,6 +44,7 @@ export class FunctionState implements ContextState { if(hasExpectations) { callCount = matchingFunctionStates + .filter(x => x._arguments[0] !== Arg.all()) .map(x => x.callCount) .reduce((a, b) => a + b, 0); } @@ -111,6 +112,16 @@ export class FunctionState implements ContextState { this.returns = returns; this._callCount--; + if(this._callCount === 0) { + var indexOfSelf = this + ._getPropertyState + .recordedFunctionStates + .indexOf(this); + this._getPropertyState + .recordedFunctionStates + .splice(indexOfSelf, 1); + } + context.state = context.initialState; }; } diff --git a/src/states/GetPropertyState.ts b/src/states/GetPropertyState.ts index 057e47a..7ffdfe0 100644 --- a/src/states/GetPropertyState.ts +++ b/src/states/GetPropertyState.ts @@ -2,6 +2,7 @@ import { ContextState, PropertyKey } from "./ContextState"; import { Context } from "src/Context"; import { FunctionState } from "./FunctionState"; import { areArgumentsEqual, areArgumentArraysEqual } from "../Utilities"; +import { Arg } from "../Arguments"; const Nothing = Symbol(); @@ -25,7 +26,7 @@ export class GetPropertyState implements ContextState { } public get recordedFunctionStates() { - return [...this._recordedFunctionStates]; + return this._recordedFunctionStates; } constructor(private _property: PropertyKey) { @@ -39,7 +40,8 @@ export class GetPropertyState implements ContextState { apply(context: Context, args: any[]) { this._callCount = 0; - const matchingFunctionStates = this._recordedFunctionStates.filter(x => areArgumentArraysEqual(x.arguments, args)); + const matchingFunctionStates = this._recordedFunctionStates + .filter(x => areArgumentArraysEqual(x.arguments, args)); if(matchingFunctionStates.length > 0) { const matchingFunctionState = matchingFunctionStates[0]; return matchingFunctionState.apply( diff --git a/src/states/InitialState.ts b/src/states/InitialState.ts index 7249a5f..c7a3d91 100644 --- a/src/states/InitialState.ts +++ b/src/states/InitialState.ts @@ -44,7 +44,7 @@ export class InitialState implements ContextState { if(this.doesCallCountMatchExpectations(expectedCount, callCount)) return; - throw new Error('Expected ' + expectedCount + ' call' + (expectedCount === 1 ? '' : 's') + ' to the ' + type + ' ' + property.toString() + ' with ' + stringifyArguments(args) + ', but received ' + (callCount === 0 ? 'none' : callCount) + ' of such call' + (callCount === 1 ? '' : 's') + '.\nAll calls received to ' + type + ' ' + property.toString() + ':' + stringifyCalls(calls)); + throw new Error('Expected ' + (expectedCount === null ? '1 or more' : expectedCount) + ' call' + (expectedCount === 1 ? '' : 's') + ' to the ' + type + ' ' + property.toString() + ' with ' + stringifyArguments(args) + ', but received ' + (callCount === 0 ? 'none' : callCount) + ' of such call' + (callCount === 1 ? '' : 's') + '.\nAll calls received to ' + type + ' ' + property.toString() + ':' + stringifyCalls(calls)); } private doesCallCountMatchExpectations(expectedCount: number|undefined|null, actualCount: number) {