strong-mock 8.0.0-beta.0 → 8.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -89
- package/dist/errors.d.ts +4 -4
- package/dist/expectation/expectation.d.ts +3 -7
- package/dist/expectation/it.d.ts +1 -1
- package/dist/expectation/repository/expectation-repository.d.ts +22 -7
- package/dist/expectation/repository/flexible-repository.d.ts +38 -0
- package/dist/expectation/repository/return-value.d.ts +13 -0
- package/dist/expectation/strong-expectation.d.ts +6 -4
- package/dist/index.d.ts +2 -1
- package/dist/index.js +345 -299
- package/dist/index.js.map +1 -1
- package/dist/mock/defaults.d.ts +3 -19
- package/dist/mock/map.d.ts +5 -3
- package/dist/mock/mock.d.ts +15 -15
- package/dist/mock/options.d.ts +99 -0
- package/dist/mock/stub.d.ts +5 -13
- package/dist/print.d.ts +3 -2
- package/dist/proxy.d.ts +1 -1
- package/dist/return/invocation-count.d.ts +1 -1
- package/dist/return/returns.d.ts +11 -7
- package/dist/verify/reset.d.ts +1 -1
- package/dist/verify/verify.d.ts +2 -2
- package/dist/when/pending-expectation.d.ts +20 -17
- package/dist/when/when.d.ts +7 -2
- package/package.json +7 -7
- package/dist/expectation/repository/base-repository.d.ts +0 -41
- package/dist/expectation/repository/strong-repository.d.ts +0 -10
- package/dist/expectation/repository/weak-repository.d.ts +0 -17
package/README.md
CHANGED
|
@@ -44,14 +44,16 @@ console.log(foo.bar(23)); // 'I am strong!'
|
|
|
44
44
|
- [Verifying expectations](#verifying-expectations)
|
|
45
45
|
- [Resetting expectations](#resetting-expectations)
|
|
46
46
|
- [Argument matchers](#argument-matchers)
|
|
47
|
-
|
|
47
|
+
- [Mock options](#mock-options)
|
|
48
|
+
- [Unexpected property return value](#unexpected-property-return-value)
|
|
49
|
+
- [Exact params](#exact-params)
|
|
50
|
+
- [Concrete matcher](#concrete-matcher)
|
|
48
51
|
- [FAQ](#faq)
|
|
49
52
|
- [Why do I have to set all expectations first?](#why-do-i-have-to-set-all-expectations-first)
|
|
50
|
-
- [Can I mock an existing object/function?](#can-i-mock-an-existing-objectfunction)
|
|
53
|
+
- [Can I partially mock an existing object/function?](#can-i-partially-mock-an-existing-objectfunction)
|
|
51
54
|
- [How do I set expectations on setters?](#how-do-i-set-expectations-on-setters)
|
|
52
55
|
- [Why do I have to set a return value even if it's `undefined`?](#why-do-i-have-to-set-a-return-value-even-if-its-undefined)
|
|
53
56
|
- [How do I provide a function for the mock to call?](#how-do-i-provide-a-function-for-the-mock-to-call)
|
|
54
|
-
- [Why does accessing an unused method throw?](#why-does-accessing-an-unused-method-throw)
|
|
55
57
|
- [Can I spread/enumerate a mock?](#can-i-spreadenumerate-a-mock)
|
|
56
58
|
- [How can I ignore `undefined` keys when setting expectations on objects?](#how-can-i-ignore-undefined-keys-when-setting-expectations-on-objects)
|
|
57
59
|
|
|
@@ -61,29 +63,39 @@ console.log(foo.bar(23)); // 'I am strong!'
|
|
|
61
63
|
|
|
62
64
|
### Type safety
|
|
63
65
|
|
|
64
|
-
The
|
|
66
|
+
The mock expectations will share the same type guarantees as your production code, and you can safely refactor in an IDE knowing that all usages will be updated.
|
|
65
67
|
|
|
66
|
-

|
|
67
69
|
|
|
68
70
|
### Useful error messages
|
|
69
71
|
|
|
70
72
|
Error messages include the property that has been accessed, any arguments passed to it and any remaining unmet expectations.
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
```typescript
|
|
75
|
+
import { mock, when } from 'strong-mock';
|
|
76
|
+
|
|
77
|
+
const fn = mock<(a: number, b: number, c: number) => number>();
|
|
78
|
+
|
|
79
|
+
when(() => fn(1, 2, 3)).thenReturn(42);
|
|
80
|
+
|
|
81
|
+
fn(4, 5, 6);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+

|
|
73
85
|
|
|
74
86
|
### Type safe argument matchers
|
|
75
87
|
|
|
76
|
-
|
|
88
|
+
You can use argument matchers to partially match values, or create complex expectations, while still maintaining type safety.
|
|
77
89
|
|
|
78
|
-

|
|
79
91
|
|
|
80
92
|
## Installation
|
|
81
93
|
|
|
82
|
-
```
|
|
94
|
+
```shell
|
|
83
95
|
npm i -D strong-mock
|
|
84
96
|
```
|
|
85
97
|
|
|
86
|
-
```
|
|
98
|
+
```shell
|
|
87
99
|
yarn add -D strong-mock
|
|
88
100
|
```
|
|
89
101
|
|
|
@@ -113,11 +125,9 @@ console.log(foo.bar(23)); // awesome
|
|
|
113
125
|
console.log(foo.bar(23)); // even more awesome
|
|
114
126
|
```
|
|
115
127
|
|
|
116
|
-
By default, each call is expected to be called only once. You can expect a call to be made multiple times using the [invocation count](#setting-invocation-count-expectations) helpers.
|
|
117
|
-
|
|
118
128
|
### Setting invocation count expectations
|
|
119
129
|
|
|
120
|
-
You can expect a call to be made multiple times by using the invocation count helpers `between`, `atLeast`, `times`, `anyTimes` etc.:
|
|
130
|
+
By default, each call is expected to be called only once. You can expect a call to be made multiple times by using the invocation count helpers `between`, `atLeast`, `times`, `anyTimes` etc.:
|
|
121
131
|
|
|
122
132
|
```typescript
|
|
123
133
|
const fn = mock<(x: number) => number>();
|
|
@@ -130,6 +140,8 @@ console.log(fn(1)); // 1
|
|
|
130
140
|
console.log(fn(1)); // throws because the expectation is finished
|
|
131
141
|
```
|
|
132
142
|
|
|
143
|
+
You'll notice there is no `never()` helper - if you expect a call to not be made simply don't set an expectation on it and the mock will throw if the call happens.
|
|
144
|
+
|
|
133
145
|
### Mocking interfaces
|
|
134
146
|
|
|
135
147
|
Pass in the interface to the generic argument of `mock`:
|
|
@@ -149,8 +161,6 @@ console.log(foo.bar(23)); // 'awesome'
|
|
|
149
161
|
console.log(foo.baz); // 100
|
|
150
162
|
```
|
|
151
163
|
|
|
152
|
-
Since the mock is type safe the compiler will guarantee that you're only mocking things that actually exist on the interface.
|
|
153
|
-
|
|
154
164
|
### Mocking functions
|
|
155
165
|
|
|
156
166
|
You can also mock functions similarly to interfaces:
|
|
@@ -192,18 +202,16 @@ when(() => fn(1)).thenThrow();
|
|
|
192
202
|
when(() => fnWithPromise(1)).thenReject();
|
|
193
203
|
```
|
|
194
204
|
|
|
195
|
-
You'll notice there is no `never()` helper - if you expect a call to not be made simply don't set an expectation on it and the mock will throw if the call happens.
|
|
196
|
-
|
|
197
205
|
### Verifying expectations
|
|
198
206
|
|
|
199
|
-
Calling `verify(
|
|
207
|
+
Calling `verify(myMock)` will make sure that all expectations set on the mock have been met, and that no additional calls have been made.
|
|
200
208
|
|
|
201
209
|
```typescript
|
|
202
210
|
const fn = mock<(x: number) => number>();
|
|
203
211
|
|
|
204
212
|
when(() => fn(1)).thenReturn(1).between(2, 10);
|
|
205
213
|
|
|
206
|
-
verify(fn); // throws
|
|
214
|
+
verify(fn); // throws UnmetExpectations
|
|
207
215
|
```
|
|
208
216
|
|
|
209
217
|
It will also throw if any unexpected calls happened that were maybe caught in the code under test.
|
|
@@ -217,10 +225,16 @@ try {
|
|
|
217
225
|
// your code might transition to an error state here
|
|
218
226
|
}
|
|
219
227
|
|
|
220
|
-
verify(fn); // throws
|
|
228
|
+
verify(fn); // throws UnexpectedCalls
|
|
221
229
|
```
|
|
222
230
|
|
|
223
|
-
It is recommended that you call `verify()` on your mocks at the end of every test. This will make sure you don't have any unused expectations in your tests and that your code did not silently catch any of the errors that are thrown when an unexpected call happens. You can use `verifyAll()` to check all existing mocks
|
|
231
|
+
It is recommended that you call `verify()` on your mocks at the end of every test. This will make sure you don't have any unused expectations in your tests and that your code did not silently catch any of the errors that are thrown when an unexpected call happens. You can use `verifyAll()` to check all existing mocks.
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
afterEach(() => {
|
|
235
|
+
verifyAll();
|
|
236
|
+
})
|
|
237
|
+
```
|
|
224
238
|
|
|
225
239
|

|
|
226
240
|
|
|
@@ -238,11 +252,17 @@ reset(fn);
|
|
|
238
252
|
fn(1); // throws
|
|
239
253
|
```
|
|
240
254
|
|
|
241
|
-
If you create common mocks that are shared by multiple tests you should reset them before
|
|
255
|
+
If you create common mocks that are shared by multiple tests you should reset them before each test. You can use `resetAll()` to reset all existing mocks.
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
beforeEach(() => {
|
|
259
|
+
resetAll();
|
|
260
|
+
})
|
|
261
|
+
```
|
|
242
262
|
|
|
243
263
|
### Argument matchers
|
|
244
264
|
|
|
245
|
-
Sometimes you're not interested in specifying all the arguments in an expectation. Maybe they've been covered in another test, maybe they're hard to specify e.g. callbacks
|
|
265
|
+
Sometimes you're not interested in specifying all the arguments in an expectation. Maybe they've been covered in another test, maybe they're hard to specify e.g. callbacks, or maybe you want to match just a property from an argument.
|
|
246
266
|
|
|
247
267
|
```typescript
|
|
248
268
|
const fn = mock<
|
|
@@ -260,6 +280,12 @@ console.log(fn(
|
|
|
260
280
|
); // 'matched!'
|
|
261
281
|
```
|
|
262
282
|
|
|
283
|
+
You can mix argument matchers with concrete arguments:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
when(() => fn(42, It.isObject())).thenReturn('matched');
|
|
287
|
+
```
|
|
288
|
+
|
|
263
289
|
Available matchers:
|
|
264
290
|
- `deepEquals` - the default, uses deep equality,
|
|
265
291
|
- `is` - uses `Object.is` for comparison,
|
|
@@ -275,7 +301,7 @@ The following table illustrates the differences between the equality matchers:
|
|
|
275
301
|
|
|
276
302
|
| expected | actual | `It.is` | `It.deepEquals` | `It.deepEquals({ strict: false })` |
|
|
277
303
|
|--------------------|----------------------|-----------|-----------------|------------------------------------|
|
|
278
|
-
| `"foo"` | `"
|
|
304
|
+
| `"foo"` | `"foo"` | equal | equal | equal |
|
|
279
305
|
| `{ foo: "bar" }` | `{ foo: "bar" }` | not equal | equal | equal |
|
|
280
306
|
| `{ }` | `{ foo: undefined }` | not equal | not equal | equal |
|
|
281
307
|
| `new (class {})()` | `new (class {})()` | not equal | not equal | equal |
|
|
@@ -315,22 +341,100 @@ console.log(fn(23, (x) => x + 1)); // 42
|
|
|
315
341
|
console.log(matcher.value?.(3)); // 4
|
|
316
342
|
```
|
|
317
343
|
|
|
318
|
-
|
|
344
|
+
## Mock options
|
|
319
345
|
|
|
320
|
-
|
|
346
|
+
The following options can be set per mock, or globally with `setDefaults`.
|
|
321
347
|
|
|
322
|
-
```
|
|
323
|
-
import { mock, when,
|
|
348
|
+
```typescript
|
|
349
|
+
import { mock, when, setDefaults } from 'strong-mock';
|
|
324
350
|
|
|
325
|
-
// Use strict equality instead of deep equality.
|
|
326
351
|
setDefaults({
|
|
327
|
-
|
|
328
|
-
})
|
|
352
|
+
exactParams: true
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Uses the new default.
|
|
356
|
+
const superStrictMock = mock<() => void>();
|
|
357
|
+
// Overrides the default.
|
|
358
|
+
const strictMock = mock<() => void>({ exactParams: false });
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Unexpected property return value
|
|
362
|
+
|
|
363
|
+
You can control what happens whenever an unexpected property is accessed, or an unexpected call is made.
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
import { mock, when, UnexpectedProperty } from 'strong-mock';
|
|
367
|
+
|
|
368
|
+
type Foo = {
|
|
369
|
+
bar: (value: number) => number;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// This is the default.
|
|
373
|
+
const callsThrow = mock<Foo>({
|
|
374
|
+
unexpectedProperty: UnexpectedProperty.CALL_THROW
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// Accessing properties with no expectations is fine.
|
|
378
|
+
callsThrow.bar;
|
|
379
|
+
// Throws "Didn't expect bar(42) to be called".
|
|
380
|
+
callsThrow.bar(42);
|
|
381
|
+
|
|
382
|
+
const propertiesThrow = mock<Foo>({
|
|
383
|
+
unexpectedProperty: UnexpectedProperty.THROW
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// Throws "Didn't expect property bar to be accessed".
|
|
387
|
+
propertiesThrow.bar;
|
|
388
|
+
// Throws "Didn't expect property bar to be accessed".
|
|
389
|
+
propertiesThrow.bar(42);
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Exact params
|
|
329
393
|
|
|
330
|
-
|
|
394
|
+
By default, function/method expectations will allow more arguments to be received than expected. Since the expectations are type safe, the TypeScript compiler will never allow expecting less arguments than required. Unspecified optional arguments will be considered ignored, as if they've been replaced with [argument matchers](#argument-matchers).
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
import { mock } from 'strong-mock';
|
|
398
|
+
|
|
399
|
+
const fn = mock<(value?: number) => number>();
|
|
400
|
+
|
|
401
|
+
when(() => fn()).thenReturn(42).twice();
|
|
402
|
+
|
|
403
|
+
// Since the expectation doesn't expect any arguments,
|
|
404
|
+
// both of the following are fine
|
|
405
|
+
console.log(fn()); // 42
|
|
406
|
+
console.log(fn(1)); // 42
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
If you're not using TypeScript, or you want to be super strict, you can set `exactParams: true`.
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
import { mock } from 'strong-mock';
|
|
413
|
+
|
|
414
|
+
const fn = mock<(optionalValue?: number) => number>({
|
|
415
|
+
exactParams: true
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
when(() => fn()).thenReturn(42).twice();
|
|
419
|
+
|
|
420
|
+
console.log(fn()); // 42
|
|
421
|
+
console.log(fn(1)); // throws
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Concrete matcher
|
|
425
|
+
|
|
426
|
+
You can set the matcher that will be used in expectations with concrete values e.g. `42` or `{ foo: "bar" }`. Passing in a [matcher argument](#argument-matchers) will always take priority.
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
import { mock, when, It } from 'strong-mock';
|
|
430
|
+
|
|
431
|
+
// Use strict equality instead of deep equality.
|
|
432
|
+
const fn = mock<(x: number[]) => boolean>({
|
|
433
|
+
concreteMatcher: It.is
|
|
434
|
+
});
|
|
331
435
|
when(() => fn([1, 2, 3])).thenReturn(true);
|
|
332
436
|
|
|
333
|
-
fn([1, 2, 3]); // throws because different
|
|
437
|
+
fn([1, 2, 3]); // throws because different array instances
|
|
334
438
|
```
|
|
335
439
|
|
|
336
440
|
## FAQ
|
|
@@ -341,11 +445,11 @@ This library is different from other mocking/spying libraries you might have use
|
|
|
341
445
|
|
|
342
446
|
This design decision has a few reasons behind it. First, it forces you to be aware of what your code needs from its dependencies. Spying libraries encourage checking those needs at the end of the test after the code has already called the mocks. This can lead to tests missing dependency calls that just happen to not throw any error at runtime with the dummy values that the spies return.
|
|
343
447
|
|
|
344
|
-
Secondly, it will highlight potential design problems such as violations of the SOLID principles. If you find yourself duplicating expectations between tests and passing dummy values to them because your test is not concerned with them then you might want to look into splitting the code to only depend on things it really needs.
|
|
448
|
+
Secondly, it will highlight potential design problems such as violations of the SOLID principles. If you find yourself duplicating expectations between tests and passing dummy values to them because your test is not concerned with them, then you might want to look into splitting the code to only depend on things it really needs.
|
|
345
449
|
|
|
346
|
-
### Can I mock an existing object/function?
|
|
450
|
+
### Can I partially mock an existing object/function?
|
|
347
451
|
|
|
348
|
-
No,
|
|
452
|
+
No, passing a concrete implementation to `mock()` will be the same as passing a type: all properties will be mocked, and you have to set expectations on the ones that will be accessed.
|
|
349
453
|
|
|
350
454
|
### How do I set expectations on setters?
|
|
351
455
|
|
|
@@ -353,7 +457,7 @@ You currently can't do that. Please use a normal method instead e.g. `setFoo()`
|
|
|
353
457
|
|
|
354
458
|
### Why do I have to set a return value even if it's `undefined`?
|
|
355
459
|
|
|
356
|
-
To make side effects explicit and to prevent future refactoring headaches. If you had just `when(() => fn())
|
|
460
|
+
To make side effects explicit and to prevent future refactoring headaches. If you had just `when(() => fn())`, and you later changed `fn()` to return a `number`, then your expectation would become incorrect and the compiler couldn't check that for you.
|
|
357
461
|
|
|
358
462
|
### How do I provide a function for the mock to call?
|
|
359
463
|
|
|
@@ -373,54 +477,6 @@ console.log(foo.bar(23)); // 'called 23'
|
|
|
373
477
|
|
|
374
478
|
The function in `thenReturn()` will be type checked against the actual interface, so you can make sure you're passing in an implementation that makes sense. Moreover, refactoring the interface will also refactor the expectation (in a capable IDE).
|
|
375
479
|
|
|
376
|
-

|
|
377
|
-
|
|
378
|
-
### Why does accessing an unused method throw?
|
|
379
|
-
|
|
380
|
-
Any unexpected property access will throw an error, even if the property is a method, and you never call it. This can sometimes be inconvenient if your code e.g. destructures your mock and only calls parts of it inside your test.
|
|
381
|
-
|
|
382
|
-
```typescript
|
|
383
|
-
interface Foo {
|
|
384
|
-
bar: () => number;
|
|
385
|
-
baz: () => number;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function doFoo(foo: Foo, { callBaz }: { callBaz: boolean }) {
|
|
389
|
-
// Will throw here with unexpected access on `baz`.
|
|
390
|
-
const { bar, baz } = foo;
|
|
391
|
-
|
|
392
|
-
bar();
|
|
393
|
-
|
|
394
|
-
if (callBaz) {
|
|
395
|
-
baz();
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
const foo = mock<Foo>();
|
|
400
|
-
when(() => foo.bar()).thenReturn(42);
|
|
401
|
-
|
|
402
|
-
// Throws with unexpected access on `baz`.
|
|
403
|
-
doFoo(foo, { callBaz: false });
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
To work around this, either change your code to avoid destructuring
|
|
407
|
-
|
|
408
|
-
```typescript
|
|
409
|
-
function doFoo(foo: Foo, callBaz: boolean) {
|
|
410
|
-
foo.bar();
|
|
411
|
-
|
|
412
|
-
if (callBaz) {
|
|
413
|
-
foo.baz();
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
or set a dummy expectation on the methods you're not interested in during the test.
|
|
419
|
-
|
|
420
|
-
```typescript
|
|
421
|
-
when(() => foo.baz()).thenThrow('should not be called').anyTimes();
|
|
422
|
-
```
|
|
423
|
-
|
|
424
480
|
### Can I spread/enumerate a mock?
|
|
425
481
|
|
|
426
482
|
Yes, and you will only get the properties that have expectations on them.
|
|
@@ -437,7 +493,6 @@ console.log(foo2.bar); // 42
|
|
|
437
493
|
console.log(foo2.baz); // undefined
|
|
438
494
|
```
|
|
439
495
|
|
|
440
|
-
|
|
441
496
|
### How can I ignore `undefined` keys when setting expectations on objects?
|
|
442
497
|
|
|
443
498
|
Use the `It.deepEquals` matcher explicitly inside `when` and pass `{ strict: false }`:
|
|
@@ -445,15 +500,17 @@ Use the `It.deepEquals` matcher explicitly inside `when` and pass `{ strict: fal
|
|
|
445
500
|
```ts
|
|
446
501
|
const fn = mock<(x: { foo: string }) => boolean>();
|
|
447
502
|
|
|
448
|
-
when(() => fn(
|
|
503
|
+
when(() => fn(
|
|
504
|
+
It.deepEquals({ foo: "bar" }, { strict: false }))
|
|
505
|
+
).thenReturn(true);
|
|
449
506
|
|
|
450
507
|
fn({ foo: "bar", baz: undefined }) === true
|
|
451
508
|
```
|
|
452
509
|
|
|
453
|
-
You can
|
|
510
|
+
You can set this behavior to be the default by configuring the [concrete matcher](#concrete-matcher).
|
|
454
511
|
|
|
455
512
|
```ts
|
|
456
513
|
setDefaults({
|
|
457
|
-
|
|
514
|
+
concreteMatcher: (expected) => It.deepEquals(expected, { strict: false })
|
|
458
515
|
});
|
|
459
516
|
```
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Expectation } from './expectation/expectation';
|
|
2
|
-
import { CallMap } from './expectation/repository/expectation-repository';
|
|
3
|
-
import { Property } from './proxy';
|
|
4
|
-
import { PendingExpectation } from './when/pending-expectation';
|
|
1
|
+
import type { Expectation } from './expectation/expectation';
|
|
2
|
+
import type { CallMap } from './expectation/repository/expectation-repository';
|
|
3
|
+
import type { Property } from './proxy';
|
|
4
|
+
import type { PendingExpectation } from './when/pending-expectation';
|
|
5
5
|
export declare class UnfinishedExpectation extends Error {
|
|
6
6
|
constructor(pendingExpectation: PendingExpectation);
|
|
7
7
|
}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import { Property } from '../proxy';
|
|
2
|
-
import { Matcher } from './matcher';
|
|
3
|
-
|
|
4
|
-
value: any;
|
|
5
|
-
isPromise?: boolean;
|
|
6
|
-
isError?: boolean;
|
|
7
|
-
};
|
|
1
|
+
import type { Property } from '../proxy';
|
|
2
|
+
import type { Matcher } from './matcher';
|
|
3
|
+
import type { ReturnValue } from './repository/return-value';
|
|
8
4
|
/**
|
|
9
5
|
* Compare received arguments against matchers.
|
|
10
6
|
*/
|
package/dist/expectation/it.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { Property } from '../../proxy';
|
|
2
|
+
import type { Expectation } from '../expectation';
|
|
3
3
|
export declare type Call = {
|
|
4
4
|
arguments: any[] | undefined;
|
|
5
5
|
};
|
|
@@ -31,7 +31,7 @@ export interface ExpectationRepository {
|
|
|
31
31
|
/**
|
|
32
32
|
* Get a return value for the given property.
|
|
33
33
|
*
|
|
34
|
-
* The value might be a non-callable e.g. a number or a string or it might
|
|
34
|
+
* The value might be a non-callable e.g. a number or a string, or it might
|
|
35
35
|
* be a function that, upon receiving arguments, will start a new search and
|
|
36
36
|
* return a value again.
|
|
37
37
|
*
|
|
@@ -41,17 +41,32 @@ export interface ExpectationRepository {
|
|
|
41
41
|
*
|
|
42
42
|
* @example
|
|
43
43
|
* add(new Expectation('getData', [1, 2], 23);
|
|
44
|
-
* get('getData')
|
|
44
|
+
* get('getData')(1, 2) === 23
|
|
45
45
|
*
|
|
46
46
|
* @example
|
|
47
47
|
* add(new Expectation('hasData', undefined, true);
|
|
48
|
-
* get('hasData')
|
|
48
|
+
* get('hasData') === true
|
|
49
49
|
*
|
|
50
50
|
* @example
|
|
51
51
|
* add(new Expectation('getData', undefined, () => 42);
|
|
52
|
-
* get('getData')
|
|
52
|
+
* get('getData')(1, 2, '3', false, NaN) === 42
|
|
53
53
|
*/
|
|
54
|
-
get(property: Property):
|
|
54
|
+
get(property: Property): unknown;
|
|
55
|
+
/**
|
|
56
|
+
* Get a return value for a function call.
|
|
57
|
+
*
|
|
58
|
+
* Note: this will only be invoked if the mocked type is a function. For
|
|
59
|
+
* method property calls {@link get} will be called instead.
|
|
60
|
+
*
|
|
61
|
+
* The list of expectations should be consulted from first to last when
|
|
62
|
+
* getting a return value. If none of them match it is up to the
|
|
63
|
+
* implementation to decide what to do.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* add(new Expectation(ApplyProp, [1, 2], 23);
|
|
67
|
+
* apply(1, 2) === 23
|
|
68
|
+
*/
|
|
69
|
+
apply(args: unknown[]): unknown;
|
|
55
70
|
/**
|
|
56
71
|
* Get all the properties that have expectations.
|
|
57
72
|
*
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { UnexpectedProperty } from '../../mock/options';
|
|
2
|
+
import type { Property } from '../../proxy';
|
|
3
|
+
import type { Expectation } from '../expectation';
|
|
4
|
+
import type { CallMap, ExpectationRepository } from './expectation-repository';
|
|
5
|
+
declare type CountableExpectation = {
|
|
6
|
+
expectation: Expectation;
|
|
7
|
+
matchCount: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* An expectation repository with a configurable behavior for
|
|
11
|
+
* unexpected property access.
|
|
12
|
+
*/
|
|
13
|
+
export declare class FlexibleRepository implements ExpectationRepository {
|
|
14
|
+
private unexpectedProperty;
|
|
15
|
+
constructor(unexpectedProperty?: UnexpectedProperty);
|
|
16
|
+
protected readonly expectations: Map<Property, CountableExpectation[]>;
|
|
17
|
+
private readonly expectedCallStats;
|
|
18
|
+
private readonly unexpectedCallStats;
|
|
19
|
+
add(expectation: Expectation): void;
|
|
20
|
+
clear(): void;
|
|
21
|
+
apply: (args: unknown[]) => unknown;
|
|
22
|
+
get(property: Property): any;
|
|
23
|
+
private handlePropertyWithMatchingExpectations;
|
|
24
|
+
private handlePropertyWithNoExpectations;
|
|
25
|
+
getAllProperties(): Property[];
|
|
26
|
+
getCallStats(): {
|
|
27
|
+
expected: CallMap;
|
|
28
|
+
unexpected: CallMap;
|
|
29
|
+
};
|
|
30
|
+
getUnmet(): Expectation[];
|
|
31
|
+
private recordExpected;
|
|
32
|
+
private recordUnexpected;
|
|
33
|
+
private countAndConsume;
|
|
34
|
+
private consumeExpectation;
|
|
35
|
+
private getValueForUnexpectedCall;
|
|
36
|
+
private getValueForUnexpectedAccess;
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare type ReturnValue = {
|
|
2
|
+
value: any;
|
|
3
|
+
isPromise?: boolean;
|
|
4
|
+
isError?: boolean;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Unbox the expectation's return value.
|
|
8
|
+
*
|
|
9
|
+
* If the value is an error then throw it.
|
|
10
|
+
*
|
|
11
|
+
* If the value is a promise then resolve/reject it.
|
|
12
|
+
*/
|
|
13
|
+
export declare const unboxReturnValue: ({ isError, isPromise, value, }: ReturnValue) => any;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Property } from '../proxy';
|
|
2
|
-
import { Expectation
|
|
3
|
-
import { Matcher } from './matcher';
|
|
1
|
+
import type { Property } from '../proxy';
|
|
2
|
+
import type { Expectation } from './expectation';
|
|
3
|
+
import type { Matcher } from './matcher';
|
|
4
|
+
import type { ReturnValue } from './repository/return-value';
|
|
4
5
|
/**
|
|
5
6
|
* Matches a call with more parameters than expected because it is assumed the
|
|
6
7
|
* compiler will check that those parameters are optional.
|
|
@@ -16,10 +17,11 @@ export declare class StrongExpectation implements Expectation {
|
|
|
16
17
|
property: Property;
|
|
17
18
|
args: Matcher[] | undefined;
|
|
18
19
|
returnValue: ReturnValue;
|
|
20
|
+
private exactParams;
|
|
19
21
|
private matched;
|
|
20
22
|
min: number;
|
|
21
23
|
max: number;
|
|
22
|
-
constructor(property: Property, args: Matcher[] | undefined, returnValue: ReturnValue);
|
|
24
|
+
constructor(property: Property, args: Matcher[] | undefined, returnValue: ReturnValue, exactParams?: boolean);
|
|
23
25
|
setInvocationCount(min: number, max?: number): void;
|
|
24
26
|
matches(args: any[] | undefined): boolean;
|
|
25
27
|
isUnmet(): boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export { verify, verifyAll } from './verify/verify';
|
|
|
5
5
|
export { It } from './expectation/it';
|
|
6
6
|
export { setDefaults } from './mock/defaults';
|
|
7
7
|
export type { Matcher } from './expectation/matcher';
|
|
8
|
-
export type {
|
|
8
|
+
export type { MockOptions } from './mock/options';
|
|
9
|
+
export { UnexpectedProperty } from './mock/options';
|