tsmockit 1.3.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Mock/Any.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare const ANY_VALUE = "ANYTHING";
2
+ /**
3
+ * Returns a value Mock understands to represent "ANYTHING" casted to "T"
4
+ * @returns
5
+ */
6
+ export declare function Any<T>(): T;
package/Mock/Any.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Any = exports.ANY_VALUE = void 0;
4
+ exports.ANY_VALUE = 'ANYTHING';
5
+ /**
6
+ * Returns a value Mock understands to represent "ANYTHING" casted to "T"
7
+ * @returns
8
+ */
9
+ function Any() {
10
+ return exports.ANY_VALUE;
11
+ }
12
+ exports.Any = Any;
13
+ //# sourceMappingURL=Any.js.map
@@ -2,4 +2,5 @@ export declare const Regex: {
2
2
  Operation: RegExp;
3
3
  Property: RegExp;
4
4
  Params: RegExp;
5
+ AnyValue: RegExp;
5
6
  };
package/Mock/Constants.js CHANGED
@@ -4,6 +4,7 @@ exports.Regex = void 0;
4
4
  exports.Regex = {
5
5
  Operation: /\s[\w\d_]*\.([\w\d$_]*)\(([\w\W\d$_]*)\)/,
6
6
  Property: /\s[\w\d_]*\.([\w\d$_]*)/,
7
- Params: /({.*?}|[^,]+)/g
7
+ Params: /({.*?}|[^,]+)/g,
8
+ AnyValue: /\((0, (.*?).Any)\)\(\)/g
8
9
  };
9
10
  //# sourceMappingURL=Constants.js.map
@@ -0,0 +1,7 @@
1
+ export declare type FunctionMap = {
2
+ state: string | string[];
3
+ returns: Function;
4
+ timesCalled: number;
5
+ singleUse: boolean;
6
+ originalSignature: string | undefined;
7
+ };
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=TypeLiterals.js.map
3
+ //# sourceMappingURL=FunctionMap.js.map
package/Mock/Mock.d.ts CHANGED
@@ -2,13 +2,43 @@ import { Times } from './Times';
2
2
  export declare class Mock<T> {
3
3
  private memberSignatureMaps;
4
4
  private object;
5
+ /**
6
+ * The mock object of the given type "T" to inject as a substitute to a concrete implementation
7
+ */
5
8
  get Object(): T;
6
- Setup(member: (func: T) => any, returns?: any, exactSignatureMatch?: boolean): void;
9
+ /**
10
+ * Configure what the mock object will return when a given member is accessed
11
+ * @param member
12
+ * @param returns
13
+ */
14
+ Setup(member: (func: T) => any, returns?: any): void;
15
+ /**
16
+ * Configure a setup that will only resolve on the first time the member is registered
17
+ * @param member
18
+ * @param returns
19
+ */
20
+ SetupOnce(member: (func: T) => any, returns?: any): void;
21
+ /**
22
+ * Configure a set of setups that will only resolve on the first time the member is registered
23
+ * @param setups
24
+ */
25
+ SetupSequence(setups: [(func: T) => any, any][]): void;
26
+ /**
27
+ * Return the number of times a given member was referenced
28
+ * @param member
29
+ * @returns
30
+ */
7
31
  TimesMemberCalled(member: (func: T) => any): number;
32
+ /**
33
+ * Make an assertion that a given member was referenced a given number of times
34
+ * @param member
35
+ * @param times
36
+ */
8
37
  Verify(member: (func: T) => any, times: Times | number): void;
9
- private getReturnsValueForProperty;
10
- private getReturnsForFunction;
38
+ private setup;
39
+ private getReturnValueForProperty;
40
+ private getReturnForFunction;
41
+ private getFunctionMapsFromSignature;
11
42
  private updateMemberSignatureMaps;
12
43
  private updateSignatureMapFunctions;
13
- private getFunctionMapFromSignatureMap;
14
44
  }
package/Mock/Mock.js CHANGED
@@ -2,27 +2,85 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Mock = void 0;
4
4
  var SignatureService_1 = require("./SignatureService");
5
+ var Any_1 = require("./Any");
5
6
  var Mock = /** @class */ (function () {
6
7
  function Mock() {
7
8
  this.memberSignatureMaps = new Array();
8
9
  this.object = {};
9
10
  }
10
11
  Object.defineProperty(Mock.prototype, "Object", {
12
+ /**
13
+ * The mock object of the given type "T" to inject as a substitute to a concrete implementation
14
+ */
11
15
  get: function () {
12
16
  return this.object;
13
17
  },
14
18
  enumerable: false,
15
19
  configurable: true
16
20
  });
17
- Mock.prototype.Setup = function (member, returns, exactSignatureMatch) {
21
+ /**
22
+ * Configure what the mock object will return when a given member is accessed
23
+ * @param member
24
+ * @param returns
25
+ */
26
+ Mock.prototype.Setup = function (member, returns) {
27
+ if (returns === void 0) { returns = null; }
28
+ this.setup(member, returns);
29
+ };
30
+ /**
31
+ * Configure a setup that will only resolve on the first time the member is registered
32
+ * @param member
33
+ * @param returns
34
+ */
35
+ Mock.prototype.SetupOnce = function (member, returns) {
36
+ if (returns === void 0) { returns = null; }
37
+ this.setup(member, returns, true);
38
+ };
39
+ /**
40
+ * Configure a set of setups that will only resolve on the first time the member is registered
41
+ * @param setups
42
+ */
43
+ Mock.prototype.SetupSequence = function (setups) {
44
+ var _this = this;
45
+ setups.forEach(function (setup) {
46
+ _this.SetupOnce(setup[0], setup[1]);
47
+ });
48
+ };
49
+ /**
50
+ * Return the number of times a given member was referenced
51
+ * @param member
52
+ * @returns
53
+ */
54
+ Mock.prototype.TimesMemberCalled = function (member) {
55
+ var _a;
56
+ var memberSignatureMap = SignatureService_1.SignatureService.GetMemberSignatureMap(member);
57
+ var functionMap = this.getFunctionMapsFromSignature(memberSignatureMap, (_a = memberSignatureMap.functionMaps[0]) === null || _a === void 0 ? void 0 : _a.state).functionMapForArgs;
58
+ return (functionMap === null || functionMap === void 0 ? void 0 : functionMap.timesCalled) || 0;
59
+ };
60
+ /**
61
+ * Make an assertion that a given member was referenced a given number of times
62
+ * @param member
63
+ * @param times
64
+ */
65
+ Mock.prototype.Verify = function (member, times) {
66
+ var timesCalled = this.TimesMemberCalled(member);
67
+ var signature = SignatureService_1.SignatureService.GetMemberSignatureMap(member).signature;
68
+ var memberSignatureMap = this.memberSignatureMaps.find(function (m) { return m.signature === signature; });
69
+ if (timesCalled !== times) {
70
+ // eslint-disable-next-line no-console
71
+ console.log("Actual calls made for, \"".concat(signature, ":"), memberSignatureMap === null || memberSignatureMap === void 0 ? void 0 : memberSignatureMap.functionMaps.map(function (m) { return "".concat(m.originalSignature, " x ").concat(m.timesCalled); }));
72
+ }
73
+ expect(timesCalled).toEqual(times, timesCalled !== times ? '' : undefined);
74
+ };
75
+ Mock.prototype.setup = function (member, returns, singleUse) {
18
76
  var _this = this;
19
77
  if (returns === void 0) { returns = null; }
20
- if (exactSignatureMatch === void 0) { exactSignatureMatch = false; }
21
- var memberSignatureMap = SignatureService_1.SignatureService.GetMemberSignatureMap(member, returns, exactSignatureMatch);
78
+ if (singleUse === void 0) { singleUse = false; }
79
+ var memberSignatureMap = SignatureService_1.SignatureService.GetMemberSignatureMap(member, returns, singleUse);
22
80
  this.updateMemberSignatureMaps(memberSignatureMap);
23
81
  var memberName = SignatureService_1.SignatureService.GetMemberNameFromSignature(memberSignatureMap.signature);
24
82
  if (SignatureService_1.SignatureService.MemberSignatureIsProperty(memberSignatureMap.signature)) {
25
- this.object[memberName] = this.getReturnsValueForProperty(memberSignatureMap);
83
+ this.object[memberName] = this.getReturnValueForProperty(memberSignatureMap);
26
84
  }
27
85
  else {
28
86
  this.object[memberName] = (function () {
@@ -31,37 +89,40 @@ var Mock = /** @class */ (function () {
31
89
  for (var _i = 0; _i < arguments.length; _i++) {
32
90
  args[_i] = arguments[_i];
33
91
  }
34
- return (_a = _this.getReturnsForFunction(memberSignatureMap, args, exactSignatureMatch)) === null || _a === void 0 ? void 0 : _a();
92
+ return (_a = _this.getReturnForFunction(memberSignatureMap, args)) === null || _a === void 0 ? void 0 : _a();
35
93
  });
36
94
  }
37
95
  };
38
- Mock.prototype.TimesMemberCalled = function (member) {
39
- var memberSignature = SignatureService_1.SignatureService.GetMemberSignatureMap(member);
40
- var functionMap = this.getFunctionMapFromSignatureMap(memberSignature);
41
- var timesCalled = functionMap ? functionMap.timesCalled : 0;
42
- return timesCalled;
96
+ Mock.prototype.getReturnValueForProperty = function (memberSignatureMap) {
97
+ var _a, _b;
98
+ return ((_b = (_a = this.memberSignatureMaps.find(function (s) { return s.signature === memberSignatureMap.signature; })) === null || _a === void 0 ? void 0 : _a.functionMaps[0]) === null || _b === void 0 ? void 0 : _b.returns) || null;
43
99
  };
44
- Mock.prototype.Verify = function (member, times) {
45
- var timesCalled = this.TimesMemberCalled(member);
46
- expect(timesCalled).toEqual(times);
100
+ Mock.prototype.getReturnForFunction = function (memberSignatureMap, args) {
101
+ var _a = this.getFunctionMapsFromSignature(memberSignatureMap, args), functionMapForArgs = _a.functionMapForArgs, signatureFunctionMaps = _a.signatureFunctionMaps;
102
+ return functionMapForArgs ? (function () {
103
+ functionMapForArgs.timesCalled++;
104
+ if (signatureFunctionMaps && functionMapForArgs.singleUse) {
105
+ var indexToDelete = signatureFunctionMaps.indexOf(functionMapForArgs);
106
+ signatureFunctionMaps.splice(indexToDelete, 1);
107
+ }
108
+ return functionMapForArgs.returns;
109
+ }) : undefined;
47
110
  };
48
- Mock.prototype.getReturnsValueForProperty = function (memberSignatureMap) {
49
- var value = null;
111
+ Mock.prototype.getFunctionMapsFromSignature = function (memberSignatureMap, args) {
50
112
  var existingMemberSignatureMap = this.memberSignatureMaps.find(function (s) { return s.signature === memberSignatureMap.signature; });
51
- if (existingMemberSignatureMap) {
52
- value = existingMemberSignatureMap.functionMaps[0] ? existingMemberSignatureMap.functionMaps[0].returns : null;
113
+ var signatureFunctionMaps = existingMemberSignatureMap === null || existingMemberSignatureMap === void 0 ? void 0 : existingMemberSignatureMap.functionMaps;
114
+ var functionMapForArgs = signatureFunctionMaps === null || signatureFunctionMaps === void 0 ? void 0 : signatureFunctionMaps.find(function (m) { return JSON.stringify(m.state) === JSON.stringify(args); });
115
+ var functionMapsUsingAny = signatureFunctionMaps === null || signatureFunctionMaps === void 0 ? void 0 : signatureFunctionMaps.filter(function (m) { return m.state.includes(Any_1.ANY_VALUE); });
116
+ if (!functionMapForArgs && (functionMapsUsingAny === null || functionMapsUsingAny === void 0 ? void 0 : functionMapsUsingAny.length)) {
117
+ functionMapsUsingAny.forEach(function (element) {
118
+ if (!functionMapForArgs) {
119
+ var anyTransposedState_1 = new Array();
120
+ args.forEach(function (a, i) { return anyTransposedState_1[i] = element.state[i] === Any_1.ANY_VALUE ? Any_1.ANY_VALUE : a; });
121
+ functionMapForArgs = signatureFunctionMaps === null || signatureFunctionMaps === void 0 ? void 0 : signatureFunctionMaps.find(function (m) { return JSON.stringify(m.state) === JSON.stringify(anyTransposedState_1); });
122
+ }
123
+ });
53
124
  }
54
- return value;
55
- };
56
- Mock.prototype.getReturnsForFunction = function (memberSignatureMap, args, exactSignatureMatch) {
57
- var existingMemberSignatureMap = this.memberSignatureMaps.find(function (s) { return s.signature === memberSignatureMap.signature; });
58
- var exactFunctionMap = existingMemberSignatureMap === null || existingMemberSignatureMap === void 0 ? void 0 : existingMemberSignatureMap.functionMaps.find(function (m) { return JSON.stringify(m.state) === JSON.stringify(args); });
59
- var defaultFunctionMap = exactSignatureMatch ? undefined : existingMemberSignatureMap === null || existingMemberSignatureMap === void 0 ? void 0 : existingMemberSignatureMap.functionMaps.find(function (m) { return m.default; });
60
- var functionMap = exactFunctionMap || defaultFunctionMap;
61
- return functionMap ? (function () {
62
- functionMap.timesCalled++;
63
- return functionMap.returns;
64
- }) : undefined;
125
+ return { functionMapForArgs: functionMapForArgs, signatureFunctionMaps: signatureFunctionMaps };
65
126
  };
66
127
  Mock.prototype.updateMemberSignatureMaps = function (memberSignatureMap) {
67
128
  var existingSignatureMap = this.memberSignatureMaps.find(function (m) { return m.signature === memberSignatureMap.signature; });
@@ -75,7 +136,7 @@ var Mock = /** @class */ (function () {
75
136
  };
76
137
  Mock.prototype.updateSignatureMapFunctions = function (existingSignatureMap, newFunctionMap) {
77
138
  var existingFunctionMap = existingSignatureMap.functionMaps.find(function (fm) { return JSON.stringify(fm.state) === JSON.stringify(newFunctionMap.state); });
78
- if (existingFunctionMap) {
139
+ if (existingFunctionMap && !newFunctionMap.singleUse) {
79
140
  var functionMaps = existingSignatureMap.functionMaps;
80
141
  functionMaps.splice(functionMaps.indexOf(existingFunctionMap), 1, newFunctionMap);
81
142
  }
@@ -83,12 +144,6 @@ var Mock = /** @class */ (function () {
83
144
  existingSignatureMap.functionMaps.push(newFunctionMap);
84
145
  }
85
146
  };
86
- Mock.prototype.getFunctionMapFromSignatureMap = function (memberSignature) {
87
- var existingMember = this.memberSignatureMaps.find(function (m) { return m.signature === memberSignature.signature; });
88
- var functionMapToFind = memberSignature.functionMaps[0];
89
- return (existingMember === null || existingMember === void 0 ? void 0 : existingMember.functionMaps.find(function (m) { return JSON.stringify(m.state) === JSON.stringify(functionMapToFind.state); })) ||
90
- (existingMember === null || existingMember === void 0 ? void 0 : existingMember.functionMaps.find(function (m) { return m.default; }));
91
- };
92
147
  return Mock;
93
148
  }());
94
149
  exports.Mock = Mock;
@@ -0,0 +1,5 @@
1
+ import { FunctionMap } from './FunctionMap';
2
+ export declare type SignatureMap = {
3
+ signature: string;
4
+ functionMaps: Array<FunctionMap>;
5
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=SignatureMap.js.map
@@ -1,8 +1,9 @@
1
- import { SignatureMap } from './TypeLiterals';
1
+ import { SignatureMap } from './SignatureMap';
2
2
  export declare class SignatureService {
3
- static GetMemberSignatureMap(value: (obj: any) => any, returns?: any, exactSignatureMatch?: boolean): SignatureMap;
3
+ static GetMemberSignatureMap(value: (obj: any) => any, returns?: any, singleUse?: boolean): SignatureMap;
4
4
  static MemberSignatureIsProperty(memberSignatureString: string): boolean;
5
5
  static GetMemberNameFromSignature(memberSignatureString: string): string;
6
+ private static getOriginalSignature;
6
7
  private static getPropertyMemberSignature;
7
8
  private static getOperationMemberSignature;
8
9
  private static getStateForMemberSignature;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SignatureService = void 0;
4
+ var Any_1 = require("./Any");
4
5
  var Constants_1 = require("./Constants");
5
6
  var SignatureService = /** @class */ (function () {
6
7
  function SignatureService() {
7
8
  }
8
- SignatureService.GetMemberSignatureMap = function (value, returns, exactSignatureMatch) {
9
- if (exactSignatureMatch === void 0) { exactSignatureMatch = false; }
9
+ SignatureService.GetMemberSignatureMap = function (value, returns, singleUse) {
10
+ if (singleUse === void 0) { singleUse = false; }
10
11
  var memberSignature = '';
11
12
  memberSignature =
12
13
  this.getOperationMemberSignature(value, memberSignature) ||
@@ -15,7 +16,13 @@ var SignatureService = /** @class */ (function () {
15
16
  SignatureService.getStateForMemberSignature(memberSignature, value);
16
17
  return {
17
18
  signature: memberSignature,
18
- functionMaps: [{ default: !exactSignatureMatch, state: state, returns: returns ? returns : null, timesCalled: 0 }]
19
+ functionMaps: [{
20
+ state: state,
21
+ returns: returns,
22
+ timesCalled: 0,
23
+ singleUse: singleUse,
24
+ originalSignature: this.getOriginalSignature(value)
25
+ }]
19
26
  };
20
27
  };
21
28
  SignatureService.MemberSignatureIsProperty = function (memberSignatureString) {
@@ -25,6 +32,13 @@ var SignatureService = /** @class */ (function () {
25
32
  return SignatureService.MemberSignatureIsProperty(memberSignatureString) ?
26
33
  memberSignatureString : memberSignatureString.split('(')[0];
27
34
  };
35
+ SignatureService.getOriginalSignature = function (value) {
36
+ var originalSignature = value.toString();
37
+ originalSignature = (originalSignature === null || originalSignature === void 0 ? void 0 : originalSignature.indexOf('i.')) ? originalSignature.split('i.')[1] : originalSignature;
38
+ originalSignature = (originalSignature === null || originalSignature === void 0 ? void 0 : originalSignature.indexOf(';')) ? originalSignature.split(';')[0] : originalSignature;
39
+ return originalSignature === null || originalSignature === void 0 ? void 0 : originalSignature.trim();
40
+ };
41
+ ;
28
42
  SignatureService.getPropertyMemberSignature = function (value, memberSignature) {
29
43
  var propertyMemberMatches = SignatureService.getMatchesForRegex(value, Constants_1.Regex.Property);
30
44
  if (propertyMemberMatches && propertyMemberMatches[1]) {
@@ -38,7 +52,7 @@ var SignatureService = /** @class */ (function () {
38
52
  memberSignature = operationNameMatches[1];
39
53
  if (operationNameMatches[2]) {
40
54
  var paramString = SignatureService.getParamString(operationNameMatches);
41
- memberSignature += "(" + paramString + ")";
55
+ memberSignature += "(".concat(paramString, ")");
42
56
  }
43
57
  else {
44
58
  memberSignature += '()';
@@ -65,10 +79,12 @@ var SignatureService = /** @class */ (function () {
65
79
  return matches;
66
80
  };
67
81
  SignatureService.getParamString = function (operationNameMatches) {
68
- var paramStrings = operationNameMatches[2].match(Constants_1.Regex.Params);
82
+ var paramStrings = operationNameMatches[2]
83
+ .replace(Constants_1.Regex.AnyValue, Any_1.ANY_VALUE)
84
+ .match(Constants_1.Regex.Params);
69
85
  var params = '';
70
86
  for (var index = 0; index < (paramStrings ? paramStrings.length : 0); index++) {
71
- params += ((index > 0 ? ', ' : '') + "p" + index);
87
+ params += ("".concat(index > 0 ? ', ' : '', "p").concat(index));
72
88
  }
73
89
  return params;
74
90
  };
package/Mock/module.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './Mock';
2
2
  export * from './Times';
3
+ export { Any } from './Any';
package/Mock/module.js CHANGED
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Any = void 0;
3
4
  var tslib_1 = require("tslib");
4
- (0, tslib_1.__exportStar)(require("./Mock"), exports);
5
- (0, tslib_1.__exportStar)(require("./Times"), exports);
5
+ tslib_1.__exportStar(require("./Mock"), exports);
6
+ tslib_1.__exportStar(require("./Times"), exports);
7
+ var Any_1 = require("./Any");
8
+ Object.defineProperty(exports, "Any", { enumerable: true, get: function () { return Any_1.Any; } });
6
9
  //# sourceMappingURL=module.js.map
package/README.md CHANGED
@@ -4,65 +4,18 @@ Generic mocking library for TypeScript
4
4
  [![CI](https://github.com/bayes343/tsmockit/actions/workflows/ci.yml/badge.svg)](https://github.com/bayes343/tsmockit/actions/workflows/ci.yml)
5
5
  ![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/bayes343/tsmockit.svg?logo=lgtm&logoWidth=18)
6
6
 
7
-
8
7
  Helpful links:
9
8
  - [GitHub](https://github.com/bayes343/tsmockit)
10
9
  - [npm](https://www.npmjs.com/package/tsmockit)
10
+ - [Docs](https://bayes343.github.io/tsmockit/modules.html)
11
11
 
12
- This library exposes a generic class, `Mock<T>`, which allows you to mock dependencies and verify usage in an intuitive and type safe manner.
12
+ This library exposes a generic class, `Mock<T>`, which allows you to mock dependencies and verify usage in an intuitive and type safe manner. Its API is based on the C# "moq" library.
13
13
 
14
- Public interface:
14
+ The below example demonstrates some of the features of this library. Please explore the "docs" linked above for further details.
15
15
 
16
16
  ```typescript
17
- class Mock<T>
18
- ```
19
- ```typescript
20
- Setup(
21
- member: (func: T) => any,
22
- returns: any = null,
23
- exactSignatureMatch = false // will default to true and replace the signature matching convention as of v2.0.0.
24
- ): void
25
- ```
26
- ```typescript
27
- TimesMemberCalled(
28
- member: (func: T) => any
29
- ): number
30
- ```
31
- ```typescript
32
- Verify(
33
- member: (func: T) => any,
34
- times: Times | number
35
- ): void
36
- ```
37
-
38
- ```typescript
39
- class TestHelpers
40
- ```
41
- ```typescript
42
- static EmitEventAtElement(element: HTMLElement, eventType: string): void
43
- ```
44
- ```typescript
45
- static EmitKeyEventAtElement(
46
- element: HTMLInputElement,
47
- key: string,
48
- keyEvent: 'keydown' | 'keypress' | 'keyup' | 'input'
49
- ): void
50
- ```
51
- ```typescript
52
- static async Expect<T>(
53
- selector: () => T,
54
- assertion: (m: jasmine.Matchers<T>) => void,
55
- interval = 0,
56
- getTimeFunc = () => Date.now()
57
- ): Promise<void>
58
- ```
59
-
60
- ## Usage
61
-
62
- ### Scenario
63
- Consider this dependency injection scenario.
17
+ // https://github.com/bayes343/tsmockit/blob/master/src/Mock/tests/Mock-Car-Example.spec.ts
64
18
 
65
- ```ts
66
19
  interface IEngine {
67
20
  Start(): void;
68
21
  Stop(): void;
@@ -114,40 +67,62 @@ class Car {
114
67
  return this.stereo.SetStation(frequency);
115
68
  }
116
69
  }
117
- ```
118
-
119
- The `Car` class above uses dependency injection for its engine, odometer, and stereo dependencies.
120
-
121
- It's a best practice to use dependency injection over 'newing' up concretions inside a class instance. This allows true unit testing as well as widely opening the door to future extendability.
122
-
123
- ### Example
124
- Here's how you would use `tsmockit` to mock the above dependencies and test the `Car` class.
125
70
 
126
- ```ts
127
- // Instantiate mocks
128
- const mockIEngine = new Mock<IEngine>();
129
- const mockIOdometer = new Mock<IOdometer>();
130
- const mockIStereo = new Mock<IStereo>();
131
-
132
- // Instantiate car, passing mock 'Objects' as its dependencies
133
- const car = new Car(mockIEngine.Object, mockIOdometer.Object, mockIStereo.Object);
134
-
135
- // 'Setup' the mock odometer to return 100
136
- mockIOdometer.Setup(o => o.GetMileage(), 100);
137
-
138
- // Assert that the Car's mileage property returns 100 and that our mock GetMileage method is called exactly once
139
- expect(car.Mileage).toEqual(100);
140
- mockIOdometer.Verify(o => o.GetMileage(), 1);
141
-
142
- // Setup mock stereo to return different strings for different arguments
143
- mockIStereo.Setup(s => s.SetStation(1), 'Station set to 1');
144
- mockIStereo.Setup(s => s.SetStation(2), 'Station set to 2');
71
+ describe('Car', () => {
72
+ let car: Car;
73
+ const mockIEngine = new Mock<IEngine>();
74
+ const mockIOdometer = new Mock<IOdometer>();
75
+ const mockIStereo = new Mock<IStereo>();
76
+
77
+ beforeEach(() => {
78
+ car = new Car(mockIEngine.Object, mockIOdometer.Object, mockIStereo.Object);
79
+ });
80
+
81
+ it('should call Engine.Start when StartEngine is called', () => {
82
+ mockIEngine.Setup(e => e.Start());
83
+ car.StartEngine();
84
+ mockIEngine.Verify(e => e.Start(), Times.Once);
85
+ });
86
+
87
+ it('should call Engine.Stop when StopEngine is called', () => {
88
+ mockIEngine.Setup(e => e.Stop());
89
+ car.StopEngine();
90
+ mockIEngine.Verify(e => e.Stop(), Times.Once);
91
+ });
92
+
93
+ it('should return the result of Odometer.GetMileage on referencing the Mileage property', () => {
94
+ mockIOdometer.Setup(o => o.GetMileage(), 100);
95
+
96
+ const mileage = car.Mileage;
97
+
98
+ expect(mileage).toEqual(100);
99
+ mockIOdometer.Verify(o => o.GetMileage(), Times.Once);
100
+ });
101
+
102
+ it('should call Stereo.SetStation on calling ChangeRadioStation returning the string from Stereo', () => {
103
+ mockIStereo.Setup(s => s.SetStation(Any<number>()), 'Station set'); // default fallback setup when a more specific setup isn't available
104
+ mockIStereo.Setup(s => s.SetStation(3), 'Station 3');
105
+
106
+ expect(car.ChangeRadioStation(3)).toEqual('Station 3');
107
+ expect(car.ChangeRadioStation(0)).toEqual('Station set');
108
+ expect(car.ChangeRadioStation(2)).toEqual('Station set');
109
+
110
+ mockIStereo.Verify(s => s.SetStation(3), Times.Once);
111
+ mockIStereo.Verify(s => s.SetStation(Any<number>()), 2);
112
+ });
113
+ });
145
114
  ```
146
115
 
147
- ## Conventions
148
-
149
- ***This convention will be replaced by passing `false` to the `exactSignatureMatch` param when calling `Setup` in version 2.0.0.***
150
-
151
- You'll often want a mock to return the same response regardless of input parameters. The following convention accommodates this:
152
-
153
- - If a method is called and no exact setup is available, the first `Setup` called without overriding `exactSignatureMatch` to `true` will be used.
116
+ ## Version 2 notes
117
+
118
+ - Any\<T\>
119
+ - A helper function which allows clients to create "Setups" on methods to be used disregarding all, or some, of the exact values the method is called with.
120
+ ```typescript
121
+ mockIStereo.Setup(s => s.SetStation(Any<number>()), 'Station set');
122
+ ```
123
+ - SetupOnce
124
+ - Creates a setup the same as the regular `Setup` method except for once the setup is used, it will de-register itself.
125
+ - One use could be an inferred guarantee that a given method on a dependency is not being called more than you expect. Using `SetupOnce` for a setup that should only be used once, will have the inherent effect of leading to a runtime error at test time on the second execution.
126
+ - SetupSequence
127
+ - Creates several, "one time" setups for a given method.
128
+ - You'll occasionally want the first execution of a given method on a dependency to return "x" but then "y" on the following execution. Use `SetupSequence` to achieve this.
@@ -1,4 +1,3 @@
1
1
  export * from './EmitEventAtElement';
2
2
  export * from './EmitKeyEventAtElement';
3
3
  export * from './Expect';
4
- export * from './TestHelpers';
package/Utility/module.js CHANGED
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  var tslib_1 = require("tslib");
4
- (0, tslib_1.__exportStar)(require("./EmitEventAtElement"), exports);
5
- (0, tslib_1.__exportStar)(require("./EmitKeyEventAtElement"), exports);
6
- (0, tslib_1.__exportStar)(require("./Expect"), exports);
7
- (0, tslib_1.__exportStar)(require("./TestHelpers"), exports);
4
+ tslib_1.__exportStar(require("./EmitEventAtElement"), exports);
5
+ tslib_1.__exportStar(require("./EmitKeyEventAtElement"), exports);
6
+ tslib_1.__exportStar(require("./Expect"), exports);
8
7
  //# sourceMappingURL=module.js.map
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "dependency injection"
15
15
  ],
16
16
  "license": "MIT",
17
- "version": "1.3.0",
17
+ "version": "2.0.2",
18
18
  "description": "Generic mocking library for TypeScript",
19
19
  "private": false,
20
20
  "main": "./public_api.js",
package/public_api.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  var tslib_1 = require("tslib");
4
- (0, tslib_1.__exportStar)(require("./Mock/module"), exports);
5
- (0, tslib_1.__exportStar)(require("./Utility/module"), exports);
4
+ tslib_1.__exportStar(require("./Mock/module"), exports);
5
+ tslib_1.__exportStar(require("./Utility/module"), exports);
6
6
  //# sourceMappingURL=public_api.js.map
@@ -1,10 +0,0 @@
1
- export declare type FunctionMap = {
2
- default: boolean;
3
- state: string;
4
- returns: Function;
5
- timesCalled: number;
6
- };
7
- export declare type SignatureMap = {
8
- signature: string;
9
- functionMaps: Array<FunctionMap>;
10
- };
@@ -1,33 +0,0 @@
1
- /// <reference types="jasmine" />
2
- /**
3
- * @deprecated This class will be removed in v2 - Import its functions directly as of 1.3.0
4
- */
5
- export declare class TestHelpers {
6
- /**
7
- * Emit an event at a given element
8
- * @param element
9
- * @param eventType
10
- */
11
- static EmitEventAtElement(element: HTMLElement, eventType: string): void;
12
- /**
13
- * Emit a key event at a given element
14
- * @param element
15
- * @param key
16
- * @param keyEvent
17
- */
18
- static EmitKeyEventAtElement(element: HTMLInputElement, key: string, keyEvent: 'keydown' | 'keypress' | 'keyup' | 'input'): void;
19
- /**
20
- * Wait up to 1 second for a given condition to be true
21
- * @deprecated Will be removed in version 2 - Use "Expect" instead
22
- * @param condition
23
- * @param interval
24
- * @returns true if condition is met before 1 second limit, false otherwise
25
- */
26
- static TimeLapsedCondition(condition: () => boolean, interval?: number): Promise<boolean>;
27
- /**
28
- * Performs an asynchronous assertion, allowing up to one second to pass before failing
29
- * @param selector A function that returns the subject of the assertion once it is expected to pass.
30
- * @param assertion A function that is given the result of the selector function for normal jasmine assertions.
31
- */
32
- static Expect<T>(selector: () => T, assertion: (m: jasmine.Matchers<T>) => void, interval?: number, getTimeFunc?: () => number): Promise<void>;
33
- }
@@ -1,83 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TestHelpers = void 0;
4
- var tslib_1 = require("tslib");
5
- var EmitEventAtElement_1 = require("./EmitEventAtElement");
6
- var EmitKeyEventAtElement_1 = require("./EmitKeyEventAtElement");
7
- var Expect_1 = require("./Expect");
8
- /**
9
- * @deprecated This class will be removed in v2 - Import its functions directly as of 1.3.0
10
- */
11
- var TestHelpers = /** @class */ (function () {
12
- function TestHelpers() {
13
- }
14
- /**
15
- * Emit an event at a given element
16
- * @param element
17
- * @param eventType
18
- */
19
- TestHelpers.EmitEventAtElement = function (element, eventType) {
20
- (0, EmitEventAtElement_1.EmitEventAtElement)(element, eventType);
21
- };
22
- /**
23
- * Emit a key event at a given element
24
- * @param element
25
- * @param key
26
- * @param keyEvent
27
- */
28
- TestHelpers.EmitKeyEventAtElement = function (element, key, keyEvent) {
29
- (0, EmitKeyEventAtElement_1.EmitKeyEventAtElement)(element, key, keyEvent);
30
- };
31
- /**
32
- * Wait up to 1 second for a given condition to be true
33
- * @deprecated Will be removed in version 2 - Use "Expect" instead
34
- * @param condition
35
- * @param interval
36
- * @returns true if condition is met before 1 second limit, false otherwise
37
- */
38
- TestHelpers.TimeLapsedCondition = function (condition, interval) {
39
- if (interval === void 0) { interval = 10; }
40
- return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
41
- var _this = this;
42
- return (0, tslib_1.__generator)(this, function (_a) {
43
- return [2 /*return*/, new Promise(function (resolve) {
44
- var assertionPassed = false;
45
- var elapsedTime = 0;
46
- var enabled = (function () {
47
- return !assertionPassed && elapsedTime < 1000;
48
- });
49
- var executer = setInterval(function () { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
50
- return (0, tslib_1.__generator)(this, function (_a) {
51
- elapsedTime += interval;
52
- if (enabled()) {
53
- assertionPassed = condition();
54
- }
55
- else {
56
- clearInterval(executer);
57
- resolve(assertionPassed);
58
- }
59
- return [2 /*return*/];
60
- });
61
- }); }, interval);
62
- })];
63
- });
64
- });
65
- };
66
- /**
67
- * Performs an asynchronous assertion, allowing up to one second to pass before failing
68
- * @param selector A function that returns the subject of the assertion once it is expected to pass.
69
- * @param assertion A function that is given the result of the selector function for normal jasmine assertions.
70
- */
71
- TestHelpers.Expect = function (selector, assertion, interval, getTimeFunc) {
72
- if (interval === void 0) { interval = 0; }
73
- if (getTimeFunc === void 0) { getTimeFunc = function () { return Date.now(); }; }
74
- return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
75
- return (0, tslib_1.__generator)(this, function (_a) {
76
- return [2 /*return*/, (0, Expect_1.Expect)(selector, assertion, interval, getTimeFunc)];
77
- });
78
- });
79
- };
80
- return TestHelpers;
81
- }());
82
- exports.TestHelpers = TestHelpers;
83
- //# sourceMappingURL=TestHelpers.js.map