strong-mock 9.0.0 → 9.1.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 +25 -25
- package/dist/index.cjs +1175 -0
- package/dist/index.d.cts +572 -0
- package/dist/index.d.ts +572 -14
- package/dist/index.js +638 -836
- package/package.json +44 -25
- package/dist/errors/api.d.ts +0 -13
- package/dist/errors/diff.d.ts +0 -4
- package/dist/errors/unexpected-access.d.ts +0 -5
- package/dist/errors/unexpected-call.d.ts +0 -14
- package/dist/errors/verify.d.ts +0 -8
- package/dist/expectation/expectation.d.ts +0 -27
- package/dist/expectation/repository/expectation-repository.d.ts +0 -90
- package/dist/expectation/repository/flexible-repository.d.ts +0 -38
- package/dist/expectation/repository/return-value.d.ts +0 -13
- package/dist/expectation/strong-expectation.d.ts +0 -30
- package/dist/index.js.map +0 -1
- package/dist/matchers/contains-object.d.ts +0 -28
- package/dist/matchers/deep-equals.d.ts +0 -16
- package/dist/matchers/is-any.d.ts +0 -11
- package/dist/matchers/is-array.d.ts +0 -22
- package/dist/matchers/is-number.d.ts +0 -12
- package/dist/matchers/is-plain-object.d.ts +0 -17
- package/dist/matchers/is-string.d.ts +0 -15
- package/dist/matchers/is.d.ts +0 -9
- package/dist/matchers/it.d.ts +0 -10
- package/dist/matchers/matcher.d.ts +0 -93
- package/dist/matchers/will-capture.d.ts +0 -21
- package/dist/mock/defaults.d.ts +0 -11
- package/dist/mock/map.d.ts +0 -16
- package/dist/mock/mock.d.ts +0 -29
- package/dist/mock/options.d.ts +0 -99
- package/dist/mock/stub.d.ts +0 -5
- package/dist/print.d.ts +0 -10
- package/dist/proxy.d.ts +0 -48
- package/dist/return/invocation-count.d.ts +0 -44
- package/dist/return/returns.d.ts +0 -61
- package/dist/verify/reset.d.ts +0 -20
- package/dist/verify/verify.d.ts +0 -27
- package/dist/when/expectation-builder.d.ts +0 -26
- package/dist/when/when.d.ts +0 -32
package/dist/index.js
CHANGED
|
@@ -1,69 +1,57 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
var
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
17
|
+
var __export = (target, all) => {
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
20
|
+
};
|
|
5
21
|
|
|
6
|
-
|
|
22
|
+
// src/errors/unexpected-access.ts
|
|
23
|
+
import { DIM_COLOR } from "jest-matcher-utils";
|
|
7
24
|
|
|
8
|
-
|
|
25
|
+
// src/print.ts
|
|
26
|
+
import { EXPECTED_COLOR, RECEIVED_COLOR, stringify } from "jest-matcher-utils";
|
|
27
|
+
import cloneDeepWith from "lodash/cloneDeepWith.js";
|
|
9
28
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*/
|
|
13
|
-
const ApplyProp = Symbol('apply');
|
|
29
|
+
// src/expectation/expectation.ts
|
|
30
|
+
var ApplyProp = Symbol("apply");
|
|
14
31
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* Used to test if an expectation is an argument is a custom matcher.
|
|
18
|
-
*/
|
|
32
|
+
// src/matchers/matcher.ts
|
|
33
|
+
var MATCHER_SYMBOL = Symbol("matcher");
|
|
19
34
|
function isMatcher(f) {
|
|
20
35
|
return !!(f && f[MATCHER_SYMBOL]);
|
|
21
36
|
}
|
|
22
|
-
|
|
37
|
+
var getMatcherDiffs = (matchers, args) => {
|
|
23
38
|
const matcherDiffs = matchers.map((matcher, i) => matcher.getDiff(args[i]));
|
|
24
|
-
const actual = matcherDiffs.map(d => d.actual);
|
|
25
|
-
const expected = matcherDiffs.map(d => d.expected);
|
|
26
|
-
return {
|
|
27
|
-
actual,
|
|
28
|
-
expected
|
|
29
|
-
};
|
|
39
|
+
const actual = matcherDiffs.map((d) => d.actual);
|
|
40
|
+
const expected = matcherDiffs.map((d) => d.expected);
|
|
41
|
+
return { actual, expected };
|
|
30
42
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* @param options
|
|
36
|
-
* @param options.toString An optional function that should return a string that will be
|
|
37
|
-
* used when the matcher needs to be printed in an error message. By default,
|
|
38
|
-
* it stringifies `predicate`.
|
|
39
|
-
* @param options.getDiff An optional function that will be called when printing the
|
|
40
|
-
* diff for a failed expectation. It will only be called if there's a mismatch
|
|
41
|
-
* between the expected and received values i.e. `predicate(actual)` fails.
|
|
42
|
-
* By default, the `toString` method will be used to format the expected value,
|
|
43
|
-
* while the received value will be returned as-is.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* // Create a matcher for positive numbers.
|
|
47
|
-
* const fn = mock<(x: number) => number>();
|
|
48
|
-
* when(() => fn(It.matches(x => x >= 0))).thenReturn(42);
|
|
49
|
-
*
|
|
50
|
-
* fn(2) === 42
|
|
51
|
-
* fn(-1) // throws
|
|
52
|
-
*/
|
|
53
|
-
const matches = (predicate, options) => {
|
|
54
|
-
var _options$toString, _options$getDiff;
|
|
55
|
-
// We can't use destructuring with default values because `options` is optional,
|
|
56
|
-
// so it needs a default value of `{}`, which will come with a native `toString`.
|
|
57
|
-
const toString = (_options$toString = options == null ? void 0 : options.toString) != null ? _options$toString : () => `Matcher(${predicate.toString()})`;
|
|
58
|
-
const getDiff = (_options$getDiff = options == null ? void 0 : options.getDiff) != null ? _options$getDiff : actual => ({
|
|
43
|
+
var matches = (predicate, options) => {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
const toString = (_a = options == null ? void 0 : options.toString) != null ? _a : () => `Matcher(${predicate.toString()})`;
|
|
46
|
+
const getDiff = (_b = options == null ? void 0 : options.getDiff) != null ? _b : (actual) => ({
|
|
59
47
|
actual,
|
|
60
48
|
expected: toString()
|
|
61
49
|
});
|
|
62
50
|
const matcher = {
|
|
63
51
|
[MATCHER_SYMBOL]: true,
|
|
64
|
-
matches: actual => predicate(actual),
|
|
52
|
+
matches: (actual) => predicate(actual),
|
|
65
53
|
toString,
|
|
66
|
-
getDiff: actual => {
|
|
54
|
+
getDiff: (actual) => {
|
|
67
55
|
if (predicate(actual)) {
|
|
68
56
|
return {
|
|
69
57
|
actual,
|
|
@@ -76,217 +64,191 @@ const matches = (predicate, options) => {
|
|
|
76
64
|
return matcher;
|
|
77
65
|
};
|
|
78
66
|
|
|
79
|
-
|
|
67
|
+
// src/print.ts
|
|
68
|
+
var printProperty = (property) => {
|
|
80
69
|
if (property === ApplyProp) {
|
|
81
|
-
return
|
|
70
|
+
return "";
|
|
82
71
|
}
|
|
83
|
-
if (typeof property ===
|
|
72
|
+
if (typeof property === "symbol") {
|
|
84
73
|
return `[${property.toString()}]`;
|
|
85
74
|
}
|
|
86
75
|
return `.${property}`;
|
|
87
76
|
};
|
|
88
|
-
|
|
89
|
-
// Call toString on matchers directly to avoid wrapping strings returned by them in quotes.
|
|
77
|
+
var printValue = (arg) => {
|
|
90
78
|
if (isMatcher(arg)) {
|
|
91
79
|
return arg.toString();
|
|
92
80
|
}
|
|
93
|
-
return
|
|
81
|
+
return stringify(arg);
|
|
94
82
|
};
|
|
95
|
-
|
|
96
|
-
|
|
83
|
+
var deepPrint = (value) => cloneDeepWith(value, (value2) => {
|
|
84
|
+
if (isMatcher(value2)) {
|
|
85
|
+
return value2.toString();
|
|
86
|
+
}
|
|
87
|
+
return void 0;
|
|
88
|
+
});
|
|
89
|
+
var printArgs = (args) => args.map((arg) => printValue(arg)).join(", ");
|
|
90
|
+
var printCall = (property, args) => {
|
|
97
91
|
const prettyProperty = printProperty(property);
|
|
98
92
|
if (args) {
|
|
99
93
|
const prettyArgs = printArgs(args);
|
|
100
|
-
return `mock${
|
|
94
|
+
return `mock${RECEIVED_COLOR(`${prettyProperty}(${prettyArgs})`)}`;
|
|
101
95
|
}
|
|
102
|
-
return `mock${
|
|
96
|
+
return `mock${RECEIVED_COLOR(`${prettyProperty}`)}`;
|
|
103
97
|
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
isPromise,
|
|
107
|
-
value
|
|
108
|
-
}, min, max) => {
|
|
109
|
-
let thenPrefix = '';
|
|
98
|
+
var printReturns = ({ isError, isPromise, value }, min, max) => {
|
|
99
|
+
let thenPrefix = "";
|
|
110
100
|
if (isPromise) {
|
|
111
101
|
if (isError) {
|
|
112
|
-
thenPrefix +=
|
|
102
|
+
thenPrefix += "thenReject";
|
|
113
103
|
} else {
|
|
114
|
-
thenPrefix +=
|
|
104
|
+
thenPrefix += "thenResolve";
|
|
115
105
|
}
|
|
116
106
|
} else if (isError) {
|
|
117
|
-
thenPrefix +=
|
|
107
|
+
thenPrefix += "thenThrow";
|
|
118
108
|
} else {
|
|
119
|
-
thenPrefix +=
|
|
109
|
+
thenPrefix += "thenReturn";
|
|
120
110
|
}
|
|
121
|
-
return `.${thenPrefix}(${
|
|
111
|
+
return `.${thenPrefix}(${RECEIVED_COLOR(
|
|
112
|
+
printValue(value)
|
|
113
|
+
)}).between(${min}, ${max})`;
|
|
122
114
|
};
|
|
123
|
-
|
|
115
|
+
var printWhen = (property, args) => {
|
|
124
116
|
const prettyProperty = printProperty(property);
|
|
125
117
|
if (args) {
|
|
126
|
-
return `when(() => mock${
|
|
118
|
+
return `when(() => mock${EXPECTED_COLOR(
|
|
119
|
+
`${prettyProperty}(${printArgs(args)})`
|
|
120
|
+
)})`;
|
|
127
121
|
}
|
|
128
|
-
return `when(() => mock${
|
|
122
|
+
return `when(() => mock${EXPECTED_COLOR(`${printProperty(property)}`)})`;
|
|
129
123
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
- ${expectations.map(e => e.toString()).join(
|
|
124
|
+
var printExpectation = (property, args, returnValue, min, max) => `${printWhen(property, args)}${printReturns(returnValue, min, max)}`;
|
|
125
|
+
var printRemainingExpectations = (expectations) => expectations.length ? `Remaining unmet expectations:
|
|
126
|
+
- ${expectations.map((e) => e.toString()).join("\n - ")}` : "There are no remaining unmet expectations.";
|
|
133
127
|
|
|
134
|
-
|
|
128
|
+
// src/errors/unexpected-access.ts
|
|
129
|
+
var UnexpectedAccess = class extends Error {
|
|
135
130
|
constructor(property, expectations) {
|
|
136
|
-
super(
|
|
131
|
+
super(
|
|
132
|
+
DIM_COLOR(`Didn't expect ${printCall(property)} to be accessed.
|
|
137
133
|
|
|
138
|
-
If you expect this property to be accessed then
|
|
139
|
-
set an expectation for it.
|
|
134
|
+
If you expect this property to be accessed then you should
|
|
135
|
+
set an expectation for it with when().
|
|
140
136
|
|
|
141
|
-
${printRemainingExpectations(expectations)}`)
|
|
137
|
+
${printRemainingExpectations(expectations)}`)
|
|
138
|
+
);
|
|
142
139
|
}
|
|
143
|
-
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// src/errors/unexpected-call.ts
|
|
143
|
+
import { DIM_COLOR as DIM_COLOR2 } from "jest-matcher-utils";
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
// src/errors/diff.ts
|
|
146
|
+
import { diff as printDiff } from "jest-diff";
|
|
147
|
+
import { EXPECTED_COLOR as EXPECTED_COLOR2, RECEIVED_COLOR as RECEIVED_COLOR2 } from "jest-matcher-utils";
|
|
148
|
+
var noColor = (s) => s;
|
|
149
|
+
var printArgsDiff = (expected, actual) => {
|
|
150
|
+
const diff = printDiff(expected, actual, {
|
|
151
|
+
omitAnnotationLines: true,
|
|
152
|
+
aColor: noColor,
|
|
153
|
+
bColor: noColor,
|
|
154
|
+
changeColor: noColor,
|
|
155
|
+
commonColor: noColor,
|
|
156
|
+
patchColor: noColor
|
|
148
157
|
});
|
|
149
|
-
/* istanbul ignore next this is not expected in practice */
|
|
150
158
|
if (!diff) {
|
|
151
|
-
return
|
|
159
|
+
return "";
|
|
152
160
|
}
|
|
153
|
-
const
|
|
161
|
+
const diffLines = diff.split("\n");
|
|
154
162
|
let relevantDiffLines;
|
|
155
|
-
// Strip Array [ ... ] surroundings.
|
|
156
163
|
if (!expected.length) {
|
|
157
|
-
|
|
158
|
-
// + Array [
|
|
159
|
-
// ...
|
|
160
|
-
// ]
|
|
161
|
-
relevantDiffLines = ansilessDiffLines.slice(2, -1);
|
|
164
|
+
relevantDiffLines = diffLines.slice(2, -1);
|
|
162
165
|
} else if (!actual.length) {
|
|
163
|
-
|
|
164
|
-
// ...
|
|
165
|
-
// ]
|
|
166
|
-
// + Array []
|
|
167
|
-
relevantDiffLines = ansilessDiffLines.slice(1, -2);
|
|
166
|
+
relevantDiffLines = diffLines.slice(1, -2);
|
|
168
167
|
} else {
|
|
169
|
-
|
|
170
|
-
// ...
|
|
171
|
-
// ]
|
|
172
|
-
relevantDiffLines = ansilessDiffLines.slice(1, -1);
|
|
168
|
+
relevantDiffLines = diffLines.slice(1, -1);
|
|
173
169
|
}
|
|
174
|
-
// Strip the trailing comma.
|
|
175
170
|
const lastLine = relevantDiffLines[relevantDiffLines.length - 1].slice(0, -1);
|
|
176
|
-
const coloredDiffLines = [...relevantDiffLines.slice(0, -1), lastLine].map(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
171
|
+
const coloredDiffLines = [...relevantDiffLines.slice(0, -1), lastLine].map(
|
|
172
|
+
(line) => {
|
|
173
|
+
const first = line.charAt(0);
|
|
174
|
+
switch (first) {
|
|
175
|
+
case "-":
|
|
176
|
+
return EXPECTED_COLOR2(line);
|
|
177
|
+
case "+":
|
|
178
|
+
return RECEIVED_COLOR2(line);
|
|
179
|
+
default:
|
|
180
|
+
return line;
|
|
181
|
+
}
|
|
185
182
|
}
|
|
186
|
-
|
|
187
|
-
return coloredDiffLines.join(
|
|
183
|
+
);
|
|
184
|
+
return coloredDiffLines.join("\n");
|
|
188
185
|
};
|
|
189
|
-
|
|
190
|
-
var
|
|
191
|
-
if (!((
|
|
192
|
-
return
|
|
186
|
+
var printExpectationDiff = (e, args) => {
|
|
187
|
+
var _a;
|
|
188
|
+
if (!((_a = e.args) == null ? void 0 : _a.length)) {
|
|
189
|
+
return "";
|
|
193
190
|
}
|
|
194
|
-
const {
|
|
195
|
-
actual,
|
|
196
|
-
expected
|
|
197
|
-
} = getMatcherDiffs(e.args, args);
|
|
191
|
+
const { actual, expected } = getMatcherDiffs(e.args, args);
|
|
198
192
|
return printArgsDiff(expected, actual);
|
|
199
193
|
};
|
|
200
|
-
|
|
194
|
+
var printDiffForAllExpectations = (expectations, actual) => expectations.map((e) => {
|
|
201
195
|
const diff = printExpectationDiff(e, actual);
|
|
202
196
|
if (diff) {
|
|
203
197
|
return `${e.toString()}
|
|
204
|
-
${
|
|
205
|
-
${
|
|
198
|
+
${EXPECTED_COLOR2("- Expected")}
|
|
199
|
+
${RECEIVED_COLOR2("+ Received")}
|
|
206
200
|
|
|
207
201
|
${diff}`;
|
|
208
202
|
}
|
|
209
|
-
return
|
|
210
|
-
}).filter(x => x).join(
|
|
203
|
+
return void 0;
|
|
204
|
+
}).filter((x) => x).join("\n\n");
|
|
211
205
|
|
|
212
|
-
|
|
206
|
+
// src/errors/unexpected-call.ts
|
|
207
|
+
var UnexpectedCall = class extends Error {
|
|
213
208
|
constructor(property, args, expectations) {
|
|
209
|
+
var _a;
|
|
214
210
|
const header = `Didn't expect ${printCall(property, args)} to be called.`;
|
|
215
|
-
const propertyExpectations = expectations.filter(
|
|
211
|
+
const propertyExpectations = expectations.filter(
|
|
212
|
+
(e) => e.property === property
|
|
213
|
+
);
|
|
216
214
|
if (propertyExpectations.length) {
|
|
217
|
-
|
|
218
|
-
|
|
215
|
+
super(
|
|
216
|
+
DIM_COLOR2(`${header}
|
|
219
217
|
|
|
220
218
|
Remaining expectations:
|
|
221
|
-
${printDiffForAllExpectations(propertyExpectations, args)}`)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
219
|
+
${printDiffForAllExpectations(propertyExpectations, args)}`)
|
|
220
|
+
);
|
|
221
|
+
if (propertyExpectations.length === 1 && ((_a = propertyExpectations[0].args) == null ? void 0 : _a.length)) {
|
|
222
|
+
const { actual, expected } = getMatcherDiffs(
|
|
223
|
+
propertyExpectations[0].args,
|
|
224
|
+
args
|
|
225
|
+
);
|
|
226
|
+
this.actual = actual;
|
|
227
|
+
this.expected = expected;
|
|
230
228
|
this.matcherResult = {
|
|
231
229
|
actual,
|
|
232
230
|
expected
|
|
233
231
|
};
|
|
234
232
|
}
|
|
235
233
|
} else {
|
|
236
|
-
super(
|
|
234
|
+
super(
|
|
235
|
+
DIM_COLOR2(`${header}
|
|
237
236
|
|
|
238
|
-
No remaining expectations.`)
|
|
239
|
-
|
|
237
|
+
No remaining expectations.`)
|
|
238
|
+
);
|
|
240
239
|
}
|
|
241
240
|
}
|
|
242
|
-
}
|
|
241
|
+
};
|
|
243
242
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
* // Will throw "Didn't expect foo to be accessed".
|
|
251
|
-
* const { foo } = service;
|
|
252
|
-
*
|
|
253
|
-
* // Will throw "Didn't expect foo to be accessed",
|
|
254
|
-
* // without printing the arguments.
|
|
255
|
-
* foo(42);
|
|
256
|
-
*/
|
|
257
|
-
UnexpectedProperty[UnexpectedProperty["THROW"] = 0] = "THROW";
|
|
258
|
-
/**
|
|
259
|
-
* Return a function that will throw if called. This can be useful if your
|
|
260
|
-
* code destructures a function but never calls it.
|
|
261
|
-
*
|
|
262
|
-
* It will also improve error messages for unexpected calls because arguments
|
|
263
|
-
* will be captured instead of throwing immediately on the property access.
|
|
264
|
-
*
|
|
265
|
-
* The function will be returned even if the property is not supposed to be a
|
|
266
|
-
* function. This could cause weird behavior at runtime, when your code expects
|
|
267
|
-
* e.g. a number and gets a function instead.
|
|
268
|
-
*
|
|
269
|
-
* @example
|
|
270
|
-
* // This will NOT throw.
|
|
271
|
-
* const { foo } = service;
|
|
272
|
-
*
|
|
273
|
-
* // This will NOT throw, and might produce unexpected results.
|
|
274
|
-
* foo > 0
|
|
275
|
-
*
|
|
276
|
-
* // Will throw "Didn't expect foo(42) to be called".
|
|
277
|
-
* foo(42);
|
|
278
|
-
*/
|
|
279
|
-
UnexpectedProperty[UnexpectedProperty["CALL_THROW"] = 1] = "CALL_THROW";
|
|
280
|
-
})(exports.UnexpectedProperty || (exports.UnexpectedProperty = {}));
|
|
243
|
+
// src/mock/options.ts
|
|
244
|
+
var UnexpectedProperty = /* @__PURE__ */ ((UnexpectedProperty2) => {
|
|
245
|
+
UnexpectedProperty2[UnexpectedProperty2["THROW"] = 0] = "THROW";
|
|
246
|
+
UnexpectedProperty2[UnexpectedProperty2["CALL_THROW"] = 1] = "CALL_THROW";
|
|
247
|
+
return UnexpectedProperty2;
|
|
248
|
+
})(UnexpectedProperty || {});
|
|
281
249
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
*
|
|
285
|
-
* If the value is an error then throw it.
|
|
286
|
-
*
|
|
287
|
-
* If the value is a promise then resolve/reject it.
|
|
288
|
-
*/
|
|
289
|
-
const unboxReturnValue = ({
|
|
250
|
+
// src/expectation/repository/return-value.ts
|
|
251
|
+
var unboxReturnValue = ({
|
|
290
252
|
isError,
|
|
291
253
|
isPromise,
|
|
292
254
|
value
|
|
@@ -309,32 +271,29 @@ const unboxReturnValue = ({
|
|
|
309
271
|
return value;
|
|
310
272
|
};
|
|
311
273
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
this.
|
|
319
|
-
this.
|
|
320
|
-
this.expectedCallStats = new Map();
|
|
321
|
-
this.unexpectedCallStats = new Map();
|
|
322
|
-
this.apply = args => this.get(ApplyProp)(...args);
|
|
274
|
+
// src/expectation/repository/flexible-repository.ts
|
|
275
|
+
var FlexibleRepository = class {
|
|
276
|
+
constructor(unexpectedProperty = 0 /* THROW */) {
|
|
277
|
+
this.unexpectedProperty = unexpectedProperty;
|
|
278
|
+
this.expectations = /* @__PURE__ */ new Map();
|
|
279
|
+
this.expectedCallStats = /* @__PURE__ */ new Map();
|
|
280
|
+
this.unexpectedCallStats = /* @__PURE__ */ new Map();
|
|
281
|
+
this.apply = (args) => this.get(ApplyProp)(...args);
|
|
323
282
|
this.handlePropertyWithMatchingExpectations = (property, expectations) => {
|
|
324
|
-
// Avoid recording call stats for function calls, since the property is an
|
|
325
|
-
// internal detail.
|
|
326
283
|
if (property !== ApplyProp) {
|
|
327
|
-
|
|
328
|
-
// function that will not match the given args.
|
|
329
|
-
this.recordExpected(property, undefined);
|
|
284
|
+
this.recordExpected(property, void 0);
|
|
330
285
|
}
|
|
331
|
-
const propertyExpectation = expectations.find(
|
|
286
|
+
const propertyExpectation = expectations.find(
|
|
287
|
+
(e) => e.expectation.matches(void 0)
|
|
288
|
+
);
|
|
332
289
|
if (propertyExpectation) {
|
|
333
290
|
this.countAndConsume(propertyExpectation);
|
|
334
291
|
return unboxReturnValue(propertyExpectation.expectation.returnValue);
|
|
335
292
|
}
|
|
336
293
|
return (...args) => {
|
|
337
|
-
const callExpectation = expectations.find(
|
|
294
|
+
const callExpectation = expectations.find(
|
|
295
|
+
(e) => e.expectation.matches(args)
|
|
296
|
+
);
|
|
338
297
|
if (callExpectation) {
|
|
339
298
|
this.recordExpected(property, args);
|
|
340
299
|
this.countAndConsume(callExpectation);
|
|
@@ -343,23 +302,23 @@ class FlexibleRepository {
|
|
|
343
302
|
return this.getValueForUnexpectedCall(property, args);
|
|
344
303
|
};
|
|
345
304
|
};
|
|
346
|
-
this.handlePropertyWithNoExpectations = property => {
|
|
305
|
+
this.handlePropertyWithNoExpectations = (property) => {
|
|
347
306
|
switch (property) {
|
|
348
|
-
case
|
|
349
|
-
return () =>
|
|
350
|
-
case
|
|
307
|
+
case "toString":
|
|
308
|
+
return () => "mock";
|
|
309
|
+
case "@@toStringTag":
|
|
351
310
|
case Symbol.toStringTag:
|
|
352
|
-
case
|
|
353
|
-
return
|
|
311
|
+
case "name":
|
|
312
|
+
return "mock";
|
|
354
313
|
// Promise.resolve() tries to see if it's a "thenable".
|
|
355
314
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#thenables
|
|
356
|
-
case
|
|
357
|
-
return
|
|
315
|
+
case "then":
|
|
316
|
+
return void 0;
|
|
358
317
|
// pretty-format
|
|
359
|
-
case
|
|
360
|
-
case
|
|
361
|
-
case
|
|
362
|
-
case
|
|
318
|
+
case "$$typeof":
|
|
319
|
+
case "constructor":
|
|
320
|
+
case "@@__IMMUTABLE_ITERABLE__@@":
|
|
321
|
+
case "@@__IMMUTABLE_RECORD__@@":
|
|
363
322
|
return null;
|
|
364
323
|
case MATCHER_SYMBOL:
|
|
365
324
|
return false;
|
|
@@ -369,17 +328,17 @@ class FlexibleRepository {
|
|
|
369
328
|
return this.getValueForUnexpectedAccess(property);
|
|
370
329
|
}
|
|
371
330
|
};
|
|
372
|
-
this.unexpectedProperty = unexpectedProperty;
|
|
373
331
|
}
|
|
374
332
|
add(expectation) {
|
|
375
|
-
const {
|
|
376
|
-
property
|
|
377
|
-
} = expectation;
|
|
333
|
+
const { property } = expectation;
|
|
378
334
|
const expectations = this.expectations.get(property) || [];
|
|
379
|
-
this.expectations.set(property, [
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
335
|
+
this.expectations.set(property, [
|
|
336
|
+
...expectations,
|
|
337
|
+
{
|
|
338
|
+
expectation,
|
|
339
|
+
matchCount: 0
|
|
340
|
+
}
|
|
341
|
+
]);
|
|
383
342
|
}
|
|
384
343
|
clear() {
|
|
385
344
|
this.expectations.clear();
|
|
@@ -391,7 +350,10 @@ class FlexibleRepository {
|
|
|
391
350
|
get(property) {
|
|
392
351
|
const expectations = this.expectations.get(property);
|
|
393
352
|
if (expectations && expectations.length) {
|
|
394
|
-
return this.handlePropertyWithMatchingExpectations(
|
|
353
|
+
return this.handlePropertyWithMatchingExpectations(
|
|
354
|
+
property,
|
|
355
|
+
expectations
|
|
356
|
+
);
|
|
395
357
|
}
|
|
396
358
|
return this.handlePropertyWithNoExpectations(property);
|
|
397
359
|
}
|
|
@@ -405,33 +367,32 @@ class FlexibleRepository {
|
|
|
405
367
|
};
|
|
406
368
|
}
|
|
407
369
|
getUnmet() {
|
|
408
|
-
return [].concat(
|
|
370
|
+
return [].concat(
|
|
371
|
+
...Array.from(this.expectations.values()).map(
|
|
372
|
+
(expectations) => expectations.filter((e) => e.expectation.min > e.matchCount).map((e) => e.expectation)
|
|
373
|
+
)
|
|
374
|
+
);
|
|
409
375
|
}
|
|
410
376
|
recordExpected(property, args) {
|
|
411
377
|
const calls = this.expectedCallStats.get(property) || [];
|
|
412
|
-
this.expectedCallStats.set(property, [...calls, {
|
|
413
|
-
arguments: args
|
|
414
|
-
}]);
|
|
378
|
+
this.expectedCallStats.set(property, [...calls, { arguments: args }]);
|
|
415
379
|
}
|
|
416
380
|
recordUnexpected(property, args) {
|
|
417
381
|
const calls = this.unexpectedCallStats.get(property) || [];
|
|
418
|
-
this.unexpectedCallStats.set(property, [...calls, {
|
|
419
|
-
arguments: args
|
|
420
|
-
}]);
|
|
382
|
+
this.unexpectedCallStats.set(property, [...calls, { arguments: args }]);
|
|
421
383
|
}
|
|
422
384
|
countAndConsume(expectation) {
|
|
423
|
-
// eslint-disable-next-line no-param-reassign
|
|
424
385
|
expectation.matchCount++;
|
|
425
386
|
this.consumeExpectation(expectation);
|
|
426
387
|
}
|
|
427
388
|
consumeExpectation(expectation) {
|
|
428
|
-
const {
|
|
429
|
-
property,
|
|
430
|
-
max
|
|
431
|
-
} = expectation.expectation;
|
|
389
|
+
const { property, max } = expectation.expectation;
|
|
432
390
|
const expectations = this.expectations.get(property);
|
|
433
391
|
if (expectation.matchCount === max) {
|
|
434
|
-
this.expectations.set(
|
|
392
|
+
this.expectations.set(
|
|
393
|
+
property,
|
|
394
|
+
expectations.filter((e) => e !== expectation)
|
|
395
|
+
);
|
|
435
396
|
}
|
|
436
397
|
}
|
|
437
398
|
getValueForUnexpectedCall(property, args) {
|
|
@@ -439,8 +400,8 @@ class FlexibleRepository {
|
|
|
439
400
|
throw new UnexpectedCall(property, args, this.getUnmet());
|
|
440
401
|
}
|
|
441
402
|
getValueForUnexpectedAccess(property) {
|
|
442
|
-
if (this.unexpectedProperty ===
|
|
443
|
-
this.recordUnexpected(property,
|
|
403
|
+
if (this.unexpectedProperty === 0 /* THROW */) {
|
|
404
|
+
this.recordUnexpected(property, void 0);
|
|
444
405
|
throw new UnexpectedAccess(property, this.getUnmet());
|
|
445
406
|
}
|
|
446
407
|
return (...args) => {
|
|
@@ -448,32 +409,18 @@ class FlexibleRepository {
|
|
|
448
409
|
throw new UnexpectedCall(property, args, this.getUnmet());
|
|
449
410
|
};
|
|
450
411
|
}
|
|
451
|
-
}
|
|
412
|
+
};
|
|
452
413
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
* compiler will check that those parameters are optional.
|
|
456
|
-
*
|
|
457
|
-
* @example
|
|
458
|
-
* new StrongExpectation(
|
|
459
|
-
* 'bar',
|
|
460
|
-
* deepEquals([1, 2, 3]),
|
|
461
|
-
* 23
|
|
462
|
-
* ).matches('bar', [1, 2, 3]) === true;
|
|
463
|
-
*/
|
|
464
|
-
class StrongExpectation {
|
|
414
|
+
// src/expectation/strong-expectation.ts
|
|
415
|
+
var StrongExpectation = class {
|
|
465
416
|
constructor(property, args, returnValue, exactParams = false) {
|
|
466
|
-
this.property = void 0;
|
|
467
|
-
this.args = void 0;
|
|
468
|
-
this.returnValue = void 0;
|
|
469
|
-
this.exactParams = void 0;
|
|
470
|
-
this.matched = 0;
|
|
471
|
-
this.min = 1;
|
|
472
|
-
this.max = 1;
|
|
473
417
|
this.property = property;
|
|
474
418
|
this.args = args;
|
|
475
419
|
this.returnValue = returnValue;
|
|
476
420
|
this.exactParams = exactParams;
|
|
421
|
+
this.matched = 0;
|
|
422
|
+
this.min = 1;
|
|
423
|
+
this.max = 1;
|
|
477
424
|
}
|
|
478
425
|
setInvocationCount(min, max = 1) {
|
|
479
426
|
this.min = min;
|
|
@@ -490,7 +437,7 @@ class StrongExpectation {
|
|
|
490
437
|
return this.matched < this.min;
|
|
491
438
|
}
|
|
492
439
|
matchesArgs(received) {
|
|
493
|
-
if (this.args ===
|
|
440
|
+
if (this.args === void 0) {
|
|
494
441
|
return !received;
|
|
495
442
|
}
|
|
496
443
|
if (!received) {
|
|
@@ -504,35 +451,42 @@ class StrongExpectation {
|
|
|
504
451
|
return this.args.every((arg, i) => arg.matches(received[i]));
|
|
505
452
|
}
|
|
506
453
|
toString() {
|
|
507
|
-
return printExpectation(
|
|
454
|
+
return printExpectation(
|
|
455
|
+
this.property,
|
|
456
|
+
this.args,
|
|
457
|
+
this.returnValue,
|
|
458
|
+
this.min,
|
|
459
|
+
this.max
|
|
460
|
+
);
|
|
508
461
|
}
|
|
509
|
-
}
|
|
462
|
+
};
|
|
510
463
|
|
|
511
|
-
|
|
464
|
+
// src/errors/api.ts
|
|
465
|
+
var UnfinishedExpectation = class extends Error {
|
|
512
466
|
constructor(property, args) {
|
|
513
467
|
super(`There is an unfinished pending expectation:
|
|
514
468
|
|
|
515
469
|
${printWhen(property, args)}
|
|
516
470
|
|
|
517
|
-
|
|
518
|
-
is undefined.`);
|
|
471
|
+
You should finish it by setting a return value with e.g. thenReturns(),
|
|
472
|
+
even if that value is undefined.`);
|
|
519
473
|
}
|
|
520
|
-
}
|
|
521
|
-
|
|
474
|
+
};
|
|
475
|
+
var MissingWhen = class extends Error {
|
|
522
476
|
constructor() {
|
|
523
477
|
super(`You tried setting a return value without an expectation.
|
|
524
478
|
|
|
525
479
|
Every call to set a return value must be preceded by an expectation.`);
|
|
526
480
|
}
|
|
527
|
-
}
|
|
528
|
-
|
|
481
|
+
};
|
|
482
|
+
var NotAMock = class extends Error {
|
|
529
483
|
constructor() {
|
|
530
484
|
super(`We couldn't find the mock.
|
|
531
485
|
|
|
532
486
|
Make sure you're passing in an actual mock.`);
|
|
533
487
|
}
|
|
534
|
-
}
|
|
535
|
-
|
|
488
|
+
};
|
|
489
|
+
var NestedWhen = class extends Error {
|
|
536
490
|
constructor(parentProp, childProp) {
|
|
537
491
|
const snippet = `
|
|
538
492
|
const parentMock = mock<T1>();
|
|
@@ -541,21 +495,19 @@ const childMock = mock<T2>();
|
|
|
541
495
|
when(() => childMock${printProperty(childProp)}).thenReturn(...);
|
|
542
496
|
when(() => parentMock${printProperty(parentProp)}).thenReturn(childMock)
|
|
543
497
|
`;
|
|
544
|
-
super(
|
|
498
|
+
super(
|
|
499
|
+
`Setting an expectation on a nested property is not supported.
|
|
545
500
|
|
|
546
501
|
You can return an object directly when the first property is accessed,
|
|
547
502
|
or you can even return a separate mock:
|
|
548
|
-
${snippet}`
|
|
503
|
+
${snippet}`
|
|
504
|
+
);
|
|
549
505
|
}
|
|
550
|
-
}
|
|
506
|
+
};
|
|
551
507
|
|
|
552
|
-
|
|
508
|
+
// src/when/expectation-builder.ts
|
|
509
|
+
var ExpectationBuilderWithFactory = class {
|
|
553
510
|
constructor(createExpectation, concreteMatcher, exactParams) {
|
|
554
|
-
this.createExpectation = void 0;
|
|
555
|
-
this.concreteMatcher = void 0;
|
|
556
|
-
this.exactParams = void 0;
|
|
557
|
-
this.args = void 0;
|
|
558
|
-
this.property = void 0;
|
|
559
511
|
this.createExpectation = createExpectation;
|
|
560
512
|
this.concreteMatcher = concreteMatcher;
|
|
561
513
|
this.exactParams = exactParams;
|
|
@@ -573,211 +525,208 @@ class ExpectationBuilderWithFactory {
|
|
|
573
525
|
if (!this.property) {
|
|
574
526
|
throw new MissingWhen();
|
|
575
527
|
}
|
|
576
|
-
const expectation = this.createExpectation(
|
|
577
|
-
|
|
578
|
-
|
|
528
|
+
const expectation = this.createExpectation(
|
|
529
|
+
this.property,
|
|
530
|
+
this.args,
|
|
531
|
+
returnValue,
|
|
532
|
+
this.concreteMatcher,
|
|
533
|
+
this.exactParams
|
|
534
|
+
);
|
|
535
|
+
this.property = void 0;
|
|
536
|
+
this.args = void 0;
|
|
579
537
|
return expectation;
|
|
580
538
|
}
|
|
581
|
-
}
|
|
539
|
+
};
|
|
582
540
|
|
|
583
|
-
|
|
541
|
+
// src/matchers/deep-equals.ts
|
|
542
|
+
import cloneDeep from "lodash/cloneDeep.js";
|
|
543
|
+
import cloneDeepWith2 from "lodash/cloneDeepWith.js";
|
|
544
|
+
import isEqualWith from "lodash/isEqualWith.js";
|
|
545
|
+
import isMap from "lodash/isMap.js";
|
|
546
|
+
import isObjectLike from "lodash/isObjectLike.js";
|
|
547
|
+
import omitBy from "lodash/omitBy.js";
|
|
548
|
+
var removeUndefined = (object) => {
|
|
584
549
|
if (Array.isArray(object)) {
|
|
585
|
-
return object.map(x => removeUndefined(x));
|
|
550
|
+
return object.map((x) => removeUndefined(x));
|
|
586
551
|
}
|
|
587
|
-
if (!
|
|
552
|
+
if (!isObjectLike(object)) {
|
|
588
553
|
return object;
|
|
589
554
|
}
|
|
590
|
-
return
|
|
555
|
+
return omitBy(object, (value) => value === void 0);
|
|
591
556
|
};
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
* this to `false` will consider the objects in both cases as equal.
|
|
600
|
-
*
|
|
601
|
-
* @see {@link It.containsObject} or {@link It.isArray} if you want to nest matchers.
|
|
602
|
-
* @see {@link It.is} if you want to use strict equality.
|
|
603
|
-
*/
|
|
604
|
-
const deepEquals = (expected, {
|
|
557
|
+
var getKey = (key, object) => {
|
|
558
|
+
if (key === void 0) {
|
|
559
|
+
return object;
|
|
560
|
+
}
|
|
561
|
+
return isMap(object) ? object.get(key) : object[key];
|
|
562
|
+
};
|
|
563
|
+
var deepEquals = (expected, {
|
|
605
564
|
strict = true
|
|
606
|
-
} = {}) => matches(
|
|
607
|
-
|
|
608
|
-
|
|
565
|
+
} = {}) => matches(
|
|
566
|
+
(actual) => isEqualWith(
|
|
567
|
+
strict ? actual : removeUndefined(actual),
|
|
568
|
+
strict ? expected : removeUndefined(expected),
|
|
569
|
+
(actualValue, expectedValue) => {
|
|
570
|
+
if (isMatcher(expectedValue)) {
|
|
571
|
+
return expectedValue.matches(actualValue);
|
|
572
|
+
}
|
|
573
|
+
return void 0;
|
|
574
|
+
}
|
|
575
|
+
),
|
|
576
|
+
{
|
|
577
|
+
toString: () => printValue(deepPrint(expected)),
|
|
578
|
+
getDiff: (actual) => {
|
|
579
|
+
let actualResult = cloneDeep(actual);
|
|
580
|
+
const expectedResult = cloneDeepWith2(expected, (expectedValue, key) => {
|
|
581
|
+
const actualValue = getKey(key, actualResult);
|
|
582
|
+
if (isMatcher(expectedValue)) {
|
|
583
|
+
if (expectedValue.matches(actualValue)) {
|
|
584
|
+
return actualValue;
|
|
585
|
+
}
|
|
586
|
+
const result = expectedValue.getDiff(actualValue);
|
|
587
|
+
if (key !== void 0) {
|
|
588
|
+
if (isMap(actualResult)) {
|
|
589
|
+
actualResult.set(key, result.actual);
|
|
590
|
+
} else {
|
|
591
|
+
actualResult[key] = result.actual;
|
|
592
|
+
}
|
|
593
|
+
} else {
|
|
594
|
+
actualResult = result.actual;
|
|
595
|
+
}
|
|
596
|
+
return result.expected;
|
|
597
|
+
}
|
|
598
|
+
return void 0;
|
|
599
|
+
});
|
|
600
|
+
return {
|
|
601
|
+
actual: actualResult,
|
|
602
|
+
expected: expectedResult
|
|
603
|
+
};
|
|
604
|
+
}
|
|
609
605
|
}
|
|
610
|
-
|
|
611
|
-
}, {
|
|
612
|
-
toString: () => printValue(expected),
|
|
613
|
-
getDiff: actual => ({
|
|
614
|
-
actual,
|
|
615
|
-
expected
|
|
616
|
-
})
|
|
617
|
-
});
|
|
606
|
+
);
|
|
618
607
|
|
|
619
|
-
|
|
608
|
+
// src/mock/defaults.ts
|
|
609
|
+
var defaults = {
|
|
620
610
|
concreteMatcher: deepEquals,
|
|
621
|
-
unexpectedProperty:
|
|
611
|
+
unexpectedProperty: 1 /* CALL_THROW */,
|
|
622
612
|
exactParams: false
|
|
623
613
|
};
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
*
|
|
628
|
-
* @param newDefaults These will be applied to the library defaults. Multiple
|
|
629
|
-
* calls don't stack e.g. calling this with `{}` will clear any previously
|
|
630
|
-
* applied defaults.
|
|
631
|
-
*/
|
|
632
|
-
const setDefaults = newDefaults => {
|
|
633
|
-
currentDefaults = {
|
|
634
|
-
...defaults,
|
|
635
|
-
...newDefaults
|
|
636
|
-
};
|
|
614
|
+
var currentDefaults = defaults;
|
|
615
|
+
var setDefaults = (newDefaults) => {
|
|
616
|
+
currentDefaults = __spreadValues(__spreadValues({}, defaults), newDefaults);
|
|
637
617
|
};
|
|
638
618
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
*
|
|
644
|
-
* We also want to throw in the following case:
|
|
645
|
-
*
|
|
646
|
-
* ```
|
|
647
|
-
* when(() => mock()) // forgot returns here
|
|
648
|
-
* when(() => mock()) // should throw
|
|
649
|
-
* ```
|
|
650
|
-
*
|
|
651
|
-
* For that reason we can't just store the currently active mock, but also
|
|
652
|
-
* whether we finished the expectation or not.
|
|
653
|
-
*/
|
|
654
|
-
let activeMock;
|
|
655
|
-
const setActiveMock = mock => {
|
|
656
|
-
activeMock = mock;
|
|
619
|
+
// src/mock/map.ts
|
|
620
|
+
var activeMock;
|
|
621
|
+
var setActiveMock = (mock2) => {
|
|
622
|
+
activeMock = mock2;
|
|
657
623
|
};
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
* and `thenReturn`.
|
|
664
|
-
*/
|
|
665
|
-
const mockMap = new Map();
|
|
666
|
-
const getMockState = mock => {
|
|
667
|
-
if (mockMap.has(mock)) {
|
|
668
|
-
return mockMap.get(mock);
|
|
624
|
+
var getActiveMock = () => activeMock;
|
|
625
|
+
var mockMap = /* @__PURE__ */ new Map();
|
|
626
|
+
var getMockState = (mock2) => {
|
|
627
|
+
if (mockMap.has(mock2)) {
|
|
628
|
+
return mockMap.get(mock2);
|
|
669
629
|
}
|
|
670
630
|
throw new NotAMock();
|
|
671
631
|
};
|
|
672
|
-
|
|
673
|
-
mockMap.set(
|
|
632
|
+
var setMockState = (mock2, state) => {
|
|
633
|
+
mockMap.set(mock2, state);
|
|
674
634
|
};
|
|
675
|
-
|
|
635
|
+
var getAllMocks = () => Array.from(mockMap.entries());
|
|
676
636
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
637
|
+
// src/mock/mode.ts
|
|
638
|
+
var currentMode = 1 /* CALL */;
|
|
639
|
+
var setMode = (mode) => {
|
|
640
|
+
currentMode = mode;
|
|
641
|
+
};
|
|
642
|
+
var getMode = () => currentMode;
|
|
643
|
+
|
|
644
|
+
// src/proxy.ts
|
|
645
|
+
var createProxy = (traps) => (
|
|
646
|
+
// The Proxy target MUST be a function, otherwise we can't use the `apply` trap:
|
|
647
|
+
// https://262.ecma-international.org/6.0/#sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist
|
|
648
|
+
new Proxy(
|
|
649
|
+
/* c8 ignore next */
|
|
650
|
+
() => {
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
get: (target, prop) => {
|
|
654
|
+
if (prop === "bind") {
|
|
655
|
+
return (thisArg, ...args) => (...moreArgs) => traps.apply([...args, ...moreArgs]);
|
|
656
|
+
}
|
|
657
|
+
if (prop === "apply") {
|
|
658
|
+
return (thisArg, args) => traps.apply(args || []);
|
|
659
|
+
}
|
|
660
|
+
if (prop === "call") {
|
|
661
|
+
return (thisArg, ...args) => traps.apply(args);
|
|
662
|
+
}
|
|
663
|
+
return traps.property(prop);
|
|
664
|
+
},
|
|
665
|
+
apply: (target, thisArg, args) => traps.apply(args),
|
|
666
|
+
ownKeys: () => traps.ownKeys(),
|
|
667
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
668
|
+
const keys = traps.ownKeys();
|
|
669
|
+
if (keys.includes(prop)) {
|
|
670
|
+
return {
|
|
671
|
+
configurable: true,
|
|
672
|
+
enumerable: true
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
return void 0;
|
|
676
|
+
}
|
|
703
677
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
});
|
|
678
|
+
)
|
|
679
|
+
);
|
|
707
680
|
|
|
708
|
-
|
|
681
|
+
// src/mock/stub.ts
|
|
682
|
+
var createStub = (repo, builder, getCurrentMode) => {
|
|
709
683
|
const stub = createProxy({
|
|
710
|
-
property: property => {
|
|
711
|
-
if (getCurrentMode() ===
|
|
684
|
+
property: (property) => {
|
|
685
|
+
if (getCurrentMode() === 1 /* CALL */) {
|
|
712
686
|
return repo.get(property);
|
|
713
687
|
}
|
|
714
688
|
setActiveMock(stub);
|
|
715
689
|
builder.setProperty(property);
|
|
716
690
|
return createProxy({
|
|
717
|
-
property: childProp => {
|
|
691
|
+
property: (childProp) => {
|
|
718
692
|
throw new NestedWhen(property, childProp);
|
|
719
693
|
},
|
|
720
|
-
apply: args => {
|
|
694
|
+
apply: (args) => {
|
|
721
695
|
builder.setArgs(args);
|
|
722
696
|
},
|
|
723
697
|
ownKeys: () => {
|
|
724
|
-
throw new Error(
|
|
698
|
+
throw new Error("Spreading during an expectation is not supported.");
|
|
725
699
|
}
|
|
726
700
|
});
|
|
727
701
|
},
|
|
728
|
-
apply: args => {
|
|
729
|
-
if (getCurrentMode() ===
|
|
702
|
+
apply: (args) => {
|
|
703
|
+
if (getCurrentMode() === 1 /* CALL */) {
|
|
730
704
|
return repo.apply(args);
|
|
731
705
|
}
|
|
732
706
|
setActiveMock(stub);
|
|
733
707
|
builder.setProperty(ApplyProp);
|
|
734
708
|
builder.setArgs(args);
|
|
735
|
-
return
|
|
709
|
+
return void 0;
|
|
736
710
|
},
|
|
737
711
|
ownKeys: () => {
|
|
738
|
-
if (getCurrentMode() ===
|
|
712
|
+
if (getCurrentMode() === 1 /* CALL */) {
|
|
739
713
|
return repo.getAllProperties();
|
|
740
714
|
}
|
|
741
|
-
throw new Error(
|
|
715
|
+
throw new Error("Spreading during an expectation is not supported.");
|
|
742
716
|
}
|
|
743
717
|
});
|
|
744
718
|
return stub;
|
|
745
719
|
};
|
|
746
720
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
currentMode = mode;
|
|
757
|
-
};
|
|
758
|
-
const getMode = () => currentMode;
|
|
759
|
-
/**
|
|
760
|
-
* Create a type safe mock.
|
|
761
|
-
*
|
|
762
|
-
* @see {@link when} Set expectations on the mock using `when`.
|
|
763
|
-
*
|
|
764
|
-
* @param options Configure the options for this specific mock, overriding any
|
|
765
|
-
* defaults that were set with {@link setDefaults}.
|
|
766
|
-
* @param options.unexpectedProperty Controls what happens when an unexpected
|
|
767
|
-
* property is accessed.
|
|
768
|
-
* @param options.concreteMatcher The matcher that will be used when one isn't
|
|
769
|
-
* specified explicitly.
|
|
770
|
-
* @param options.exactParams Controls whether the number of received arguments
|
|
771
|
-
* has to match the expectation.
|
|
772
|
-
*
|
|
773
|
-
* @example
|
|
774
|
-
* const fn = mock<() => number>();
|
|
775
|
-
*
|
|
776
|
-
* when(() => fn()).thenReturn(23);
|
|
777
|
-
*
|
|
778
|
-
* fn() === 23;
|
|
779
|
-
*/
|
|
780
|
-
const mock = ({
|
|
721
|
+
// src/mock/mock.ts
|
|
722
|
+
var strongExpectationFactory = (property, args, returnValue, concreteMatcher, exactParams) => new StrongExpectation(
|
|
723
|
+
property,
|
|
724
|
+
// Wrap every non-matcher in the default matcher.
|
|
725
|
+
args == null ? void 0 : args.map((arg) => isMatcher(arg) ? arg : concreteMatcher(arg)),
|
|
726
|
+
returnValue,
|
|
727
|
+
exactParams
|
|
728
|
+
);
|
|
729
|
+
var mock = ({
|
|
781
730
|
unexpectedProperty,
|
|
782
731
|
concreteMatcher,
|
|
783
732
|
exactParams
|
|
@@ -788,7 +737,11 @@ const mock = ({
|
|
|
788
737
|
exactParams: exactParams != null ? exactParams : currentDefaults.exactParams
|
|
789
738
|
};
|
|
790
739
|
const repository = new FlexibleRepository(options.unexpectedProperty);
|
|
791
|
-
const builder = new ExpectationBuilderWithFactory(
|
|
740
|
+
const builder = new ExpectationBuilderWithFactory(
|
|
741
|
+
strongExpectationFactory,
|
|
742
|
+
options.concreteMatcher,
|
|
743
|
+
options.exactParams
|
|
744
|
+
);
|
|
792
745
|
const stub = createStub(repository, builder, getMode);
|
|
793
746
|
setMockState(stub, {
|
|
794
747
|
repository,
|
|
@@ -798,44 +751,45 @@ const mock = ({
|
|
|
798
751
|
return stub;
|
|
799
752
|
};
|
|
800
753
|
|
|
801
|
-
|
|
754
|
+
// src/return/invocation-count.ts
|
|
755
|
+
var createInvocationCount = (expectation) => ({
|
|
802
756
|
between(min, max) {
|
|
803
757
|
expectation.setInvocationCount(min, max);
|
|
804
758
|
},
|
|
805
|
-
/*
|
|
759
|
+
/* c8 ignore next 3 */
|
|
806
760
|
times(exact) {
|
|
807
761
|
expectation.setInvocationCount(exact, exact);
|
|
808
762
|
},
|
|
809
|
-
/*
|
|
763
|
+
/* c8 ignore next 3 */
|
|
810
764
|
anyTimes() {
|
|
811
765
|
expectation.setInvocationCount(0, 0);
|
|
812
766
|
},
|
|
813
|
-
/*
|
|
767
|
+
/* c8 ignore next 3 */
|
|
814
768
|
atLeast(min) {
|
|
815
769
|
expectation.setInvocationCount(min, Infinity);
|
|
816
770
|
},
|
|
817
|
-
/*
|
|
771
|
+
/* c8 ignore next 3 */
|
|
818
772
|
atMost(max) {
|
|
819
773
|
expectation.setInvocationCount(0, max);
|
|
820
774
|
},
|
|
821
|
-
/*
|
|
775
|
+
/* c8 ignore next 3 */
|
|
822
776
|
once() {
|
|
823
777
|
expectation.setInvocationCount(1, 1);
|
|
824
778
|
},
|
|
825
|
-
/*
|
|
779
|
+
/* c8 ignore next 3 */
|
|
826
780
|
twice() {
|
|
827
781
|
expectation.setInvocationCount(2, 2);
|
|
828
782
|
}
|
|
829
|
-
/* eslint-enable no-param-reassign, no-multi-assign */
|
|
830
783
|
});
|
|
831
784
|
|
|
832
|
-
|
|
785
|
+
// src/return/returns.ts
|
|
786
|
+
var finishExpectation = (returnValue, builder, repo) => {
|
|
833
787
|
const finishedExpectation = builder.finish(returnValue);
|
|
834
788
|
repo.add(finishedExpectation);
|
|
835
789
|
return createInvocationCount(finishedExpectation);
|
|
836
790
|
};
|
|
837
|
-
|
|
838
|
-
if (typeof errorOrMessage ===
|
|
791
|
+
var getError = (errorOrMessage) => {
|
|
792
|
+
if (typeof errorOrMessage === "string") {
|
|
839
793
|
return new Error(errorOrMessage);
|
|
840
794
|
}
|
|
841
795
|
if (errorOrMessage instanceof Error) {
|
|
@@ -843,128 +797,95 @@ const getError = errorOrMessage => {
|
|
|
843
797
|
}
|
|
844
798
|
return new Error();
|
|
845
799
|
};
|
|
846
|
-
|
|
847
|
-
thenReturn: returnValue => finishExpectation(
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
800
|
+
var createReturns = (builder, repository) => ({
|
|
801
|
+
thenReturn: (returnValue) => finishExpectation(
|
|
802
|
+
// This will handle both thenReturn(23) and thenReturn(Promise.resolve(3)).
|
|
803
|
+
{ value: returnValue, isError: false, isPromise: false },
|
|
804
|
+
builder,
|
|
805
|
+
repository
|
|
806
|
+
),
|
|
807
|
+
thenThrow: (errorOrMessage) => finishExpectation(
|
|
808
|
+
{ value: getError(errorOrMessage), isError: true, isPromise: false },
|
|
809
|
+
builder,
|
|
810
|
+
repository
|
|
811
|
+
),
|
|
812
|
+
thenResolve: (promiseValue) => finishExpectation(
|
|
813
|
+
{
|
|
814
|
+
value: promiseValue,
|
|
815
|
+
isError: false,
|
|
816
|
+
isPromise: true
|
|
817
|
+
},
|
|
818
|
+
builder,
|
|
819
|
+
repository
|
|
820
|
+
),
|
|
821
|
+
thenReject: (errorOrMessage) => finishExpectation(
|
|
822
|
+
{
|
|
823
|
+
value: getError(errorOrMessage),
|
|
824
|
+
isError: true,
|
|
825
|
+
isPromise: true
|
|
826
|
+
},
|
|
827
|
+
builder,
|
|
828
|
+
repository
|
|
829
|
+
)
|
|
869
830
|
});
|
|
870
831
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
* The expectation must be finished by setting a return value, even if the value
|
|
875
|
-
* is `undefined`.
|
|
876
|
-
*
|
|
877
|
-
* If a call happens that was not expected then the mock will throw an error.
|
|
878
|
-
* By default, the call is expected to only be made once. Use the invocation
|
|
879
|
-
* count helpers to expect a call multiple times.
|
|
880
|
-
*
|
|
881
|
-
* @param expectation A callback to set the expectation on your mock. The
|
|
882
|
-
* callback must return the value from the mock to properly infer types.
|
|
883
|
-
*
|
|
884
|
-
* @example
|
|
885
|
-
* const fn = mock<() => void>();
|
|
886
|
-
* when(() => fn()).thenReturn(undefined);
|
|
887
|
-
*
|
|
888
|
-
* @example
|
|
889
|
-
* const fn = mock<() => number>();
|
|
890
|
-
* when(() => fn()).thenReturn(42).atMost(3);
|
|
891
|
-
*
|
|
892
|
-
* @example
|
|
893
|
-
* const fn = mock<(x: number) => Promise<number>();
|
|
894
|
-
* when(() => fn(23)).thenResolve(42);
|
|
895
|
-
*/
|
|
896
|
-
const when = expectation => {
|
|
897
|
-
setMode(Mode.EXPECT);
|
|
832
|
+
// src/when/when.ts
|
|
833
|
+
var when = (expectation) => {
|
|
834
|
+
setMode(0 /* EXPECT */);
|
|
898
835
|
expectation();
|
|
899
|
-
setMode(
|
|
900
|
-
const {
|
|
901
|
-
builder,
|
|
902
|
-
repository
|
|
903
|
-
} = getMockState(getActiveMock());
|
|
836
|
+
setMode(1 /* CALL */);
|
|
837
|
+
const { builder, repository } = getMockState(getActiveMock());
|
|
904
838
|
return createReturns(builder, repository);
|
|
905
839
|
};
|
|
906
840
|
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
* @example
|
|
911
|
-
* const fn = mock<() => number>();
|
|
912
|
-
*
|
|
913
|
-
* when(() => fn()).thenReturn(23);
|
|
914
|
-
*
|
|
915
|
-
* reset(fn);
|
|
916
|
-
*
|
|
917
|
-
* fn(); // throws
|
|
918
|
-
*/
|
|
919
|
-
const reset = mock => {
|
|
920
|
-
getMockState(mock).repository.clear();
|
|
841
|
+
// src/verify/reset.ts
|
|
842
|
+
var reset = (mock2) => {
|
|
843
|
+
getMockState(mock2).repository.clear();
|
|
921
844
|
};
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
* @see reset
|
|
926
|
-
*/
|
|
927
|
-
const resetAll = () => {
|
|
928
|
-
getAllMocks().forEach(([mock]) => {
|
|
929
|
-
reset(mock);
|
|
845
|
+
var resetAll = () => {
|
|
846
|
+
getAllMocks().forEach(([mock2]) => {
|
|
847
|
+
reset(mock2);
|
|
930
848
|
});
|
|
931
849
|
};
|
|
932
850
|
|
|
933
|
-
|
|
851
|
+
// src/errors/verify.ts
|
|
852
|
+
import { DIM_COLOR as DIM_COLOR3 } from "jest-matcher-utils";
|
|
853
|
+
var UnmetExpectations = class extends Error {
|
|
934
854
|
constructor(expectations) {
|
|
935
|
-
super(
|
|
855
|
+
super(
|
|
856
|
+
DIM_COLOR3(`There are unmet expectations:
|
|
936
857
|
|
|
937
|
-
- ${expectations.map(e => e.toString()).join(
|
|
858
|
+
- ${expectations.map((e) => e.toString()).join("\n - ")}`)
|
|
859
|
+
);
|
|
938
860
|
}
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
if (hasMethodCalls && hasPropertyAccesses) {
|
|
952
|
-
return [property, calls.filter(call => call.arguments)];
|
|
953
|
-
}
|
|
954
|
-
return [property, calls];
|
|
955
|
-
}));
|
|
956
|
-
class UnexpectedCalls extends Error {
|
|
861
|
+
};
|
|
862
|
+
var mergeCalls = (callMap) => new Map(
|
|
863
|
+
Array.from(callMap.entries()).map(([property, calls]) => {
|
|
864
|
+
const hasMethodCalls = calls.some((call) => call.arguments);
|
|
865
|
+
const hasPropertyAccesses = calls.some((call) => !call.arguments);
|
|
866
|
+
if (hasMethodCalls && hasPropertyAccesses) {
|
|
867
|
+
return [property, calls.filter((call) => call.arguments)];
|
|
868
|
+
}
|
|
869
|
+
return [property, calls];
|
|
870
|
+
})
|
|
871
|
+
);
|
|
872
|
+
var UnexpectedCalls = class extends Error {
|
|
957
873
|
constructor(unexpectedCalls, expectations) {
|
|
958
|
-
const printedCalls = Array.from(mergeCalls(unexpectedCalls).entries()).map(
|
|
959
|
-
|
|
874
|
+
const printedCalls = Array.from(mergeCalls(unexpectedCalls).entries()).map(
|
|
875
|
+
([property, calls]) => calls.map((call) => printCall(property, call.arguments)).join("\n - ")
|
|
876
|
+
).join("\n - ");
|
|
877
|
+
super(
|
|
878
|
+
DIM_COLOR3(`The following calls were unexpected:
|
|
960
879
|
|
|
961
880
|
- ${printedCalls}
|
|
962
881
|
|
|
963
|
-
${printRemainingExpectations(expectations)}`)
|
|
882
|
+
${printRemainingExpectations(expectations)}`)
|
|
883
|
+
);
|
|
964
884
|
}
|
|
965
|
-
}
|
|
885
|
+
};
|
|
966
886
|
|
|
967
|
-
|
|
887
|
+
// src/verify/verify.ts
|
|
888
|
+
var verifyRepo = (repository) => {
|
|
968
889
|
const unmetExpectations = repository.getUnmet();
|
|
969
890
|
if (unmetExpectations.length) {
|
|
970
891
|
throw new UnmetExpectations(unmetExpectations);
|
|
@@ -974,213 +895,161 @@ const verifyRepo = repository => {
|
|
|
974
895
|
throw new UnexpectedCalls(callStats.unexpected, unmetExpectations);
|
|
975
896
|
}
|
|
976
897
|
};
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
*
|
|
980
|
-
* @throws Will throw if there are remaining expectations that were set
|
|
981
|
-
* using `when` and that weren't met.
|
|
982
|
-
*
|
|
983
|
-
* @throws Will throw if any unexpected calls happened. Normally those
|
|
984
|
-
* calls throw on their own, but the error might be caught by the code
|
|
985
|
-
* being tested.
|
|
986
|
-
*
|
|
987
|
-
* @example
|
|
988
|
-
* const fn = mock<() => number>();
|
|
989
|
-
*
|
|
990
|
-
* when(() => fn()).thenReturn(23);
|
|
991
|
-
*
|
|
992
|
-
* verify(fn); // throws
|
|
993
|
-
*/
|
|
994
|
-
const verify = mock => {
|
|
995
|
-
const {
|
|
996
|
-
repository
|
|
997
|
-
} = getMockState(mock);
|
|
898
|
+
var verify = (mock2) => {
|
|
899
|
+
const { repository } = getMockState(mock2);
|
|
998
900
|
verifyRepo(repository);
|
|
999
901
|
};
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
* @see verify
|
|
1004
|
-
*/
|
|
1005
|
-
const verifyAll = () => {
|
|
1006
|
-
getAllMocks().forEach(([mock]) => {
|
|
1007
|
-
verify(mock);
|
|
902
|
+
var verifyAll = () => {
|
|
903
|
+
getAllMocks().forEach(([mock2]) => {
|
|
904
|
+
verify(mock2);
|
|
1008
905
|
});
|
|
1009
906
|
};
|
|
1010
907
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
908
|
+
// src/matchers/it.ts
|
|
909
|
+
var it_exports = {};
|
|
910
|
+
__export(it_exports, {
|
|
911
|
+
containsObject: () => containsObject,
|
|
912
|
+
deepEquals: () => deepEquals,
|
|
913
|
+
is: () => is,
|
|
914
|
+
isAny: () => isAny,
|
|
915
|
+
isArray: () => isArray,
|
|
916
|
+
isNumber: () => isNumber,
|
|
917
|
+
isPlainObject: () => isPlainObject,
|
|
918
|
+
isString: () => isString,
|
|
919
|
+
matches: () => matches,
|
|
920
|
+
willCapture: () => willCapture
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
// src/matchers/is.ts
|
|
924
|
+
var is = (expected) => matches((actual) => Object.is(actual, expected), {
|
|
1019
925
|
toString: () => `${printValue(expected)}`,
|
|
1020
|
-
getDiff: actual => ({
|
|
1021
|
-
actual,
|
|
1022
|
-
expected
|
|
1023
|
-
})
|
|
926
|
+
getDiff: (actual) => ({ actual, expected })
|
|
1024
927
|
});
|
|
1025
928
|
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
* @example
|
|
1030
|
-
* const fn = mock<(x: number, y: string) => number>();
|
|
1031
|
-
* when(() => fn(It.isAny(), It.isAny())).thenReturn(1);
|
|
1032
|
-
*
|
|
1033
|
-
* fn(23, 'foobar') === 1
|
|
1034
|
-
*/
|
|
1035
|
-
const isAny = () => matches(() => true, {
|
|
1036
|
-
toString: () => 'Matcher<any>'
|
|
929
|
+
// src/matchers/is-any.ts
|
|
930
|
+
var isAny = () => matches(() => true, {
|
|
931
|
+
toString: () => "Matcher<any>"
|
|
1037
932
|
});
|
|
1038
933
|
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
* @example
|
|
1048
|
-
* const fn = mock<(arr: number[]) => number>();
|
|
1049
|
-
* when(() => fn(It.isArray())).thenReturn(1);
|
|
1050
|
-
* when(() => fn(It.isArray([2, 3]))).thenReturn(2);
|
|
1051
|
-
*
|
|
1052
|
-
* fn({ length: 1, 0: 42 }) // throws
|
|
1053
|
-
* fn([]) === 1
|
|
1054
|
-
* fn([3, 2, 1]) === 2
|
|
1055
|
-
*
|
|
1056
|
-
* @example
|
|
1057
|
-
* It.isArray([It.isString({ containing: 'foobar' })])
|
|
1058
|
-
*/
|
|
1059
|
-
const isArray = containing => matches(actual => {
|
|
1060
|
-
if (!Array.isArray(actual)) {
|
|
1061
|
-
return false;
|
|
1062
|
-
}
|
|
1063
|
-
if (!containing) {
|
|
1064
|
-
return true;
|
|
1065
|
-
}
|
|
1066
|
-
return containing.every(x => actual.find(y => {
|
|
1067
|
-
if (isMatcher(x)) {
|
|
1068
|
-
return x.matches(y);
|
|
934
|
+
// src/matchers/is-array.ts
|
|
935
|
+
var isArray = (containing) => matches(
|
|
936
|
+
(actual) => {
|
|
937
|
+
if (!Array.isArray(actual)) {
|
|
938
|
+
return false;
|
|
939
|
+
}
|
|
940
|
+
if (!containing) {
|
|
941
|
+
return true;
|
|
1069
942
|
}
|
|
1070
|
-
return
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
943
|
+
return containing.every(
|
|
944
|
+
(x) => actual.find((y) => {
|
|
945
|
+
if (isMatcher(x)) {
|
|
946
|
+
return x.matches(y);
|
|
947
|
+
}
|
|
948
|
+
return deepEquals(x).matches(y);
|
|
949
|
+
}) !== void 0
|
|
950
|
+
);
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
toString: () => containing ? `array([${containing.map((v) => printValue(v)).join(", ")}])` : "array",
|
|
954
|
+
getDiff: (actual) => {
|
|
955
|
+
if (containing) {
|
|
956
|
+
return {
|
|
957
|
+
actual,
|
|
958
|
+
expected: `Matcher<array>([${containing.map((value) => {
|
|
959
|
+
if (isMatcher(value)) {
|
|
960
|
+
return value.toString();
|
|
961
|
+
}
|
|
962
|
+
return value;
|
|
963
|
+
}).join(", ")}])`
|
|
964
|
+
};
|
|
965
|
+
}
|
|
1076
966
|
return {
|
|
1077
|
-
actual
|
|
1078
|
-
expected:
|
|
1079
|
-
if (isMatcher(value)) {
|
|
1080
|
-
return value.toString();
|
|
1081
|
-
}
|
|
1082
|
-
return value;
|
|
1083
|
-
}).join(', ')}])`
|
|
967
|
+
actual: `${printValue(actual)} (${typeof actual})`,
|
|
968
|
+
expected: "Matcher<array>"
|
|
1084
969
|
};
|
|
1085
970
|
}
|
|
1086
|
-
return {
|
|
1087
|
-
actual: `${printValue(actual)} (${typeof actual})`,
|
|
1088
|
-
expected: 'Matcher<array>'
|
|
1089
|
-
};
|
|
1090
971
|
}
|
|
1091
|
-
|
|
972
|
+
);
|
|
1092
973
|
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
* const fn = mock<(x: number) => number>();
|
|
1098
|
-
* when(() => fn(It.isNumber())).returns(42);
|
|
1099
|
-
*
|
|
1100
|
-
* fn(20.5) === 42
|
|
1101
|
-
* fn(NaN) // throws
|
|
1102
|
-
*/
|
|
1103
|
-
const isNumber = () => matches(actual => typeof actual === 'number' && !Number.isNaN(actual), {
|
|
1104
|
-
toString: () => 'Matcher<number>',
|
|
1105
|
-
getDiff: actual => ({
|
|
974
|
+
// src/matchers/is-number.ts
|
|
975
|
+
var isNumber = () => matches((actual) => typeof actual === "number" && !Number.isNaN(actual), {
|
|
976
|
+
toString: () => "Matcher<number>",
|
|
977
|
+
getDiff: (actual) => ({
|
|
1106
978
|
actual: `${printValue(actual)} (${typeof actual})`,
|
|
1107
|
-
expected:
|
|
979
|
+
expected: "Matcher<number>"
|
|
1108
980
|
})
|
|
1109
981
|
});
|
|
1110
982
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
* const fn = mock<({ foo: string }) => number>();
|
|
1119
|
-
* when(() => fn(It.isPlainObject())).thenReturn(42);
|
|
1120
|
-
*
|
|
1121
|
-
* fn({ foo: 'bar' }) // returns 42
|
|
1122
|
-
*/
|
|
1123
|
-
const isPlainObject = () => matches(actual => lodash.isPlainObject(actual), {
|
|
1124
|
-
toString: () => 'Matcher<object>',
|
|
1125
|
-
getDiff: actual => {
|
|
1126
|
-
const type = lodash.isObjectLike(actual) ? 'object-like' : typeof actual;
|
|
983
|
+
// src/matchers/is-plain-object.ts
|
|
984
|
+
import isObjectLike2 from "lodash/isObjectLike.js";
|
|
985
|
+
import isPlainObjectLodash from "lodash/isPlainObject.js";
|
|
986
|
+
var isPlainObject = () => matches((actual) => isPlainObjectLodash(actual), {
|
|
987
|
+
toString: () => "Matcher<object>",
|
|
988
|
+
getDiff: (actual) => {
|
|
989
|
+
const type = isObjectLike2(actual) ? "object-like" : typeof actual;
|
|
1127
990
|
return {
|
|
1128
991
|
actual: `${printValue(actual)} (${type})`,
|
|
1129
|
-
expected:
|
|
992
|
+
expected: "Matcher<object>"
|
|
1130
993
|
};
|
|
1131
994
|
}
|
|
1132
995
|
});
|
|
1133
996
|
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
997
|
+
// src/matchers/contains-object.ts
|
|
998
|
+
import isPlainObject2 from "lodash/isPlainObject.js";
|
|
999
|
+
var looksLikeObject = (value) => isPlainObject2(value);
|
|
1000
|
+
var getExpectedObjectDiff = (actual, expected) => Object.fromEntries(
|
|
1001
|
+
getKeys(expected).map((key) => {
|
|
1002
|
+
const expectedValue = getKey2(expected, key);
|
|
1003
|
+
const actualValue = getKey2(actual, key);
|
|
1004
|
+
if (isMatcher(expectedValue)) {
|
|
1005
|
+
return [key, expectedValue.getDiff(actualValue).expected];
|
|
1006
|
+
}
|
|
1007
|
+
if (looksLikeObject(expectedValue)) {
|
|
1008
|
+
return [key, getExpectedObjectDiff(actualValue, expectedValue)];
|
|
1009
|
+
}
|
|
1010
|
+
return [key, expectedValue];
|
|
1011
|
+
})
|
|
1012
|
+
);
|
|
1013
|
+
var getActualObjectDiff = (actual, expected) => {
|
|
1147
1014
|
const actualKeys = getKeys(actual);
|
|
1148
1015
|
const expectedKeys = new Set(getKeys(expected));
|
|
1149
|
-
const commonKeys = actualKeys.filter(key => expectedKeys.has(key));
|
|
1016
|
+
const commonKeys = actualKeys.filter((key) => expectedKeys.has(key));
|
|
1150
1017
|
if (!commonKeys.length) {
|
|
1151
|
-
// When we don't have any common keys we return the whole object
|
|
1152
|
-
// so the user can inspect what's in there.
|
|
1153
1018
|
return actual;
|
|
1154
1019
|
}
|
|
1155
|
-
return Object.fromEntries(
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1020
|
+
return Object.fromEntries(
|
|
1021
|
+
commonKeys.map((key) => {
|
|
1022
|
+
const expectedValue = getKey2(expected, key);
|
|
1023
|
+
const actualValue = getKey2(actual, key);
|
|
1024
|
+
if (isMatcher(expectedValue)) {
|
|
1025
|
+
return [key, expectedValue.getDiff(actualValue).actual];
|
|
1026
|
+
}
|
|
1027
|
+
if (looksLikeObject(expectedValue)) {
|
|
1028
|
+
return [key, getActualObjectDiff(actualValue, expectedValue)];
|
|
1029
|
+
}
|
|
1030
|
+
return [key, actualValue];
|
|
1031
|
+
})
|
|
1032
|
+
);
|
|
1166
1033
|
};
|
|
1167
|
-
|
|
1168
|
-
if (typeof value ===
|
|
1034
|
+
var getKeys = (value) => {
|
|
1035
|
+
if (typeof value === "object" && value !== null) {
|
|
1169
1036
|
return Reflect.ownKeys(value);
|
|
1170
1037
|
}
|
|
1171
1038
|
return [];
|
|
1172
1039
|
};
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1040
|
+
var getKey2 = (value, key) => (
|
|
1041
|
+
// @ts-expect-error because we're fine with a runtime undefined value
|
|
1042
|
+
value == null ? void 0 : value[key]
|
|
1043
|
+
);
|
|
1044
|
+
var isMatch = (actual, expected) => {
|
|
1176
1045
|
const actualKeys = getKeys(actual);
|
|
1177
1046
|
const expectedKeys = getKeys(expected);
|
|
1178
1047
|
if (!isArray(expectedKeys).matches(actualKeys)) {
|
|
1179
1048
|
return false;
|
|
1180
1049
|
}
|
|
1181
|
-
return expectedKeys.every(key => {
|
|
1182
|
-
const expectedValue =
|
|
1183
|
-
const actualValue =
|
|
1050
|
+
return expectedKeys.every((key) => {
|
|
1051
|
+
const expectedValue = getKey2(expected, key);
|
|
1052
|
+
const actualValue = getKey2(actual, key);
|
|
1184
1053
|
if (isMatcher(expectedValue)) {
|
|
1185
1054
|
return expectedValue.matches(actualValue);
|
|
1186
1055
|
}
|
|
@@ -1190,114 +1059,61 @@ const isMatch = (actual, expected) => {
|
|
|
1190
1059
|
return deepEquals(expectedValue).matches(actualValue);
|
|
1191
1060
|
});
|
|
1192
1061
|
};
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
}
|
|
1197
|
-
return undefined;
|
|
1198
|
-
});
|
|
1199
|
-
/**
|
|
1200
|
-
* Check if an object recursively contains the expected properties,
|
|
1201
|
-
* i.e. the expected object is a subset of the received object.
|
|
1202
|
-
*
|
|
1203
|
-
* @param partial A subset of the expected object that will be recursively matched.
|
|
1204
|
-
* Supports nested matchers.
|
|
1205
|
-
* Concrete values will be compared with {@link deepEquals}.
|
|
1206
|
-
*
|
|
1207
|
-
* @see {@link isPlainObject} if you want to match any plain object.
|
|
1208
|
-
*
|
|
1209
|
-
* @example
|
|
1210
|
-
* const fn = mock<(pos: { x: number, y: number }) => number>();
|
|
1211
|
-
* when(() => fn(It.containsObject({ x: 23 }))).returns(42);
|
|
1212
|
-
*
|
|
1213
|
-
* fn({ x: 23, y: 200 }) // returns 42
|
|
1214
|
-
*
|
|
1215
|
-
* @example
|
|
1216
|
-
* It.containsObject({ foo: It.isString() })
|
|
1217
|
-
*/
|
|
1218
|
-
// T is not constrained to ObjectType because of
|
|
1219
|
-
// https://github.com/microsoft/TypeScript/issues/57810,
|
|
1220
|
-
// but K is to avoid inferring non-object partials
|
|
1221
|
-
const containsObject = partial => matches(actual => isMatch(actual, partial), {
|
|
1222
|
-
toString: () => `Matcher<object>(${printValue(deepPrintObject(partial))})`,
|
|
1223
|
-
getDiff: actual => ({
|
|
1062
|
+
var containsObject = (partial) => matches((actual) => isMatch(actual, partial), {
|
|
1063
|
+
toString: () => `Matcher<object>(${printValue(deepPrint(partial))})`,
|
|
1064
|
+
getDiff: (actual) => ({
|
|
1224
1065
|
actual: getActualObjectDiff(actual, partial),
|
|
1225
1066
|
expected: getExpectedObjectDiff(actual, partial)
|
|
1226
1067
|
})
|
|
1227
1068
|
});
|
|
1228
1069
|
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
*
|
|
1235
|
-
* @example
|
|
1236
|
-
* const fn = mock<(x: string, y: string) => number>();
|
|
1237
|
-
* when(() => fn(It.isString(), It.isString('bar'))).returns(42);
|
|
1238
|
-
*
|
|
1239
|
-
* fn('foo', 'baz') // throws
|
|
1240
|
-
* fn('foo', 'bar') === 42
|
|
1241
|
-
*/
|
|
1242
|
-
const isString = matching => matches(actual => {
|
|
1243
|
-
if (typeof actual !== 'string') {
|
|
1244
|
-
return false;
|
|
1245
|
-
}
|
|
1246
|
-
if (!matching) {
|
|
1247
|
-
return true;
|
|
1248
|
-
}
|
|
1249
|
-
if (typeof matching === 'string') {
|
|
1250
|
-
return actual.indexOf(matching) !== -1;
|
|
1251
|
-
}
|
|
1252
|
-
return matching.test(actual);
|
|
1253
|
-
}, {
|
|
1254
|
-
toString: () => {
|
|
1255
|
-
if (matching) {
|
|
1256
|
-
return `Matcher<string>(${matching})`;
|
|
1070
|
+
// src/matchers/is-string.ts
|
|
1071
|
+
var isString = (matching) => matches(
|
|
1072
|
+
(actual) => {
|
|
1073
|
+
if (typeof actual !== "string") {
|
|
1074
|
+
return false;
|
|
1257
1075
|
}
|
|
1258
|
-
|
|
1076
|
+
if (!matching) {
|
|
1077
|
+
return true;
|
|
1078
|
+
}
|
|
1079
|
+
if (typeof matching === "string") {
|
|
1080
|
+
return actual.indexOf(matching) !== -1;
|
|
1081
|
+
}
|
|
1082
|
+
return matching.test(actual);
|
|
1259
1083
|
},
|
|
1260
|
-
|
|
1261
|
-
|
|
1084
|
+
{
|
|
1085
|
+
toString: () => {
|
|
1086
|
+
if (matching) {
|
|
1087
|
+
return `Matcher<string>(${matching})`;
|
|
1088
|
+
}
|
|
1089
|
+
return "Matcher<string>";
|
|
1090
|
+
},
|
|
1091
|
+
getDiff: (actual) => {
|
|
1092
|
+
if (matching) {
|
|
1093
|
+
return {
|
|
1094
|
+
expected: `Matcher<string>(${matching})`,
|
|
1095
|
+
actual
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1262
1098
|
return {
|
|
1263
|
-
expected:
|
|
1264
|
-
actual
|
|
1099
|
+
expected: "Matcher<string>",
|
|
1100
|
+
actual: `${actual} (${typeof actual})`
|
|
1265
1101
|
};
|
|
1266
1102
|
}
|
|
1267
|
-
return {
|
|
1268
|
-
expected: 'Matcher<string>',
|
|
1269
|
-
actual: `${actual} (${typeof actual})`
|
|
1270
|
-
};
|
|
1271
1103
|
}
|
|
1272
|
-
|
|
1104
|
+
);
|
|
1273
1105
|
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
*
|
|
1277
|
-
* This should not be needed for most cases, but can be useful if you need
|
|
1278
|
-
* access to a complex argument outside the expectation e.g. to test a
|
|
1279
|
-
* callback.
|
|
1280
|
-
*
|
|
1281
|
-
* @param name If given, this name will be printed in error messages.
|
|
1282
|
-
*
|
|
1283
|
-
* @example
|
|
1284
|
-
* const fn = mock<(cb: (value: number) => number) => void>();
|
|
1285
|
-
* const matcher = It.willCapture();
|
|
1286
|
-
* when(() => fn(matcher)).thenReturn();
|
|
1287
|
-
*
|
|
1288
|
-
* fn(x => x + 1);
|
|
1289
|
-
* matcher.value?.(3) === 4
|
|
1290
|
-
*/
|
|
1291
|
-
const willCapture = name => {
|
|
1106
|
+
// src/matchers/will-capture.ts
|
|
1107
|
+
var willCapture = (name) => {
|
|
1292
1108
|
let capturedValue;
|
|
1293
1109
|
const matcher = {
|
|
1294
1110
|
[MATCHER_SYMBOL]: true,
|
|
1295
|
-
matches: actual => {
|
|
1111
|
+
matches: (actual) => {
|
|
1296
1112
|
capturedValue = actual;
|
|
1297
1113
|
return true;
|
|
1298
1114
|
},
|
|
1299
|
-
toString: () => name ? `Capture(${name})` :
|
|
1300
|
-
getDiff: actual => ({
|
|
1115
|
+
toString: () => name ? `Capture(${name})` : "Capture",
|
|
1116
|
+
getDiff: (actual) => ({
|
|
1301
1117
|
actual,
|
|
1302
1118
|
expected: actual
|
|
1303
1119
|
}),
|
|
@@ -1307,29 +1123,15 @@ const willCapture = name => {
|
|
|
1307
1123
|
};
|
|
1308
1124
|
return matcher;
|
|
1309
1125
|
};
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
isPlainObject: isPlainObject,
|
|
1321
|
-
containsObject: containsObject,
|
|
1322
|
-
isString: isString,
|
|
1323
|
-
matches: matches,
|
|
1324
|
-
willCapture: willCapture
|
|
1126
|
+
export {
|
|
1127
|
+
it_exports as It,
|
|
1128
|
+
UnexpectedProperty,
|
|
1129
|
+
mock,
|
|
1130
|
+
reset,
|
|
1131
|
+
resetAll,
|
|
1132
|
+
setDefaults,
|
|
1133
|
+
verify,
|
|
1134
|
+
verifyAll,
|
|
1135
|
+
when
|
|
1325
1136
|
};
|
|
1326
|
-
|
|
1327
|
-
exports.It = it;
|
|
1328
|
-
exports.mock = mock;
|
|
1329
|
-
exports.reset = reset;
|
|
1330
|
-
exports.resetAll = resetAll;
|
|
1331
|
-
exports.setDefaults = setDefaults;
|
|
1332
|
-
exports.verify = verify;
|
|
1333
|
-
exports.verifyAll = verifyAll;
|
|
1334
|
-
exports.when = when;
|
|
1335
|
-
//# sourceMappingURL=index.js.map
|
|
1137
|
+
/* c8 ignore next 3 this is not expected in practice -- @preserve */
|