strong-mock 7.3.0 → 8.0.0-beta.0
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/README.md +79 -83
- package/dist/errors.d.ts +1 -1
- package/dist/expectation/it.d.ts +1 -1
- package/dist/expectation/repository/base-repository.d.ts +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +921 -889
- package/dist/index.js.map +1 -0
- package/dist/mock/defaults.d.ts +2 -2
- package/dist/mock/map.d.ts +1 -1
- package/dist/mock/mock.d.ts +5 -4
- package/dist/mock/stub.d.ts +11 -2
- package/dist/return/returns.d.ts +6 -6
- package/dist/verify/reset.d.ts +2 -2
- package/dist/verify/verify.d.ts +1 -1
- package/dist/when/when.d.ts +6 -5
- package/package.json +22 -24
- package/CHANGELOG.md +0 -150
- package/dist/instance/instance.d.ts +0 -14
package/dist/index.js
CHANGED
|
@@ -1,180 +1,124 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
1
|
var jestMatcherUtils = require('jest-matcher-utils');
|
|
6
2
|
var lodash = require('lodash');
|
|
7
3
|
|
|
8
|
-
|
|
4
|
+
const MATCHER_SYMBOL = Symbol('matcher');
|
|
9
5
|
/**
|
|
10
6
|
* Used to test if an expectation on an argument is a custom matcher.
|
|
11
|
-
*/
|
|
12
|
-
function isMatcher(f) {
|
|
13
|
-
return !!(f && f[MATCHER_SYMBOL]);
|
|
14
|
-
}
|
|
7
|
+
*/
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
20
|
-
purpose with or without fee is hereby granted.
|
|
21
|
-
|
|
22
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
23
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
24
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
25
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
26
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
27
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
28
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
29
|
-
***************************************************************************** */
|
|
30
|
-
/* global Reflect, Promise */
|
|
31
|
-
|
|
32
|
-
var extendStatics = function(d, b) {
|
|
33
|
-
extendStatics = Object.setPrototypeOf ||
|
|
34
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
35
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
36
|
-
return extendStatics(d, b);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
function __extends(d, b) {
|
|
40
|
-
if (typeof b !== "function" && b !== null)
|
|
41
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
42
|
-
extendStatics(d, b);
|
|
43
|
-
function __() { this.constructor = d; }
|
|
44
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
var __assign = function() {
|
|
48
|
-
__assign = Object.assign || function __assign(t) {
|
|
49
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
50
|
-
s = arguments[i];
|
|
51
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
52
|
-
}
|
|
53
|
-
return t;
|
|
54
|
-
};
|
|
55
|
-
return __assign.apply(this, arguments);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
function __read(o, n) {
|
|
59
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
60
|
-
if (!m) return o;
|
|
61
|
-
var i = m.call(o), r, ar = [], e;
|
|
62
|
-
try {
|
|
63
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
64
|
-
}
|
|
65
|
-
catch (error) { e = { error: error }; }
|
|
66
|
-
finally {
|
|
67
|
-
try {
|
|
68
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
69
|
-
}
|
|
70
|
-
finally { if (e) throw e.error; }
|
|
71
|
-
}
|
|
72
|
-
return ar;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function __spreadArray(to, from) {
|
|
76
|
-
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
|
|
77
|
-
to[j] = from[i];
|
|
78
|
-
return to;
|
|
9
|
+
function isMatcher(f) {
|
|
10
|
+
return !!(f && f[MATCHER_SYMBOL]);
|
|
79
11
|
}
|
|
80
12
|
|
|
81
13
|
/**
|
|
82
14
|
* Special symbol denoting the call of a function.
|
|
83
|
-
*/
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
};
|
|
104
|
-
var printReturns = function (_a, min, max) {
|
|
105
|
-
var isError = _a.isError, isPromise = _a.isPromise, value = _a.value;
|
|
106
|
-
var thenPrefix = '';
|
|
107
|
-
if (isPromise) {
|
|
108
|
-
if (isError) {
|
|
109
|
-
thenPrefix += 'thenReject';
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
thenPrefix += 'thenResolve';
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
else if (isError) {
|
|
116
|
-
thenPrefix += 'thenThrow';
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
thenPrefix += 'thenReturn';
|
|
120
|
-
}
|
|
121
|
-
return "." + thenPrefix + "(" + jestMatcherUtils.printExpected(value) + ").between(" + min + ", " + max + ")";
|
|
122
|
-
};
|
|
123
|
-
var printWhen = function (property, args) {
|
|
124
|
-
if (args) {
|
|
125
|
-
return "when(" + jestMatcherUtils.EXPECTED_COLOR("mock" + printCall(property, args)) + ")";
|
|
126
|
-
}
|
|
127
|
-
return "when(" + jestMatcherUtils.EXPECTED_COLOR("mock" + printProperty(property)) + ")";
|
|
128
|
-
};
|
|
129
|
-
var printExpectation = function (property, args, returnValue, min, max) { return "" + printWhen(property, args) + printReturns(returnValue, min, max); };
|
|
130
|
-
var printRemainingExpectations = function (expectations) {
|
|
131
|
-
return expectations.length
|
|
132
|
-
? "Remaining unmet expectations:\n - " + expectations.map(function (e) { return e.toJSON(); }).join('\n - ')
|
|
133
|
-
: 'There are no remaining unmet expectations.';
|
|
15
|
+
*/
|
|
16
|
+
const ApplyProp = Symbol('apply');
|
|
17
|
+
|
|
18
|
+
const printProperty = property => {
|
|
19
|
+
if (property === ApplyProp) {
|
|
20
|
+
return '';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (typeof property === 'symbol') {
|
|
24
|
+
return `[${property.toString()}]`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return `.${property}`;
|
|
28
|
+
};
|
|
29
|
+
const printArg = arg => // Call toJSON on matchers directly to avoid wrapping them in quotes.
|
|
30
|
+
isMatcher(arg) ? arg.toJSON() : jestMatcherUtils.printExpected(arg);
|
|
31
|
+
const printCall = (property, args) => {
|
|
32
|
+
const prettyArgs = args.map(arg => printArg(arg)).join(', ');
|
|
33
|
+
const prettyProperty = printProperty(property);
|
|
34
|
+
return `${prettyProperty}(${prettyArgs})`;
|
|
134
35
|
};
|
|
36
|
+
const printReturns = ({
|
|
37
|
+
isError,
|
|
38
|
+
isPromise,
|
|
39
|
+
value
|
|
40
|
+
}, min, max) => {
|
|
41
|
+
let thenPrefix = '';
|
|
42
|
+
|
|
43
|
+
if (isPromise) {
|
|
44
|
+
if (isError) {
|
|
45
|
+
thenPrefix += 'thenReject';
|
|
46
|
+
} else {
|
|
47
|
+
thenPrefix += 'thenResolve';
|
|
48
|
+
}
|
|
49
|
+
} else if (isError) {
|
|
50
|
+
thenPrefix += 'thenThrow';
|
|
51
|
+
} else {
|
|
52
|
+
thenPrefix += 'thenReturn';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return `.${thenPrefix}(${jestMatcherUtils.printExpected(value)}).between(${min}, ${max})`;
|
|
56
|
+
};
|
|
57
|
+
const printWhen = (property, args) => {
|
|
58
|
+
if (args) {
|
|
59
|
+
return `when(${jestMatcherUtils.EXPECTED_COLOR(`mock${printCall(property, args)}`)})`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return `when(${jestMatcherUtils.EXPECTED_COLOR(`mock${printProperty(property)}`)})`;
|
|
63
|
+
};
|
|
64
|
+
const printExpectation = (property, args, returnValue, min, max) => `${printWhen(property, args)}${printReturns(returnValue, min, max)}`;
|
|
65
|
+
const printRemainingExpectations = expectations => expectations.length ? `Remaining unmet expectations:
|
|
66
|
+
- ${expectations.map(e => e.toJSON()).join('\n - ')}` : 'There are no remaining unmet expectations.';
|
|
67
|
+
|
|
68
|
+
class UnfinishedExpectation extends Error {
|
|
69
|
+
constructor(pendingExpectation) {
|
|
70
|
+
super(`There is an unfinished pending expectation:
|
|
135
71
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
72
|
+
${pendingExpectation.toJSON()}
|
|
73
|
+
|
|
74
|
+
Please finish it by setting a return value even if the value
|
|
75
|
+
is undefined.`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
}
|
|
79
|
+
class MissingWhen extends Error {
|
|
80
|
+
constructor() {
|
|
81
|
+
super(`You tried setting a return value without an expectation.
|
|
82
|
+
|
|
83
|
+
Every call to set a return value must be preceded by an expectation.`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
class UnexpectedAccess extends Error {
|
|
88
|
+
constructor(property, expectations) {
|
|
89
|
+
super(`Didn't expect ${jestMatcherUtils.EXPECTED_COLOR(`mock${printProperty(property)}`)} to be accessed.
|
|
90
|
+
|
|
91
|
+
If you expect this property to be accessed then please
|
|
92
|
+
set an expectation for it.
|
|
93
|
+
|
|
94
|
+
${printRemainingExpectations(expectations)}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
}
|
|
98
|
+
class UnexpectedCall extends Error {
|
|
99
|
+
constructor(property, args, expectations) {
|
|
100
|
+
super(`Didn't expect ${jestMatcherUtils.EXPECTED_COLOR(`mock${printCall(property, args)}`)} to be called.
|
|
101
|
+
|
|
102
|
+
${printRemainingExpectations(expectations)}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
class NotAMock extends Error {
|
|
107
|
+
constructor() {
|
|
108
|
+
super(`We couldn't find the mock.
|
|
109
|
+
|
|
110
|
+
Make sure you're passing in an actual mock.`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
class UnmetExpectations extends Error {
|
|
115
|
+
constructor(expectations) {
|
|
116
|
+
super(`There are unmet expectations:
|
|
117
|
+
|
|
118
|
+
- ${expectations.map(e => e.toJSON()).join('\n - ')}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
}
|
|
178
122
|
/**
|
|
179
123
|
* Merge property accesses and method calls for the same property
|
|
180
124
|
* into a single call.
|
|
@@ -182,335 +126,375 @@ var UnmetExpectations = /** @class */ (function (_super) {
|
|
|
182
126
|
* @example
|
|
183
127
|
* mergeCalls({ foo: [{ arguments: undefined }, { arguments: [1, 2, 3] }] }
|
|
184
128
|
* // returns { foo: [{ arguments: [1, 2, 3] } }
|
|
185
|
-
*/
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
const mergeCalls = callMap => new Map(Array.from(callMap.entries()).map(([property, calls]) => {
|
|
132
|
+
const hasMethodCalls = calls.some(call => call.arguments);
|
|
133
|
+
const hasPropertyAccesses = calls.some(call => !call.arguments);
|
|
134
|
+
|
|
135
|
+
if (hasMethodCalls && hasPropertyAccesses) {
|
|
136
|
+
return [property, calls.filter(call => call.arguments)];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return [property, calls];
|
|
140
|
+
}));
|
|
141
|
+
|
|
142
|
+
class UnexpectedCalls extends Error {
|
|
143
|
+
constructor(unexpectedCalls, expectations) {
|
|
144
|
+
const printedCalls = Array.from(mergeCalls(unexpectedCalls).entries()).map(([property, calls]) => calls.map(call => call.arguments ? jestMatcherUtils.EXPECTED_COLOR(`mock${printCall(property, call.arguments)}`) : jestMatcherUtils.EXPECTED_COLOR(`mock${printProperty(property)}`)).join('\n - ')).join('\n - ');
|
|
145
|
+
super(`The following calls were unexpected:
|
|
146
|
+
|
|
147
|
+
- ${printedCalls}
|
|
148
|
+
|
|
149
|
+
${printRemainingExpectations(expectations)}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
class NestedWhen extends Error {
|
|
154
|
+
constructor(parentProp, childProp) {
|
|
155
|
+
const snippet = `
|
|
156
|
+
const parentMock = mock<T1>();
|
|
157
|
+
const childMock = mock<T2>();
|
|
158
|
+
|
|
159
|
+
when(() => childMock${printProperty(childProp)}).thenReturn(...);
|
|
160
|
+
when(() => parentMock${printProperty(parentProp)}).thenReturn(childMock)
|
|
161
|
+
`;
|
|
162
|
+
super(`Setting an expectation on a nested property is not supported.
|
|
163
|
+
|
|
164
|
+
You can return an object directly when the first property is accessed,
|
|
165
|
+
or you can even return a separate mock:
|
|
166
|
+
${snippet}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const createProxy = traps => // eslint-disable-next-line no-empty-function
|
|
172
|
+
new Proxy(
|
|
173
|
+
/* istanbul ignore next */
|
|
174
|
+
() => {}, {
|
|
175
|
+
get: (target, prop) => {
|
|
176
|
+
if (prop === 'bind') {
|
|
177
|
+
return (thisArg, ...args) => (...moreArgs) => traps.apply([...args, ...moreArgs]);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (prop === 'apply') {
|
|
181
|
+
return (thisArg, args) => traps.apply(args || []);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (prop === 'call') {
|
|
185
|
+
return (thisArg, ...args) => traps.apply(args);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return traps.property(prop);
|
|
189
|
+
},
|
|
190
|
+
apply: (target, thisArg, args) => traps.apply(args),
|
|
191
|
+
ownKeys: () => traps.ownKeys(),
|
|
192
|
+
|
|
193
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
194
|
+
const keys = traps.ownKeys();
|
|
195
|
+
|
|
196
|
+
if (keys.includes(prop)) {
|
|
197
|
+
return {
|
|
198
|
+
configurable: true,
|
|
199
|
+
enumerable: true
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
});
|
|
228
207
|
|
|
229
208
|
/**
|
|
230
|
-
* Since `when
|
|
209
|
+
* Since `when` doesn't receive the mock subject (because we can't make it
|
|
231
210
|
* consistently return it from `mock()`, `mock.foo` and `mock.bar()`) we need
|
|
232
211
|
* to store a global state for the currently active mock.
|
|
233
212
|
*
|
|
234
213
|
* We also want to throw in the following case:
|
|
235
214
|
*
|
|
236
215
|
* ```
|
|
237
|
-
* when(mock()) // forgot returns here
|
|
238
|
-
* when(mock()) // should throw
|
|
216
|
+
* when(() => mock()) // forgot returns here
|
|
217
|
+
* when(() => mock()) // should throw
|
|
239
218
|
* ```
|
|
240
219
|
*
|
|
241
220
|
* For that reason we can't just store the currently active mock, but also
|
|
242
221
|
* whether we finished the expectation or not.
|
|
243
|
-
*/
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
222
|
+
*/
|
|
223
|
+
|
|
224
|
+
let activeMock;
|
|
225
|
+
const setActiveMock = mock => {
|
|
226
|
+
activeMock = mock;
|
|
227
|
+
};
|
|
228
|
+
const getActiveMock = () => activeMock;
|
|
249
229
|
/**
|
|
250
230
|
* Store a global map of all mocks created and their state.
|
|
251
231
|
*
|
|
252
|
-
* This is needed because we can't reliably pass the state between `when
|
|
253
|
-
*
|
|
254
|
-
*/
|
|
255
|
-
var mockMap = new Map();
|
|
256
|
-
var getMockState = function (mock) {
|
|
257
|
-
if (mockMap.has(mock)) {
|
|
258
|
-
return mockMap.get(mock);
|
|
259
|
-
}
|
|
260
|
-
throw new NotAMock();
|
|
261
|
-
};
|
|
262
|
-
var setMockState = function (mock, state) {
|
|
263
|
-
mockMap.set(mock, state);
|
|
264
|
-
};
|
|
265
|
-
var getAllMocks = function () {
|
|
266
|
-
return Array.from(mockMap.entries());
|
|
267
|
-
};
|
|
232
|
+
* This is needed because we can't reliably pass the state between `when`
|
|
233
|
+
* and `thenReturn`.
|
|
234
|
+
*/
|
|
268
235
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
return function () {
|
|
280
|
-
var moreArgs = [];
|
|
281
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
282
|
-
moreArgs[_i] = arguments[_i];
|
|
283
|
-
}
|
|
284
|
-
return traps.apply(__spreadArray(__spreadArray([], __read(args), false), __read(moreArgs)));
|
|
285
|
-
};
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
if (prop === 'apply') {
|
|
289
|
-
return function (thisArg, args) {
|
|
290
|
-
return traps.apply(args || []);
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
if (prop === 'call') {
|
|
294
|
-
return function (thisArg) {
|
|
295
|
-
var args = [];
|
|
296
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
297
|
-
args[_i - 1] = arguments[_i];
|
|
298
|
-
}
|
|
299
|
-
return traps.apply(args);
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
return traps.property(prop);
|
|
303
|
-
},
|
|
304
|
-
apply: function (target, thisArg, args) { return traps.apply(args); },
|
|
305
|
-
ownKeys: function () { return traps.ownKeys(); },
|
|
306
|
-
getOwnPropertyDescriptor: function (target, prop) {
|
|
307
|
-
var keys = traps.ownKeys();
|
|
308
|
-
if (keys.includes(prop)) {
|
|
309
|
-
return {
|
|
310
|
-
configurable: true,
|
|
311
|
-
enumerable: true,
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
return undefined;
|
|
315
|
-
},
|
|
316
|
-
});
|
|
236
|
+
const mockMap = new Map();
|
|
237
|
+
const getMockState = mock => {
|
|
238
|
+
if (mockMap.has(mock)) {
|
|
239
|
+
return mockMap.get(mock);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
throw new NotAMock();
|
|
243
|
+
};
|
|
244
|
+
const setMockState = (mock, state) => {
|
|
245
|
+
mockMap.set(mock, state);
|
|
317
246
|
};
|
|
247
|
+
const getAllMocks = () => Array.from(mockMap.entries());
|
|
318
248
|
|
|
319
|
-
// Keep a cache of all mock instances so that we can return a stable reference
|
|
320
|
-
// if `instance` is used multiple times.
|
|
321
|
-
var cache = new Map();
|
|
322
249
|
/**
|
|
323
250
|
* Return the expectation's return value.
|
|
324
251
|
*
|
|
325
252
|
* If the value is an error then throw it.
|
|
326
253
|
*
|
|
327
254
|
* If the value is a promise then resolve/reject it.
|
|
328
|
-
*/
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
var repository = getMockState(mock).repository;
|
|
353
|
-
var proxy = createProxy({
|
|
354
|
-
property: function (property) { return returnOrThrow(repository.get(property)); },
|
|
355
|
-
apply: function (args) {
|
|
356
|
-
var fn = repository.get(ApplyProp);
|
|
357
|
-
// This is not using `returnOrThrow` because the repo will use it.
|
|
358
|
-
return fn.value.apply(fn, __spreadArray([], __read(args)));
|
|
359
|
-
},
|
|
360
|
-
ownKeys: function () { return repository.getAllProperties(); },
|
|
361
|
-
});
|
|
362
|
-
cache.set(mock, proxy);
|
|
363
|
-
return proxy;
|
|
255
|
+
*/
|
|
256
|
+
|
|
257
|
+
const returnOrThrow = ({
|
|
258
|
+
isError,
|
|
259
|
+
isPromise,
|
|
260
|
+
value
|
|
261
|
+
}) => {
|
|
262
|
+
if (isError) {
|
|
263
|
+
if (isPromise) {
|
|
264
|
+
return Promise.reject(value);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (value instanceof Error) {
|
|
268
|
+
throw value;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
throw new Error(value);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (isPromise) {
|
|
275
|
+
return Promise.resolve(value);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return value;
|
|
364
279
|
};
|
|
280
|
+
const createStub = (repo, pendingExpectation, isRecording = () => true) => {
|
|
281
|
+
const stub = createProxy({
|
|
282
|
+
property: property => {
|
|
283
|
+
if (!isRecording()) {
|
|
284
|
+
return returnOrThrow(repo.get(property));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
setActiveMock(stub);
|
|
288
|
+
pendingExpectation.start(repo); // eslint-disable-next-line no-param-reassign
|
|
289
|
+
|
|
290
|
+
pendingExpectation.property = property;
|
|
291
|
+
return createProxy({
|
|
292
|
+
property: childProp => {
|
|
293
|
+
pendingExpectation.clear();
|
|
294
|
+
throw new NestedWhen(property, childProp);
|
|
295
|
+
},
|
|
296
|
+
apply: args => {
|
|
297
|
+
// eslint-disable-next-line no-param-reassign
|
|
298
|
+
pendingExpectation.args = args;
|
|
299
|
+
},
|
|
300
|
+
ownKeys: () => {
|
|
301
|
+
throw new Error('Spreading during an expectation is not supported.');
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
},
|
|
305
|
+
apply: args => {
|
|
306
|
+
if (!isRecording()) {
|
|
307
|
+
const fn = repo.get(ApplyProp); // This is not using `returnOrThrow` because the repo will use it.
|
|
308
|
+
|
|
309
|
+
return fn.value(...args);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
setActiveMock(stub);
|
|
313
|
+
pendingExpectation.start(repo); // eslint-disable-next-line no-param-reassign
|
|
314
|
+
|
|
315
|
+
pendingExpectation.property = ApplyProp; // eslint-disable-next-line no-param-reassign
|
|
316
|
+
|
|
317
|
+
pendingExpectation.args = args;
|
|
318
|
+
return undefined;
|
|
319
|
+
},
|
|
320
|
+
ownKeys: () => {
|
|
321
|
+
if (!isRecording()) {
|
|
322
|
+
return repo.getAllProperties();
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
throw new Error('Spreading during an expectation is not supported.');
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
return stub;
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
class BaseRepository {
|
|
332
|
+
constructor() {
|
|
333
|
+
this.expectations = new Map();
|
|
334
|
+
this.expectedCallStats = new Map();
|
|
335
|
+
this.unexpectedCallStats = new Map();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
add(expectation) {
|
|
339
|
+
const {
|
|
340
|
+
property
|
|
341
|
+
} = expectation;
|
|
342
|
+
const expectations = this.expectations.get(property) || [];
|
|
343
|
+
this.expectations.set(property, [...expectations, {
|
|
344
|
+
expectation,
|
|
345
|
+
matchCount: 0
|
|
346
|
+
}]);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
clear() {
|
|
350
|
+
this.expectations.clear();
|
|
351
|
+
this.expectedCallStats.clear();
|
|
352
|
+
this.unexpectedCallStats.clear();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
get(property) {
|
|
356
|
+
const expectations = this.expectations.get(property);
|
|
357
|
+
|
|
358
|
+
if (expectations && expectations.length) {
|
|
359
|
+
// We record that an expected property access has happened, but an
|
|
360
|
+
// unexpected call could still happen later.
|
|
361
|
+
this.recordExpected(property, undefined);
|
|
362
|
+
const propertyExpectation = expectations.find(e => e.expectation.matches(undefined));
|
|
365
363
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
var calls = this.expectedCallStats.get(property) || [];
|
|
474
|
-
this.expectedCallStats.set(property, __spreadArray(__spreadArray([], __read(calls), false), [{ arguments: args }]));
|
|
475
|
-
};
|
|
476
|
-
/**
|
|
477
|
-
* Record an unexpected property access/method call.
|
|
478
|
-
*/
|
|
479
|
-
BaseRepository.prototype.recordUnexpected = function (property, args) {
|
|
480
|
-
var calls = this.unexpectedCallStats.get(property) || [];
|
|
481
|
-
this.unexpectedCallStats.set(property, __spreadArray(__spreadArray([], __read(calls), false), [{ arguments: args }]));
|
|
482
|
-
};
|
|
483
|
-
BaseRepository.prototype.countAndConsume = function (expectation) {
|
|
484
|
-
// eslint-disable-next-line no-param-reassign
|
|
485
|
-
expectation.matchCount++;
|
|
486
|
-
this.consumeExpectation(expectation);
|
|
487
|
-
};
|
|
488
|
-
return BaseRepository;
|
|
489
|
-
}());
|
|
364
|
+
if (propertyExpectation) {
|
|
365
|
+
this.countAndConsume(propertyExpectation);
|
|
366
|
+
return propertyExpectation.expectation.returnValue;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return {
|
|
370
|
+
value: (...args) => {
|
|
371
|
+
const callExpectation = expectations.find(e => e.expectation.matches(args));
|
|
372
|
+
|
|
373
|
+
if (callExpectation) {
|
|
374
|
+
this.recordExpected(property, args);
|
|
375
|
+
this.countAndConsume(callExpectation); // TODO: this is duplicated in stub
|
|
376
|
+
|
|
377
|
+
return returnOrThrow(callExpectation.expectation.returnValue);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
this.recordUnexpected(property, args);
|
|
381
|
+
return this.getValueForUnexpectedCall(property, args);
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
switch (property) {
|
|
387
|
+
case 'toString':
|
|
388
|
+
return {
|
|
389
|
+
value: () => 'mock'
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
case '@@toStringTag':
|
|
393
|
+
case Symbol.toStringTag:
|
|
394
|
+
case 'name':
|
|
395
|
+
return {
|
|
396
|
+
value: 'mock'
|
|
397
|
+
};
|
|
398
|
+
// pretty-format
|
|
399
|
+
|
|
400
|
+
case '$$typeof':
|
|
401
|
+
case 'constructor':
|
|
402
|
+
case '@@__IMMUTABLE_ITERABLE__@@':
|
|
403
|
+
case '@@__IMMUTABLE_RECORD__@@':
|
|
404
|
+
return {
|
|
405
|
+
value: null
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
case MATCHER_SYMBOL:
|
|
409
|
+
return {
|
|
410
|
+
value: false
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
case ApplyProp:
|
|
414
|
+
return {
|
|
415
|
+
value: (...args) => {
|
|
416
|
+
this.recordUnexpected(property, args);
|
|
417
|
+
return this.getValueForUnexpectedCall(property, args);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
default:
|
|
422
|
+
this.recordUnexpected(property, undefined);
|
|
423
|
+
return this.getValueForUnexpectedAccess(property);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
getAllProperties() {
|
|
428
|
+
return Array.from(this.expectations.keys());
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
getCallStats() {
|
|
432
|
+
return {
|
|
433
|
+
expected: this.expectedCallStats,
|
|
434
|
+
unexpected: this.unexpectedCallStats
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
getUnmet() {
|
|
439
|
+
return [].concat(...Array.from(this.expectations.values()).map(expectations => expectations.filter(e => e.expectation.min > e.matchCount).map(e => e.expectation)));
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Record an expected property access/method call.
|
|
443
|
+
*/
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
recordExpected(property, args) {
|
|
447
|
+
const calls = this.expectedCallStats.get(property) || [];
|
|
448
|
+
this.expectedCallStats.set(property, [...calls, {
|
|
449
|
+
arguments: args
|
|
450
|
+
}]);
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Record an unexpected property access/method call.
|
|
454
|
+
*/
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
recordUnexpected(property, args) {
|
|
458
|
+
const calls = this.unexpectedCallStats.get(property) || [];
|
|
459
|
+
this.unexpectedCallStats.set(property, [...calls, {
|
|
460
|
+
arguments: args
|
|
461
|
+
}]);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
countAndConsume(expectation) {
|
|
465
|
+
// eslint-disable-next-line no-param-reassign
|
|
466
|
+
expectation.matchCount++;
|
|
467
|
+
this.consumeExpectation(expectation);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
}
|
|
490
471
|
|
|
491
472
|
/**
|
|
492
473
|
* Throw if no expectation matches.
|
|
493
|
-
*/
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
474
|
+
*/
|
|
475
|
+
|
|
476
|
+
class StrongRepository extends BaseRepository {
|
|
477
|
+
consumeExpectation(expectation) {
|
|
478
|
+
const {
|
|
479
|
+
property,
|
|
480
|
+
max
|
|
481
|
+
} = expectation.expectation;
|
|
482
|
+
const expectations = this.expectations.get(property);
|
|
483
|
+
|
|
484
|
+
if (expectation.matchCount === max) {
|
|
485
|
+
this.expectations.set(property, expectations.filter(e => e !== expectation));
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
getValueForUnexpectedCall(property, args) {
|
|
490
|
+
throw new UnexpectedCall(property, args, this.getUnmet());
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
getValueForUnexpectedAccess(property) {
|
|
494
|
+
throw new UnexpectedAccess(property, this.getUnmet());
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
}
|
|
514
498
|
|
|
515
499
|
/**
|
|
516
500
|
* Matches a call with more parameters than expected because it is assumed the
|
|
@@ -522,91 +506,125 @@ var StrongRepository = /** @class */ (function (_super) {
|
|
|
522
506
|
* deepEquals([1, 2, 3]),
|
|
523
507
|
* 23
|
|
524
508
|
* ).matches('bar', [1, 2, 3]) === true;
|
|
525
|
-
*/
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
509
|
+
*/
|
|
510
|
+
|
|
511
|
+
class StrongExpectation {
|
|
512
|
+
constructor(property, args, returnValue) {
|
|
513
|
+
this.property = void 0;
|
|
514
|
+
this.args = void 0;
|
|
515
|
+
this.returnValue = void 0;
|
|
516
|
+
this.matched = 0;
|
|
517
|
+
this.min = 1;
|
|
518
|
+
this.max = 1;
|
|
519
|
+
this.property = property;
|
|
520
|
+
this.args = args;
|
|
521
|
+
this.returnValue = returnValue;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
setInvocationCount(min, max = 1) {
|
|
525
|
+
this.min = min;
|
|
526
|
+
this.max = max;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
matches(args) {
|
|
530
|
+
if (!this.matchesArgs(args)) {
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
this.matched++;
|
|
535
|
+
return this.max === 0 || this.matched <= this.max;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
isUnmet() {
|
|
539
|
+
return this.matched < this.min;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
matchesArgs(received) {
|
|
543
|
+
if (this.args === undefined) {
|
|
544
|
+
return !received;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (!received) {
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
return this.args.every((arg, i) => arg.matches(received[i]));
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
toJSON() {
|
|
555
|
+
return printExpectation(this.property, this.args, this.returnValue, this.min, this.max);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
class RepoSideEffectPendingExpectation {
|
|
561
|
+
constructor(createExpectation) {
|
|
562
|
+
this.createExpectation = void 0;
|
|
563
|
+
this._repo = void 0;
|
|
564
|
+
this._args = void 0;
|
|
565
|
+
this._property = '';
|
|
566
|
+
this.createExpectation = createExpectation;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
start(repo) {
|
|
570
|
+
if (this._repo) {
|
|
571
|
+
throw new UnfinishedExpectation(this);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
this.clear();
|
|
575
|
+
this._repo = repo;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
set property(value) {
|
|
579
|
+
this._property = value;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
set args(value) {
|
|
583
|
+
this._args = value;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
finish(returnValue) {
|
|
587
|
+
if (!this._repo) {
|
|
588
|
+
throw new MissingWhen();
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const expectation = this.createExpectation(this._property, this._args, returnValue);
|
|
592
|
+
|
|
593
|
+
this._repo.add(expectation);
|
|
594
|
+
|
|
595
|
+
this.clear();
|
|
596
|
+
return expectation;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
clear() {
|
|
600
|
+
this._repo = undefined;
|
|
601
|
+
this._args = undefined;
|
|
602
|
+
this._property = '';
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
toJSON() {
|
|
606
|
+
return printWhen(this._property, this._args);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
function _extends() {
|
|
612
|
+
_extends = Object.assign || function (target) {
|
|
613
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
614
|
+
var source = arguments[i];
|
|
615
|
+
|
|
616
|
+
for (var key in source) {
|
|
617
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
618
|
+
target[key] = source[key];
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return target;
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
return _extends.apply(this, arguments);
|
|
627
|
+
}
|
|
610
628
|
|
|
611
629
|
/**
|
|
612
630
|
* Match a custom predicate.
|
|
@@ -618,30 +636,34 @@ var RepoSideEffectPendingExpectation = /** @class */ (function () {
|
|
|
618
636
|
*
|
|
619
637
|
* @example
|
|
620
638
|
* const fn = mock<(x: number) => number>();
|
|
621
|
-
* when(fn(It.matches(x => x >= 0))).returns(42);
|
|
639
|
+
* when(() => fn(It.matches(x => x >= 0))).returns(42);
|
|
622
640
|
*
|
|
623
|
-
*
|
|
624
|
-
*
|
|
625
|
-
*/
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
641
|
+
* fn(2) === 42
|
|
642
|
+
* fn(-1) // throws
|
|
643
|
+
*/
|
|
644
|
+
|
|
645
|
+
const matches = (cb, {
|
|
646
|
+
toJSON = () => `matches(${cb.toString()})`
|
|
647
|
+
} = {}) => {
|
|
648
|
+
const matcher = {
|
|
649
|
+
[MATCHER_SYMBOL]: true,
|
|
650
|
+
matches: arg => cb(arg),
|
|
651
|
+
toJSON
|
|
652
|
+
};
|
|
653
|
+
return matcher;
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
const removeUndefined = object => {
|
|
657
|
+
if (Array.isArray(object)) {
|
|
658
|
+
return object.map(x => removeUndefined(x));
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (!lodash.isObjectLike(object)) {
|
|
662
|
+
return object;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return lodash.omitBy(object, lodash.isUndefined);
|
|
666
|
+
};
|
|
645
667
|
/**
|
|
646
668
|
* Compare values using deep equality.
|
|
647
669
|
*
|
|
@@ -652,40 +674,46 @@ var removeUndefined = function (object) {
|
|
|
652
674
|
* this to `false` will consider the objects in both cases as equal.
|
|
653
675
|
*
|
|
654
676
|
* @see It.is A matcher that uses strict equality.
|
|
655
|
-
*/
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
677
|
+
*/
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
const deepEquals = (expected, {
|
|
681
|
+
strict = true
|
|
682
|
+
} = {}) => matches(actual => {
|
|
683
|
+
if (strict) {
|
|
684
|
+
return lodash.isEqual(actual, expected);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
return lodash.isEqual(removeUndefined(actual), removeUndefined(expected));
|
|
688
|
+
}, {
|
|
689
|
+
toJSON: () => printArg(expected)
|
|
690
|
+
});
|
|
665
691
|
/**
|
|
666
692
|
* Compare values using `Object.is`.
|
|
667
693
|
*
|
|
668
694
|
* @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
|
|
669
695
|
*
|
|
670
696
|
* @see It.deepEquals A matcher that uses deep equality.
|
|
671
|
-
*/
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
};
|
|
697
|
+
*/
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
const is = expected => matches(actual => Object.is(actual, expected), {
|
|
701
|
+
toJSON: () => `${jestMatcherUtils.printExpected(expected)}`
|
|
702
|
+
});
|
|
677
703
|
/**
|
|
678
704
|
* Match any value, including `undefined` and `null`.
|
|
679
705
|
*
|
|
680
706
|
* @example
|
|
681
707
|
* const fn = mock<(x: number, y: string) => number>();
|
|
682
|
-
* when(fn(It.isAny(), It.isAny())).thenReturn(1);
|
|
708
|
+
* when(() => fn(It.isAny(), It.isAny())).thenReturn(1);
|
|
683
709
|
*
|
|
684
|
-
*
|
|
685
|
-
*/
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
710
|
+
* fn(23, 'foobar') === 1
|
|
711
|
+
*/
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
const isAny = () => matches(() => true, {
|
|
715
|
+
toJSON: () => 'anything'
|
|
716
|
+
});
|
|
689
717
|
/**
|
|
690
718
|
* Recursively match an object.
|
|
691
719
|
*
|
|
@@ -695,40 +723,41 @@ var isAny = function () {
|
|
|
695
723
|
*
|
|
696
724
|
* @example
|
|
697
725
|
* const fn = mock<(foo: { x: number, y: number }) => number>();
|
|
698
|
-
* when(fn(It.isObject({ x: 23 }))).returns(42);
|
|
726
|
+
* when(() => fn(It.isObject({ x: 23 }))).returns(42);
|
|
699
727
|
*
|
|
700
|
-
*
|
|
701
|
-
*
|
|
728
|
+
* fn({ x: 100, y: 200 }) // throws
|
|
729
|
+
* fn({ x: 23, y: 200 }) // returns 42
|
|
702
730
|
*
|
|
703
731
|
* @example
|
|
704
732
|
* It.isObject({ foo: It.isString() })
|
|
705
|
-
*/
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
}
|
|
733
|
+
*/
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
const isObject = partial => matches(actual => lodash.isMatchWith(actual, partial || {}, (argValue, partialValue) => {
|
|
737
|
+
if (isMatcher(partialValue)) {
|
|
738
|
+
return partialValue.matches(argValue);
|
|
739
|
+
} // Let lodash handle it otherwise.
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
return undefined;
|
|
743
|
+
}), {
|
|
744
|
+
toJSON: () => partial ? `object(${jestMatcherUtils.printExpected(partial)})` : 'object'
|
|
745
|
+
});
|
|
717
746
|
/**
|
|
718
747
|
* Match any number.
|
|
719
748
|
*
|
|
720
749
|
* @example
|
|
721
750
|
* const fn = mock<(x: number) => number>();
|
|
722
|
-
* when(fn(It.isNumber())).returns(42);
|
|
751
|
+
* when(() => fn(It.isNumber())).returns(42);
|
|
723
752
|
*
|
|
724
|
-
*
|
|
725
|
-
*
|
|
726
|
-
*/
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
};
|
|
753
|
+
* fn(20.5) === 42
|
|
754
|
+
* fn(NaN) // throws
|
|
755
|
+
*/
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
const isNumber = () => matches(actual => typeof actual === 'number' && !Number.isNaN(actual), {
|
|
759
|
+
toJSON: () => 'number'
|
|
760
|
+
});
|
|
732
761
|
/**
|
|
733
762
|
* Match a string, potentially by a pattern.
|
|
734
763
|
*
|
|
@@ -737,33 +766,37 @@ var isNumber = function () {
|
|
|
737
766
|
*
|
|
738
767
|
* @example
|
|
739
768
|
* const fn = mock<(x: string, y: string) => number>();
|
|
740
|
-
* when(fn(It.isString(), It.isString({ containing: 'bar' }))).returns(42);
|
|
769
|
+
* when(() => fn(It.isString(), It.isString({ containing: 'bar' }))).returns(42);
|
|
741
770
|
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
*/
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
771
|
+
* fn('foo', 'baz') // throws
|
|
772
|
+
* fn('foo', 'bar') === 42
|
|
773
|
+
*/
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
const isString = ({
|
|
777
|
+
matching,
|
|
778
|
+
containing
|
|
779
|
+
} = {}) => {
|
|
780
|
+
if (matching && containing) {
|
|
781
|
+
throw new Error('You can only pass `matching` or `containing`, not both.');
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
return matches(actual => {
|
|
785
|
+
var _matching$test;
|
|
786
|
+
|
|
787
|
+
if (typeof actual !== 'string') {
|
|
788
|
+
return false;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
if (containing) {
|
|
792
|
+
return actual.indexOf(containing) !== -1;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
return (_matching$test = matching == null ? void 0 : matching.test(actual)) != null ? _matching$test : true;
|
|
796
|
+
}, {
|
|
797
|
+
toJSON: () => containing || matching ? `string(${jestMatcherUtils.printExpected(containing || matching)})` : 'string'
|
|
798
|
+
});
|
|
799
|
+
};
|
|
767
800
|
/**
|
|
768
801
|
* Match an array.
|
|
769
802
|
*
|
|
@@ -774,38 +807,37 @@ var isString = function (_a) {
|
|
|
774
807
|
*
|
|
775
808
|
* @example
|
|
776
809
|
* const fn = mock<(arr: number[]) => number>();
|
|
777
|
-
* when(fn(It.isArray())).thenReturn(1);
|
|
778
|
-
* when(fn(It.isArray([2, 3]))).thenReturn(2);
|
|
810
|
+
* when(() => fn(It.isArray())).thenReturn(1);
|
|
811
|
+
* when(() => fn(It.isArray([2, 3]))).thenReturn(2);
|
|
779
812
|
*
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
*
|
|
813
|
+
* fn({ length: 1, 0: 42 }) // throws
|
|
814
|
+
* fn([]) === 1
|
|
815
|
+
* fn([3, 2, 1]) === 2
|
|
783
816
|
*
|
|
784
817
|
* @example
|
|
785
818
|
* It.isArray([It.isString({ containing: 'foobar' })])
|
|
786
|
-
*/
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
};
|
|
819
|
+
*/
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
const isArray = containing => matches(actual => {
|
|
823
|
+
if (!Array.isArray(actual)) {
|
|
824
|
+
return false;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
if (!containing) {
|
|
828
|
+
return true;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
return containing.every(x => actual.find(y => {
|
|
832
|
+
if (isMatcher(x)) {
|
|
833
|
+
return x.matches(y);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
return deepEquals(x).matches(y);
|
|
837
|
+
}) !== undefined);
|
|
838
|
+
}, {
|
|
839
|
+
toJSON: () => containing ? `array(${jestMatcherUtils.printExpected(containing)})` : 'array'
|
|
840
|
+
});
|
|
809
841
|
/**
|
|
810
842
|
* Matches anything and stores the received value.
|
|
811
843
|
*
|
|
@@ -818,208 +850,196 @@ var isArray = function (containing) {
|
|
|
818
850
|
* @example
|
|
819
851
|
* const fn = mock<(cb: (value: number) => number) => void>();
|
|
820
852
|
* const matcher = It.willCapture();
|
|
821
|
-
* when(fn(matcher)).thenReturn();
|
|
853
|
+
* when(() => fn(matcher)).thenReturn();
|
|
822
854
|
*
|
|
823
|
-
*
|
|
855
|
+
* fn(x => x + 1);
|
|
824
856
|
* matcher.value?.(3) === 4
|
|
825
|
-
*/
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
};
|
|
857
|
+
*/
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
const willCapture = name => {
|
|
861
|
+
let capturedValue;
|
|
862
|
+
const matcher = {
|
|
863
|
+
[MATCHER_SYMBOL]: true,
|
|
864
|
+
matches: actual => {
|
|
865
|
+
capturedValue = actual;
|
|
866
|
+
return true;
|
|
867
|
+
},
|
|
868
|
+
toJSON: () => name != null ? name : 'captures',
|
|
869
|
+
|
|
870
|
+
get value() {
|
|
871
|
+
return capturedValue;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
};
|
|
875
|
+
return matcher;
|
|
876
|
+
};
|
|
846
877
|
/**
|
|
847
878
|
* Contains argument matchers that can be used to ignore arguments in an
|
|
848
879
|
* expectation or to match complex arguments.
|
|
849
|
-
*/
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
880
|
+
*/
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
const It = {
|
|
884
|
+
matches,
|
|
885
|
+
deepEquals,
|
|
886
|
+
is,
|
|
887
|
+
isAny,
|
|
888
|
+
isObject,
|
|
889
|
+
isNumber,
|
|
890
|
+
isString,
|
|
891
|
+
isArray,
|
|
892
|
+
willCapture
|
|
860
893
|
};
|
|
861
894
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
};
|
|
865
|
-
|
|
895
|
+
const defaults = {
|
|
896
|
+
matcher: It.deepEquals
|
|
897
|
+
};
|
|
898
|
+
let currentDefaults = defaults;
|
|
866
899
|
/**
|
|
867
900
|
* Override strong-mock's defaults.
|
|
868
901
|
*
|
|
869
902
|
* @param newDefaults These will be applied to the library defaults. Multiple
|
|
870
903
|
* calls don't stack e.g. calling this with `{}` will clear any previously
|
|
871
904
|
* applied defaults.
|
|
872
|
-
*/
|
|
873
|
-
var setDefaults = function (newDefaults) {
|
|
874
|
-
currentDefaults = __assign(__assign({}, defaults), newDefaults);
|
|
875
|
-
};
|
|
905
|
+
*/
|
|
876
906
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
property: function (property) {
|
|
880
|
-
setActiveMock(stub);
|
|
881
|
-
pendingExpectation.start(repo);
|
|
882
|
-
// eslint-disable-next-line no-param-reassign
|
|
883
|
-
pendingExpectation.property = property;
|
|
884
|
-
return createProxy({
|
|
885
|
-
property: function (childProp) {
|
|
886
|
-
pendingExpectation.clear();
|
|
887
|
-
throw new NestedWhen(property, childProp);
|
|
888
|
-
},
|
|
889
|
-
apply: function (args) {
|
|
890
|
-
// eslint-disable-next-line no-param-reassign
|
|
891
|
-
pendingExpectation.args = args;
|
|
892
|
-
},
|
|
893
|
-
ownKeys: function () {
|
|
894
|
-
throw new Error('Spreading during an expectation is not supported.');
|
|
895
|
-
},
|
|
896
|
-
});
|
|
897
|
-
},
|
|
898
|
-
apply: function (args) {
|
|
899
|
-
setActiveMock(stub);
|
|
900
|
-
pendingExpectation.start(repo);
|
|
901
|
-
// eslint-disable-next-line no-param-reassign
|
|
902
|
-
pendingExpectation.property = ApplyProp;
|
|
903
|
-
// eslint-disable-next-line no-param-reassign
|
|
904
|
-
pendingExpectation.args = args;
|
|
905
|
-
},
|
|
906
|
-
ownKeys: function () {
|
|
907
|
-
throw new Error('Spreading during an expectation is not supported.');
|
|
908
|
-
},
|
|
909
|
-
});
|
|
910
|
-
return stub;
|
|
907
|
+
const setDefaults = newDefaults => {
|
|
908
|
+
currentDefaults = _extends({}, defaults, newDefaults);
|
|
911
909
|
};
|
|
912
910
|
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
911
|
+
const strongExpectationFactory = (property, args, returnValue) => new StrongExpectation(property, // Wrap every non-matcher in the default matcher.
|
|
912
|
+
args == null ? void 0 : args.map(arg => isMatcher(arg) ? arg : currentDefaults.matcher(arg)), returnValue);
|
|
913
|
+
|
|
914
|
+
let isRecording = false;
|
|
915
|
+
const setRecording = recording => {
|
|
916
|
+
isRecording = recording;
|
|
917
|
+
};
|
|
918
918
|
/**
|
|
919
919
|
* Create a type safe mock.
|
|
920
920
|
*
|
|
921
|
-
* Set expectations on the mock using `when
|
|
922
|
-
* instance from the mock using `instance`.
|
|
921
|
+
* @see {@link when} Set expectations on the mock using `when`.
|
|
923
922
|
*
|
|
924
923
|
* @example
|
|
925
924
|
* const fn = mock<() => number>();
|
|
926
925
|
*
|
|
927
|
-
* when(fn()).thenReturn(23);
|
|
926
|
+
* when(() => fn()).thenReturn(23);
|
|
928
927
|
*
|
|
929
|
-
*
|
|
930
|
-
*/
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
928
|
+
* fn() === 23;
|
|
929
|
+
*/
|
|
930
|
+
|
|
931
|
+
const mock = ({
|
|
932
|
+
repository = new StrongRepository(),
|
|
933
|
+
expectationFactory = strongExpectationFactory
|
|
934
|
+
} = {}) => {
|
|
935
|
+
const pendingExpectation = new RepoSideEffectPendingExpectation(expectationFactory);
|
|
936
|
+
const stub = createStub(repository, pendingExpectation, () => isRecording);
|
|
937
|
+
setMockState(stub, {
|
|
938
|
+
repository,
|
|
939
|
+
pendingExpectation
|
|
940
|
+
});
|
|
941
|
+
return stub;
|
|
937
942
|
};
|
|
938
943
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
944
|
+
const createInvocationCount = expectation => ({
|
|
945
|
+
between(min, max) {
|
|
946
|
+
expectation.setInvocationCount(min, max);
|
|
947
|
+
},
|
|
948
|
+
|
|
949
|
+
/* istanbul ignore next */
|
|
950
|
+
times(exact) {
|
|
951
|
+
expectation.setInvocationCount(exact, exact);
|
|
952
|
+
},
|
|
953
|
+
|
|
954
|
+
/* istanbul ignore next */
|
|
955
|
+
anyTimes() {
|
|
956
|
+
expectation.setInvocationCount(0, 0);
|
|
957
|
+
},
|
|
958
|
+
|
|
959
|
+
/* istanbul ignore next */
|
|
960
|
+
atLeast(min) {
|
|
961
|
+
expectation.setInvocationCount(min, Infinity);
|
|
962
|
+
},
|
|
963
|
+
|
|
964
|
+
/* istanbul ignore next */
|
|
965
|
+
atMost(max) {
|
|
966
|
+
expectation.setInvocationCount(0, max);
|
|
967
|
+
},
|
|
968
|
+
|
|
969
|
+
/* istanbul ignore next */
|
|
970
|
+
once() {
|
|
971
|
+
expectation.setInvocationCount(1, 1);
|
|
972
|
+
},
|
|
973
|
+
|
|
974
|
+
/* istanbul ignore next */
|
|
975
|
+
twice() {
|
|
976
|
+
expectation.setInvocationCount(2, 2);
|
|
977
|
+
}
|
|
978
|
+
/* eslint-enable no-param-reassign, no-multi-assign */
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
});
|
|
969
982
|
|
|
970
983
|
/**
|
|
971
984
|
* Set a return value for the currently pending expectation.
|
|
972
|
-
*/
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
985
|
+
*/
|
|
986
|
+
|
|
987
|
+
const finishPendingExpectation = (returnValue, pendingExpectation) => {
|
|
988
|
+
const finishedExpectation = pendingExpectation.finish(returnValue);
|
|
989
|
+
pendingExpectation.clear();
|
|
990
|
+
return createInvocationCount(finishedExpectation);
|
|
991
|
+
};
|
|
992
|
+
|
|
993
|
+
const getError = errorOrMessage => {
|
|
994
|
+
if (typeof errorOrMessage === 'string') {
|
|
995
|
+
return new Error(errorOrMessage);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
if (errorOrMessage instanceof Error) {
|
|
999
|
+
return errorOrMessage;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
return new Error();
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
const createReturns = pendingExpectation => {
|
|
1006
|
+
const nonPromiseStub = {
|
|
1007
|
+
// TODO: merge this with the promise version
|
|
1008
|
+
thenReturn:
|
|
1009
|
+
/* istanbul ignore next: because this is overwritten by the promise version */
|
|
1010
|
+
returnValue => finishPendingExpectation({
|
|
1011
|
+
value: returnValue,
|
|
1012
|
+
isError: false,
|
|
1013
|
+
isPromise: false
|
|
1014
|
+
}, pendingExpectation),
|
|
1015
|
+
thenThrow: errorOrMessage => finishPendingExpectation({
|
|
1016
|
+
value: getError(errorOrMessage),
|
|
1017
|
+
isError: true,
|
|
1018
|
+
isPromise: false
|
|
1019
|
+
}, pendingExpectation)
|
|
1020
|
+
};
|
|
1021
|
+
const promiseStub = {
|
|
1022
|
+
thenReturn: promise => finishPendingExpectation({
|
|
1023
|
+
value: promise,
|
|
1024
|
+
isError: false,
|
|
1025
|
+
// We're setting this to false because we can't distinguish between a
|
|
1026
|
+
// promise thenReturn and a normal thenReturn.
|
|
1027
|
+
isPromise: false
|
|
1028
|
+
}, pendingExpectation),
|
|
1029
|
+
thenResolve: promiseValue => finishPendingExpectation({
|
|
1030
|
+
value: promiseValue,
|
|
1031
|
+
isError: false,
|
|
1032
|
+
isPromise: true
|
|
1033
|
+
}, pendingExpectation),
|
|
1034
|
+
thenReject: errorOrMessage => finishPendingExpectation({
|
|
1035
|
+
value: getError(errorOrMessage),
|
|
1036
|
+
isError: true,
|
|
1037
|
+
isPromise: true
|
|
1038
|
+
}, pendingExpectation)
|
|
1039
|
+
}; // @ts-expect-error because the return type is a conditional, and we're merging
|
|
1040
|
+
// both branches here
|
|
1041
|
+
|
|
1042
|
+
return _extends({}, nonPromiseStub, promiseStub);
|
|
1023
1043
|
};
|
|
1024
1044
|
|
|
1025
1045
|
/**
|
|
@@ -1032,23 +1052,28 @@ var createReturns = function (pendingExpectation) {
|
|
|
1032
1052
|
* By default, the call is expected to only be made once. Use the invocation
|
|
1033
1053
|
* count helpers to expect a call multiple times.
|
|
1034
1054
|
*
|
|
1035
|
-
* @param
|
|
1055
|
+
* @param expectation A callback to set the expectation on your mock. The
|
|
1056
|
+
* callback must return the value from the mock to properly infer types.
|
|
1036
1057
|
*
|
|
1037
1058
|
* @example
|
|
1038
1059
|
* const fn = mock<() => void>();
|
|
1039
|
-
* when(fn()).thenReturn(undefined);
|
|
1060
|
+
* when(() => fn()).thenReturn(undefined);
|
|
1040
1061
|
*
|
|
1041
1062
|
* @example
|
|
1042
1063
|
* const fn = mock<() => number>();
|
|
1043
|
-
* when(fn()).thenReturn(42).atMost(3);
|
|
1064
|
+
* when(() => fn()).thenReturn(42).atMost(3);
|
|
1044
1065
|
*
|
|
1045
1066
|
* @example
|
|
1046
1067
|
* const fn = mock<(x: number) => Promise<number>();
|
|
1047
|
-
* when(fn(23)).thenResolve(42);
|
|
1048
|
-
*/
|
|
1049
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
|
|
1050
|
-
|
|
1051
|
-
|
|
1068
|
+
* when(() => fn(23)).thenResolve(42);
|
|
1069
|
+
*/
|
|
1070
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
|
|
1071
|
+
|
|
1072
|
+
const when = expectation => {
|
|
1073
|
+
setRecording(true);
|
|
1074
|
+
expectation();
|
|
1075
|
+
setRecording(false);
|
|
1076
|
+
return createReturns(getMockState(getActiveMock()).pendingExpectation);
|
|
1052
1077
|
};
|
|
1053
1078
|
|
|
1054
1079
|
/**
|
|
@@ -1057,37 +1082,41 @@ var when = function (expectedCall) {
|
|
|
1057
1082
|
* @example
|
|
1058
1083
|
* const fn = mock<() => number>();
|
|
1059
1084
|
*
|
|
1060
|
-
* when(fn()).thenReturn(23);
|
|
1085
|
+
* when(() => fn()).thenReturn(23);
|
|
1061
1086
|
*
|
|
1062
1087
|
* reset(fn);
|
|
1063
1088
|
*
|
|
1064
|
-
*
|
|
1065
|
-
*/
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1089
|
+
* fn(); // throws
|
|
1090
|
+
*/
|
|
1091
|
+
|
|
1092
|
+
const reset = mock => {
|
|
1093
|
+
getMockState(mock).repository.clear();
|
|
1094
|
+
};
|
|
1069
1095
|
/**
|
|
1070
1096
|
* Reset all existing mocks.
|
|
1071
1097
|
*
|
|
1072
1098
|
* @see reset
|
|
1073
|
-
*/
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1099
|
+
*/
|
|
1100
|
+
|
|
1101
|
+
const resetAll = () => {
|
|
1102
|
+
getAllMocks().forEach(([mock]) => {
|
|
1103
|
+
reset(mock);
|
|
1104
|
+
});
|
|
1079
1105
|
};
|
|
1080
1106
|
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1107
|
+
const verifyRepo = repository => {
|
|
1108
|
+
const unmetExpectations = repository.getUnmet();
|
|
1109
|
+
|
|
1110
|
+
if (unmetExpectations.length) {
|
|
1111
|
+
throw new UnmetExpectations(unmetExpectations);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
const callStats = repository.getCallStats();
|
|
1115
|
+
|
|
1116
|
+
if (callStats.unexpected.size) {
|
|
1117
|
+
throw new UnexpectedCalls(callStats.unexpected, unmetExpectations);
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1091
1120
|
/**
|
|
1092
1121
|
* Verify that all expectations on the given mock have been met.
|
|
1093
1122
|
*
|
|
@@ -1101,28 +1130,30 @@ var verifyRepo = function (repository) {
|
|
|
1101
1130
|
* @example
|
|
1102
1131
|
* const fn = mock<() => number>();
|
|
1103
1132
|
*
|
|
1104
|
-
* when(fn()).thenReturn(23);
|
|
1133
|
+
* when(() => fn()).thenReturn(23);
|
|
1105
1134
|
*
|
|
1106
1135
|
* verify(fn); // throws
|
|
1107
|
-
*/
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1136
|
+
*/
|
|
1137
|
+
|
|
1138
|
+
const verify = mock => {
|
|
1139
|
+
const {
|
|
1140
|
+
repository
|
|
1141
|
+
} = getMockState(mock);
|
|
1142
|
+
verifyRepo(repository);
|
|
1143
|
+
};
|
|
1112
1144
|
/**
|
|
1113
1145
|
* Verify all existing mocks.
|
|
1114
1146
|
*
|
|
1115
1147
|
* @see verify
|
|
1116
|
-
*/
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1148
|
+
*/
|
|
1149
|
+
|
|
1150
|
+
const verifyAll = () => {
|
|
1151
|
+
getAllMocks().forEach(([mock]) => {
|
|
1152
|
+
verify(mock);
|
|
1153
|
+
});
|
|
1122
1154
|
};
|
|
1123
1155
|
|
|
1124
1156
|
exports.It = It;
|
|
1125
|
-
exports.instance = instance;
|
|
1126
1157
|
exports.mock = mock;
|
|
1127
1158
|
exports.reset = reset;
|
|
1128
1159
|
exports.resetAll = resetAll;
|
|
@@ -1130,3 +1161,4 @@ exports.setDefaults = setDefaults;
|
|
|
1130
1161
|
exports.verify = verify;
|
|
1131
1162
|
exports.verifyAll = verifyAll;
|
|
1132
1163
|
exports.when = when;
|
|
1164
|
+
//# sourceMappingURL=index.js.map
|