@plugjs/expect5 0.4.6 → 0.4.8

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.
Files changed (55) hide show
  1. package/dist/cli.mjs +6 -1
  2. package/dist/cli.mjs.map +1 -1
  3. package/dist/execution/executable.mjs +6 -0
  4. package/dist/execution/executable.mjs.map +1 -1
  5. package/dist/execution/executor.mjs +6 -0
  6. package/dist/execution/executor.mjs.map +1 -1
  7. package/dist/execution/setup.mjs +6 -0
  8. package/dist/execution/setup.mjs.map +1 -1
  9. package/dist/expectation/async.cjs +14 -22
  10. package/dist/expectation/async.cjs.map +1 -1
  11. package/dist/expectation/async.d.ts +39 -13
  12. package/dist/expectation/async.mjs +20 -22
  13. package/dist/expectation/async.mjs.map +1 -1
  14. package/dist/expectation/diff.mjs +6 -0
  15. package/dist/expectation/diff.mjs.map +1 -1
  16. package/dist/expectation/expect.cjs +3 -3
  17. package/dist/expectation/expect.cjs.map +1 -1
  18. package/dist/expectation/expect.d.ts +3 -3
  19. package/dist/expectation/expect.mjs +10 -4
  20. package/dist/expectation/expect.mjs.map +1 -1
  21. package/dist/expectation/expectations.cjs +27 -44
  22. package/dist/expectation/expectations.cjs.map +1 -1
  23. package/dist/expectation/expectations.d.ts +72 -14
  24. package/dist/expectation/expectations.mjs +33 -44
  25. package/dist/expectation/expectations.mjs.map +1 -1
  26. package/dist/expectation/include.mjs +6 -0
  27. package/dist/expectation/include.mjs.map +1 -1
  28. package/dist/expectation/matchers.cjs +24 -47
  29. package/dist/expectation/matchers.cjs.map +1 -1
  30. package/dist/expectation/matchers.d.ts +136 -93
  31. package/dist/expectation/matchers.mjs +29 -46
  32. package/dist/expectation/matchers.mjs.map +1 -1
  33. package/dist/expectation/print.cjs +4 -0
  34. package/dist/expectation/print.cjs.map +1 -1
  35. package/dist/expectation/print.mjs +11 -1
  36. package/dist/expectation/print.mjs.map +1 -1
  37. package/dist/expectation/types.cjs.map +1 -1
  38. package/dist/expectation/types.d.ts +2 -2
  39. package/dist/expectation/types.mjs +6 -0
  40. package/dist/expectation/types.mjs.map +1 -1
  41. package/dist/globals.mjs +5 -0
  42. package/dist/index.mjs +6 -0
  43. package/dist/index.mjs.map +1 -1
  44. package/dist/test.cjs +17 -7
  45. package/dist/test.cjs.map +1 -1
  46. package/dist/test.mjs +25 -9
  47. package/dist/test.mjs.map +1 -1
  48. package/package.json +3 -3
  49. package/src/expectation/async.ts +69 -17
  50. package/src/expectation/expect.ts +6 -6
  51. package/src/expectation/expectations.ts +152 -27
  52. package/src/expectation/matchers.ts +207 -125
  53. package/src/expectation/print.ts +7 -1
  54. package/src/expectation/types.ts +2 -2
  55. package/src/test.ts +29 -8
@@ -2,8 +2,10 @@ import {
2
2
  Expectations,
3
3
  type AssertedType,
4
4
  type AssertionFunction,
5
+ type ExpectationsParent,
6
+ type InferMatcher,
7
+ type InferToEqual,
5
8
  type NegativeExpectations,
6
- type InferMatchers,
7
9
  } from './expectations'
8
10
  import {
9
11
  matcherMarker,
@@ -12,33 +14,33 @@ import {
12
14
  type TypeName,
13
15
  } from './types'
14
16
 
15
- type Matcher = (expectations: Expectations) => Expectations
16
- type NegativeMatcher = (expectations: NegativeExpectations) => Expectations
17
+ type PositiveMatcherFunction = (expectations: Expectations) => Expectations
18
+ type NegativeMatcherFunction = (expectations: NegativeExpectations) => Expectations
17
19
 
18
20
  /* ========================================================================== *
19
- * EXPECTATIONS *
21
+ * MATCHERS *
20
22
  * ========================================================================== */
21
23
 
22
- export class Matchers<T = unknown> {
23
- private readonly _matchers: Matcher[]
24
+ export class Matcher<T = unknown> {
25
+ private readonly _matchers: PositiveMatcherFunction[]
24
26
  readonly not: NegativeMatchers<T>
25
27
 
26
28
  constructor() {
27
- const matchers: Matcher[] = []
29
+ const matchers: PositiveMatcherFunction[] = []
28
30
  this.not = new NegativeMatchers(this, matchers)
29
31
  this._matchers = matchers
30
32
  }
31
33
 
32
- expect(value: unknown): T {
33
- let expectations = new Expectations(value, undefined)
34
+ expect(value: unknown, parent?: ExpectationsParent): T {
35
+ let expectations = new Expectations(value, undefined, parent)
34
36
  for (const matcher of this._matchers) {
35
37
  expectations = matcher(expectations)
36
38
  }
37
39
  return expectations.value as T
38
40
  }
39
41
 
40
- private _push(matcher: Matcher): Matchers<any> {
41
- const matchers = new Matchers()
42
+ private _push(matcher: PositiveMatcherFunction): Matcher<any> {
43
+ const matchers = new Matcher()
42
44
  matchers._matchers.push(...this._matchers, matcher)
43
45
  return matchers
44
46
  }
@@ -52,20 +54,47 @@ export class Matchers<T = unknown> {
52
54
  * ------------------------------------------------------------------------ */
53
55
 
54
56
  /**
55
- * Expects the value to be of the specified _extended_ {@link TypeName type},
56
- * and (if specified) further asserts it with an {@link AssertionFunction}.
57
+ * Expects the value to be of the specified _extended_ {@link TypeName type}.
57
58
  *
58
- * Negation: {@link NegativeMatchers.toBeA `not.toBeA(...)`}
59
+ * Negation: {@link NegativeExpectations.toBeA `not.toBeA(...)`}
59
60
  */
61
+ toBeA<Name extends TypeName>(type: Name): Matcher<TypeMappings[Name]>
62
+
63
+ /**
64
+ * Expects the value to be of the specified _extended_ {@link TypeName type},
65
+ * and further validates it with a {@link Matcher}.
66
+ *
67
+ * Negation: {@link NegativeExpectations.toBeA `not.toBeA(...)`}
68
+ */
69
+ toBeA<
70
+ Name extends TypeName,
71
+ Mapped extends TypeMappings[Name],
72
+ Match extends Matcher,
73
+ >(
74
+ type: Name,
75
+ matcher: Match,
76
+ ): Matcher<InferMatcher<Mapped, Match>>
77
+
78
+ /**
79
+ * Expects the value to be of the specified _extended_ {@link TypeName type},
80
+ * and further asserts it with an {@link AssertionFunction}.
81
+ *
82
+ * Negation: {@link NegativeExpectations.toBeA `not.toBeA(...)`}
83
+ */
60
84
  toBeA<
61
85
  Name extends TypeName,
62
86
  Mapped extends TypeMappings[Name],
63
87
  Assert extends AssertionFunction<Mapped>,
64
88
  >(
65
- type: Name,
66
- assertion?: Assert,
67
- ): Matchers<AssertedType<Mapped, Assert>> {
68
- return this._push((e) => e.toBeA(type, assertion as AssertionFunction))
89
+ type: Name,
90
+ assertion: Assert,
91
+ ): Matcher<AssertedType<Mapped, Assert>>
92
+
93
+ toBeA(
94
+ type: TypeName,
95
+ assertionOrMatcher?: AssertionFunction | Matcher,
96
+ ): Matcher {
97
+ return this._push((e) => e.toBeA(type, assertionOrMatcher as any))
69
98
  }
70
99
 
71
100
  /* ------------------------------------------------------------------------ */
@@ -76,7 +105,7 @@ export class Matchers<T = unknown> {
76
105
  *
77
106
  * Negation: {@link NegativeMatchers.toBeCloseTo `not.toBeCloseTo(...)`}
78
107
  */
79
- toBeCloseTo(value: number, delta: number): Matchers<number>
108
+ toBeCloseTo(value: number, delta: number): Matcher<number>
80
109
 
81
110
  /**
82
111
  * Expects the value to be a `bigint` within a given +/- _delta_ range of the
@@ -84,7 +113,7 @@ export class Matchers<T = unknown> {
84
113
  *
85
114
  * Negation: {@link NegativeMatchers.toBeCloseTo `not.toBeCloseTo(...)`}
86
115
  */
87
- toBeCloseTo(value: bigint, delta: bigint): Matchers<bigint>
116
+ toBeCloseTo(value: bigint, delta: bigint): Matcher<bigint>
88
117
 
89
118
  /**
90
119
  * Expects the value to be a `number` or `bigint` within a given +/- _delta_
@@ -95,7 +124,7 @@ export class Matchers<T = unknown> {
95
124
  toBeCloseTo(
96
125
  value: number | bigint,
97
126
  delta: number | bigint,
98
- ): Matchers {
127
+ ): Matcher {
99
128
  return this._push((e) => e.toBeCloseTo(value as number, delta as number))
100
129
  }
101
130
 
@@ -106,7 +135,7 @@ export class Matchers<T = unknown> {
106
135
  *
107
136
  * Negation: {@link NegativeMatchers.toBeDefined `not.toBeDefined()`}
108
137
  */
109
- toBeDefined(): Matchers<T> {
138
+ toBeDefined(): Matcher<T> {
110
139
  return this._push((e) => e.toBeDefined())
111
140
  }
112
141
 
@@ -121,7 +150,7 @@ export class Matchers<T = unknown> {
121
150
  */
122
151
  toBeError(
123
152
  message?: string | RegExp
124
- ): Matchers<Error>
153
+ ): Matcher<Error>
125
154
 
126
155
  /**
127
156
  * Expect the value to be an instance of {@link Error} and further asserts
@@ -133,12 +162,12 @@ export class Matchers<T = unknown> {
133
162
  toBeError<Class extends Constructor<Error>>(
134
163
  constructor: Class,
135
164
  message?: string | RegExp,
136
- ): Matchers<InstanceType<Class>>
165
+ ): Matcher<InstanceType<Class>>
137
166
 
138
167
  toBeError(
139
168
  constructorOrMessage?: string | RegExp | Constructor,
140
169
  maybeMessage?: string | RegExp,
141
- ): Matchers {
170
+ ): Matcher {
142
171
  const [ constructor, message ] =
143
172
  typeof constructorOrMessage === 'function' ?
144
173
  [ constructorOrMessage, maybeMessage ] :
@@ -149,7 +178,7 @@ export class Matchers<T = unknown> {
149
178
  /* ------------------------------------------------------------------------ */
150
179
 
151
180
  /** Expects the value strictly equal to `false`. */
152
- toBeFalse(): Matchers<false> {
181
+ toBeFalse(): Matcher<false> {
153
182
  return this._push((e) => e.toBeFalse())
154
183
  }
155
184
 
@@ -158,9 +187,9 @@ export class Matchers<T = unknown> {
158
187
  /**
159
188
  * Expects the value to be _falsy_ (zero, empty string, `false`, ...).
160
189
  *
161
- * Negation: {@link Matchers.toBeTruthy `toBeTruthy()`}
190
+ * Negation: {@link Matcher.toBeTruthy `toBeTruthy()`}
162
191
  */
163
- toBeFalsy(): Matchers<T> {
192
+ toBeFalsy(): Matcher<T> {
164
193
  return this._push((e) => e.toBeFalsy())
165
194
  }
166
195
 
@@ -170,19 +199,19 @@ export class Matchers<T = unknown> {
170
199
  * Expects the value to be a `number` greater than the specified* expected
171
200
  * value.
172
201
  *
173
- * Negation: {@link Matchers.toBeLessThanOrEqual `toBeLessThanOrEqual(...)`}
202
+ * Negation: {@link Matcher.toBeLessThanOrEqual `toBeLessThanOrEqual(...)`}
174
203
  */
175
- toBeGreaterThan(value: number): Matchers<number>
204
+ toBeGreaterThan(value: number): Matcher<number>
176
205
 
177
206
  /**
178
207
  * Expects the value to be a `bigint` greater than the specified expected
179
208
  * value.
180
209
  *
181
- * Negation: {@link Matchers.toBeLessThanOrEqual `toBeLessThanOrEqual(...)`}
210
+ * Negation: {@link Matcher.toBeLessThanOrEqual `toBeLessThanOrEqual(...)`}
182
211
  */
183
- toBeGreaterThan(value: bigint): Matchers<bigint>
212
+ toBeGreaterThan(value: bigint): Matcher<bigint>
184
213
 
185
- toBeGreaterThan(value: number | bigint): Matchers {
214
+ toBeGreaterThan(value: number | bigint): Matcher {
186
215
  return this._push((e) => e.toBeGreaterThan(value as number))
187
216
  }
188
217
 
@@ -192,27 +221,47 @@ export class Matchers<T = unknown> {
192
221
  * Expects the value to be a `number` greater than or equal to the specified
193
222
  * expected value.
194
223
  *
195
- * Negation: {@link Matchers.toBeLessThan `toBeLessThan(...)`}
224
+ * Negation: {@link Matcher.toBeLessThan `toBeLessThan(...)`}
196
225
  */
197
- toBeGreaterThanOrEqual(value: number): Matchers<number>
226
+ toBeGreaterThanOrEqual(value: number): Matcher<number>
198
227
 
199
228
  /**
200
229
  * Expects the value to be a `bigint` greater than or equal to the specified
201
230
  * expected value.
202
231
  *
203
- * Negation: {@link Matchers.toBeLessThan `toBeLessThan(...)`}
232
+ * Negation: {@link Matcher.toBeLessThan `toBeLessThan(...)`}
204
233
  */
205
- toBeGreaterThanOrEqual(value: bigint): Matchers<bigint>
234
+ toBeGreaterThanOrEqual(value: bigint): Matcher<bigint>
206
235
 
207
- toBeGreaterThanOrEqual(value: number | bigint): Matchers {
236
+ toBeGreaterThanOrEqual(value: number | bigint): Matcher {
208
237
  return this._push((e) => e.toBeGreaterThanOrEqual(value as number))
209
238
  }
210
239
 
211
240
  /* ------------------------------------------------------------------------ */
212
241
 
242
+ /**
243
+ * Expects the value to be an instance of the specified {@link Constructor}.
244
+ *
245
+ * Negation: {@link NegativeMatchers.toBeInstanceOf `not.toInstanceOf(...)`}
246
+ */
247
+ toBeInstanceOf<Class extends Constructor>(
248
+ constructor: Class,
249
+ ): Matcher<InstanceType<Class>>
250
+
251
+ /**
252
+ * Expects the value to be an instance of the specified {@link Constructor},
253
+ * and further validates it with a {@link Matcher}.
254
+ *
255
+ * Negation: {@link NegativeMatchers.toBeInstanceOf `not.toInstanceOf(...)`}
256
+ */
257
+ toBeInstanceOf<Class extends Constructor, Match extends Matcher>(
258
+ constructor: Class,
259
+ matcher: Match,
260
+ ): Matcher<InferMatcher<InstanceType<Class>, Match>>
261
+
213
262
  /**
214
263
  * Expects the value to be an instance of the specified {@link Constructor},
215
- * and (if specified) further asserts it with an {@link AssertionFunction}.
264
+ * and further asserts it with an {@link AssertionFunction}.
216
265
  *
217
266
  * Negation: {@link NegativeMatchers.toBeInstanceOf `not.toInstanceOf(...)`}
218
267
  */
@@ -220,10 +269,15 @@ export class Matchers<T = unknown> {
220
269
  Class extends Constructor,
221
270
  Assert extends AssertionFunction<InstanceType<Class>>,
222
271
  >(
223
- constructor: Class,
224
- assertion?: Assert,
225
- ): Matchers<AssertedType<InstanceType<Class>, Assert>> {
226
- return this._push((e) => e.toBeInstanceOf(constructor, assertion as AssertionFunction))
272
+ constructor: Class,
273
+ assertion: Assert,
274
+ ): Matcher<AssertedType<InstanceType<Class>, Assert>>
275
+
276
+ toBeInstanceOf(
277
+ constructor: Constructor,
278
+ assertionOrMatcher?: AssertionFunction | Matcher,
279
+ ): Matcher {
280
+ return this._push((e) => e.toBeInstanceOf(constructor, assertionOrMatcher as any))
227
281
  }
228
282
 
229
283
  /* ------------------------------------------------------------------------ */
@@ -231,18 +285,18 @@ export class Matchers<T = unknown> {
231
285
  /**
232
286
  * Expects the value to be a `number` less than the specified expected value.
233
287
  *
234
- * Negation: {@link Matchers.toBeGreaterThanOrEqual `toBeGreaterThanOrEqual(...)`}
288
+ * Negation: {@link Matcher.toBeGreaterThanOrEqual `toBeGreaterThanOrEqual(...)`}
235
289
  */
236
- toBeLessThan(value: number): Matchers<number>
290
+ toBeLessThan(value: number): Matcher<number>
237
291
 
238
292
  /**
239
293
  * Expects the value to be a `bigint` less than the specified expected value.
240
294
  *
241
- * Negation: {@link Matchers.toBeGreaterThanOrEqual `toBeGreaterThanOrEqual(...)`}
295
+ * Negation: {@link Matcher.toBeGreaterThanOrEqual `toBeGreaterThanOrEqual(...)`}
242
296
  */
243
- toBeLessThan(value: bigint): Matchers<bigint>
297
+ toBeLessThan(value: bigint): Matcher<bigint>
244
298
 
245
- toBeLessThan(value: number | bigint): Matchers {
299
+ toBeLessThan(value: number | bigint): Matcher {
246
300
  return this._push((e) => e.toBeLessThan(value as number))
247
301
  }
248
302
 
@@ -252,19 +306,19 @@ export class Matchers<T = unknown> {
252
306
  * Expects the value to be a `number` less than or equal to* the specified
253
307
  * expected value.
254
308
  *
255
- * Negation: {@link Matchers.toBeGreaterThan `toBeGreaterThan(...)`}
309
+ * Negation: {@link Matcher.toBeGreaterThan `toBeGreaterThan(...)`}
256
310
  */
257
- toBeLessThanOrEqual(value: number): Matchers<number>
311
+ toBeLessThanOrEqual(value: number): Matcher<number>
258
312
 
259
313
  /**
260
314
  * Expects the value to be a `bigint` less than or equal to the specified
261
315
  * expected value.
262
316
  *
263
- * Negation: {@link Matchers.toBeGreaterThan `toBeGreaterThan(...)`}
317
+ * Negation: {@link Matcher.toBeGreaterThan `toBeGreaterThan(...)`}
264
318
  */
265
- toBeLessThanOrEqual(value: bigint): Matchers<bigint>
319
+ toBeLessThanOrEqual(value: bigint): Matcher<bigint>
266
320
 
267
- toBeLessThanOrEqual(value: number | bigint): Matchers {
321
+ toBeLessThanOrEqual(value: number | bigint): Matcher {
268
322
  return this._push((e) => e.toBeLessThanOrEqual(value as number))
269
323
  }
270
324
 
@@ -275,21 +329,21 @@ export class Matchers<T = unknown> {
275
329
  *
276
330
  * Negation: {@link NegativeMatchers.toBeNaN `not.toBeNaN()`}
277
331
  */
278
- toBeNaN(): Matchers<number> {
332
+ toBeNaN(): Matcher<number> {
279
333
  return this._push((e) => e.toBeNaN())
280
334
  }
281
335
 
282
336
  /* ------------------------------------------------------------------------ */
283
337
 
284
338
  /** Expects the value to strictly equal `null`. */
285
- toBeNull(): Matchers<null> {
339
+ toBeNull(): Matcher<null> {
286
340
  return this._push((e) => e.toBeNull())
287
341
  }
288
342
 
289
343
  /* ------------------------------------------------------------------------ */
290
344
 
291
345
  /** Expects the value to strictly equal `true`. */
292
- toBeTrue(): Matchers<true> {
346
+ toBeTrue(): Matcher<true> {
293
347
  return this._push((e) => e.toBeTrue())
294
348
  }
295
349
 
@@ -298,16 +352,16 @@ export class Matchers<T = unknown> {
298
352
  /**
299
353
  * Expects the value to be _falsy_ (non-zero, non-empty string, ...).
300
354
  *
301
- * Negation: {@link Matchers.toBeFalsy `toBeFalsy()`}
355
+ * Negation: {@link Matcher.toBeFalsy `toBeFalsy()`}
302
356
  */
303
- toBeTruthy(): Matchers<T> {
357
+ toBeTruthy(): Matcher<T> {
304
358
  return this._push((e) => e.toBeTruthy())
305
359
  }
306
360
 
307
361
  /* ------------------------------------------------------------------------ */
308
362
 
309
363
  /** Expects the value to strictly equal `undefined`. */
310
- toBeUndefined(): Matchers<undefined> {
364
+ toBeUndefined(): Matcher<undefined> {
311
365
  return this._push((e) => e.toBeUndefined())
312
366
  }
313
367
 
@@ -319,7 +373,7 @@ export class Matchers<T = unknown> {
319
373
  *
320
374
  * Negation: {@link NegativeMatchers.toBeWithinRange `not.toBeWithinRange(...)`}
321
375
  */
322
- toBeWithinRange(min: number, max: number): Matchers<number>
376
+ toBeWithinRange(min: number, max: number): Matcher<number>
323
377
 
324
378
  /**
325
379
  * Expects the value to be a `bigint` within the specified range where the
@@ -327,7 +381,7 @@ export class Matchers<T = unknown> {
327
381
  *
328
382
  * Negation: {@link NegativeMatchers.toBeWithinRange `not.toBeWithinRange(...)`}
329
383
  */
330
- toBeWithinRange(min: bigint, max: bigint): Matchers<bigint>
384
+ toBeWithinRange(min: bigint, max: bigint): Matcher<bigint>
331
385
 
332
386
  /**
333
387
  * Expects the value to be a `number` or `bigint` within the specified range
@@ -335,7 +389,7 @@ export class Matchers<T = unknown> {
335
389
  *
336
390
  * Negation: {@link NegativeMatchers.toBeWithinRange `not.toBeWithinRange(...)`}
337
391
  */
338
- toBeWithinRange( min: number | bigint, max: number | bigint): Matchers {
392
+ toBeWithinRange( min: number | bigint, max: number | bigint): Matcher {
339
393
  return this._push((e) => e.toBeWithinRange(min as number, max as number))
340
394
  }
341
395
 
@@ -346,7 +400,7 @@ export class Matchers<T = unknown> {
346
400
  *
347
401
  * Negation: {@link NegativeMatchers.toEqual `not.toEqual(...)`}
348
402
  */
349
- toEqual<Type>(expected: Type): Matchers<InferMatchers<Type>> {
403
+ toEqual<Type>(expected: Type): Matcher<InferToEqual<Type>> {
350
404
  return this._push((e) => e.toEqual(expected))
351
405
  }
352
406
 
@@ -358,15 +412,38 @@ export class Matchers<T = unknown> {
358
412
  *
359
413
  * Negation: {@link NegativeMatchers.toHaveLength `not.toHaveLength(...)`}
360
414
  */
361
- toHaveLength(length: number): Matchers<T & { length: number }> {
415
+ toHaveLength(length: number): Matcher<T & { length: number }> {
362
416
  return this._push((e) => e.toHaveLength(length))
363
417
  }
364
418
 
365
419
  /* ------------------------------------------------------------------------ */
366
420
 
367
421
  /**
368
- * Expects the value to have the specified _property_ and (if specified)
369
- * further asserts its value with an {@link AssertionFunction}.
422
+ * Expects the value to have the specified _property_.
423
+ *
424
+ * Negation: {@link NegativeExpectations.toHaveProperty `not.toHaveProperty(...)`}
425
+ */
426
+ toHaveProperty<Prop extends string | number | symbol>(
427
+ property: Prop,
428
+ ): Matcher<T & { [keyt in Prop] : unknown }>
429
+
430
+ /**
431
+ * Expects the value to have the specified _property_ and validates its value
432
+ * with a {@link Matcher}.
433
+ *
434
+ * Negation: {@link NegativeExpectations.toHaveProperty `not.toHaveProperty(...)`}
435
+ */
436
+ toHaveProperty<
437
+ Prop extends string | number | symbol,
438
+ Match extends Matcher,
439
+ >(
440
+ property: Prop,
441
+ matcher: Match,
442
+ ): Matcher<T & { [keyt in Prop] : InferMatcher<unknown, Match> }>
443
+
444
+ /**
445
+ * Expects the value to have the specified _property_ and further asserts
446
+ * its value with an {@link AssertionFunction}.
370
447
  *
371
448
  * Negation: {@link NegativeMatchers.toHaveProperty `not.toHaveProperty(...)`}
372
449
  */
@@ -374,10 +451,15 @@ export class Matchers<T = unknown> {
374
451
  Prop extends string | number | symbol,
375
452
  Assert extends AssertionFunction,
376
453
  >(
377
- property: Prop,
378
- assertion?: Assert,
379
- ): Matchers<T & { [keyt in Prop] : AssertedType<unknown, Assert> }> {
380
- return this._push((e) => e.toHaveProperty(property, assertion))
454
+ property: Prop,
455
+ assertion: Assert,
456
+ ): Matcher<T & { [keyt in Prop] : AssertedType<unknown, Assert> }>
457
+
458
+ toHaveProperty(
459
+ property: string | number | symbol,
460
+ assertionOrMatcher?: AssertionFunction | Matcher,
461
+ ): Matcher {
462
+ return this._push((e) => e.toHaveProperty(property, assertionOrMatcher as any))
381
463
  }
382
464
 
383
465
  /* ------------------------------------------------------------------------ */
@@ -388,7 +470,7 @@ export class Matchers<T = unknown> {
388
470
  *
389
471
  * Negation: {@link NegativeMatchers.toHaveSize `not.toHaveSize(...)`}
390
472
  */
391
- toHaveSize(size: number): Matchers<T & { size: number }> {
473
+ toHaveSize(size: number): Matcher<T & { size: number }> {
392
474
  return this._push((e) => e.toHaveSize(size))
393
475
  }
394
476
 
@@ -402,14 +484,14 @@ export class Matchers<T = unknown> {
402
484
  *
403
485
  * Negation: {@link NegativeMatchers.toInclude `not.toInclude(...)`}
404
486
  */
405
- toInclude<P extends Record<string, any>>(properties: P): Matchers<T>
487
+ toInclude<P extends Record<string, any>>(properties: P): Matcher<T>
406
488
 
407
489
  /**
408
490
  * Expect the value to include _all_ mappings from the specified {@link Map}.
409
491
  *
410
492
  * Negation: {@link NegativeMatchers.toInclude `not.toInclude(...)`}
411
493
  */
412
- toInclude(mappings: Map<any, any>): Matchers<T>
494
+ toInclude(mappings: Map<any, any>): Matcher<T>
413
495
 
414
496
  /**
415
497
  * Expect the value to be an {@link Iterable} object includind _all_ values
@@ -417,7 +499,7 @@ export class Matchers<T = unknown> {
417
499
  *
418
500
  * Negation: {@link NegativeMatchers.toInclude `not.toInclude(...)`}
419
501
  */
420
- toInclude(entries: Set<any>): Matchers<T>
502
+ toInclude(entries: Set<any>): Matcher<T>
421
503
 
422
504
  /**
423
505
  * Expect the value to be an {@link Iterable} object includind _all_ values
@@ -425,11 +507,11 @@ export class Matchers<T = unknown> {
425
507
  *
426
508
  * Negation: {@link NegativeMatchers.toInclude `not.toInclude(...)`}
427
509
  */
428
- toInclude(values: any[]): Matchers<T>
510
+ toInclude(values: any[]): Matcher<T>
429
511
 
430
512
  toInclude(
431
513
  contents: Record<string, any> | Map<any, any> | Set<any> | any[],
432
- ): Matchers {
514
+ ): Matcher {
433
515
  return this._push((e) => e.toInclude(contents))
434
516
  }
435
517
 
@@ -441,9 +523,9 @@ export class Matchers<T = unknown> {
441
523
  *
442
524
  * Negation: {@link NegativeMatchers.toMatch `not.toMatch(...)`}
443
525
  */
444
- toMatch<Matcher extends string | RegExp>(
445
- matcher: Matcher,
446
- ): Matchers<string> {
526
+ toMatch<Match extends string | RegExp>(
527
+ matcher: Match,
528
+ ): Matcher<string> {
447
529
  return this._push((e) => e.toMatch(matcher))
448
530
  }
449
531
 
@@ -453,15 +535,15 @@ export class Matchers<T = unknown> {
453
535
  * Expect the value to be an {@link Iterable} object includind _all_ values
454
536
  * (and only those values) from the specified _array_, in any order.
455
537
  */
456
- toMatchContents(contents: any[]): Matchers<T>
538
+ toMatchContents(contents: any[]): Matcher<T>
457
539
 
458
540
  /**
459
541
  * Expect the value to be an {@link Iterable} object includind _all_ values
460
542
  * (and only those values) from the specified {@link Set}, in any order.
461
543
  */
462
- toMatchContents(contents: Set<any>): Matchers<T>
544
+ toMatchContents(contents: Set<any>): Matcher<T>
463
545
 
464
- toMatchContents(contents: any[] | Set<any>): Matchers {
546
+ toMatchContents(contents: any[] | Set<any>): Matcher {
465
547
  return this._push((e) => e.toMatchContents(contents))
466
548
  }
467
549
 
@@ -472,7 +554,7 @@ export class Matchers<T = unknown> {
472
554
  *
473
555
  * Negation: {@link NegativeMatchers.toStrictlyEqual `not.toStrictlyEqual(...)`}
474
556
  */
475
- toStrictlyEqual<Type>(expected: Type): Matchers<Type> {
557
+ toStrictlyEqual<Type>(expected: Type): Matcher<Type> {
476
558
  return this._push((e) => e.toStrictlyEqual(expected))
477
559
  }
478
560
  }
@@ -483,11 +565,11 @@ export class Matchers<T = unknown> {
483
565
 
484
566
  export class NegativeMatchers<T = unknown> {
485
567
  constructor(
486
- private readonly _instance: Matchers<T>,
487
- private readonly _matchers: Matcher[],
568
+ private readonly _instance: Matcher<T>,
569
+ private readonly _matchers: PositiveMatcherFunction[],
488
570
  ) {}
489
571
 
490
- private _push(matcher: NegativeMatcher): Matchers<any> {
572
+ private _push(matcher: NegativeMatcherFunction): Matcher<any> {
491
573
  this._matchers.push((expectations) => matcher(expectations.not))
492
574
  return this._instance
493
575
  }
@@ -498,9 +580,9 @@ export class NegativeMatchers<T = unknown> {
498
580
  * Expects the value _**NOT**_ to be of the specified _extended_
499
581
  * {@link TypeName type}.
500
582
  *
501
- * Negates: {@link Matchers.toBeA `toBeA(...)`}
583
+ * Negates: {@link Matcher.toBeA `toBeA(...)`}
502
584
  */
503
- toBeA(type: TypeName): Matchers<T> {
585
+ toBeA(type: TypeName): Matcher<T> {
504
586
  return this._push((e) => e.toBeA(type))
505
587
  }
506
588
 
@@ -510,19 +592,19 @@ export class NegativeMatchers<T = unknown> {
510
592
  * Expects the value to be a `number` _**OUTSIDE**_ of the given +/- _delta_
511
593
  * range of the specified expected value.
512
594
  *
513
- * Negates: {@link Matchers.toBeCloseTo `toBeCloseTo(...)`}
595
+ * Negates: {@link Matcher.toBeCloseTo `toBeCloseTo(...)`}
514
596
  */
515
- toBeCloseTo(value: number, delta: number): Matchers<number>
597
+ toBeCloseTo(value: number, delta: number): Matcher<number>
516
598
 
517
599
  /**
518
600
  * Expects the value to be a `bigint` _**OUTSIDE**_ of the given +/- _delta_
519
601
  * range of the specified expected value.
520
602
  *
521
- * Negates: {@link Matchers.toBeCloseTo `toBeCloseTo(...)`}
603
+ * Negates: {@link Matcher.toBeCloseTo `toBeCloseTo(...)`}
522
604
  */
523
- toBeCloseTo(value: bigint, delta: bigint): Matchers<bigint>
605
+ toBeCloseTo(value: bigint, delta: bigint): Matcher<bigint>
524
606
 
525
- toBeCloseTo(value: number | bigint, delta: number | bigint): Matchers {
607
+ toBeCloseTo(value: number | bigint, delta: number | bigint): Matcher {
526
608
  return this._push((e) => e.toBeCloseTo(value as number, delta as number))
527
609
  }
528
610
 
@@ -531,9 +613,9 @@ export class NegativeMatchers<T = unknown> {
531
613
  /**
532
614
  * Expects the value to be either `null` or `undefined`.
533
615
  *
534
- * Negates: {@link Matchers.toBeDefined `toBeDefined()`}
616
+ * Negates: {@link Matcher.toBeDefined `toBeDefined()`}
535
617
  */
536
- toBeDefined(): Matchers<null | undefined> {
618
+ toBeDefined(): Matcher<null | undefined> {
537
619
  return this._push((e) => e.toBeDefined())
538
620
  }
539
621
 
@@ -543,9 +625,9 @@ export class NegativeMatchers<T = unknown> {
543
625
  * Expects the value _**NOT**_ to be an instance of the specified
544
626
  * {@link Constructor}.
545
627
  *
546
- * Negates: {@link Matchers.toBeInstanceOf `toBeInstanceOf(...)`}
628
+ * Negates: {@link Matcher.toBeInstanceOf `toBeInstanceOf(...)`}
547
629
  */
548
- toBeInstanceOf(constructor: Constructor): Matchers<T> {
630
+ toBeInstanceOf(constructor: Constructor): Matcher<T> {
549
631
  return this._push((e) => e.toBeInstanceOf(constructor))
550
632
  }
551
633
 
@@ -554,9 +636,9 @@ export class NegativeMatchers<T = unknown> {
554
636
  /**
555
637
  * Expects the value _**NOT**_ to be `NaN`.
556
638
  *
557
- * Negates: {@link Matchers.toBeNaN `toBeNaN()`}
639
+ * Negates: {@link Matcher.toBeNaN `toBeNaN()`}
558
640
  */
559
- toBeNaN(): Matchers<number> {
641
+ toBeNaN(): Matcher<number> {
560
642
  return this._push((e) => e.toBeNaN())
561
643
  }
562
644
 
@@ -566,19 +648,19 @@ export class NegativeMatchers<T = unknown> {
566
648
  * Expects the value to be a `number` _**OUTSIDE**_ of the specified range
567
649
  * where minimum and maximum values are inclusive.
568
650
  *
569
- * Negates: {@link Matchers.toBeWithinRange `toBeWithinRange(...)`}
651
+ * Negates: {@link Matcher.toBeWithinRange `toBeWithinRange(...)`}
570
652
  */
571
- toBeWithinRange(min: number, max: number): Matchers<number>
653
+ toBeWithinRange(min: number, max: number): Matcher<number>
572
654
 
573
655
  /**
574
656
  * Expects the value to be a `bigint` _**OUTSIDE**_ of the specified range
575
657
  * where minimum and maximum values are inclusive.
576
658
  *
577
- * Negates: {@link Matchers.toBeWithinRange `toBeWithinRange(...)`}
659
+ * Negates: {@link Matcher.toBeWithinRange `toBeWithinRange(...)`}
578
660
  */
579
- toBeWithinRange(min: bigint, max: bigint): Matchers<bigint>
661
+ toBeWithinRange(min: bigint, max: bigint): Matcher<bigint>
580
662
 
581
- toBeWithinRange(min: number | bigint, max: number | bigint): Matchers {
663
+ toBeWithinRange(min: number | bigint, max: number | bigint): Matcher {
582
664
  return this._push((e) => e.toBeWithinRange(min as number, max as number))
583
665
  }
584
666
 
@@ -588,9 +670,9 @@ export class NegativeMatchers<T = unknown> {
588
670
  * Expects the value _**NOT**_ to be _deep equal to_ the specified expected
589
671
  * one.
590
672
  *
591
- * Negates: {@link Matchers.toEqual `toEqual(...)`}
673
+ * Negates: {@link Matcher.toEqual `toEqual(...)`}
592
674
  */
593
- toEqual(expected: any): Matchers<T> {
675
+ toEqual(expected: any): Matcher<T> {
594
676
  return this._push((e) => e.toEqual(expected))
595
677
  }
596
678
 
@@ -600,9 +682,9 @@ export class NegativeMatchers<T = unknown> {
600
682
  * Expects the value to have a `number` _property_ `length` _different_ from
601
683
  * the specified expected value.
602
684
  *
603
- * Negates: {@link Matchers.toHaveLength `toHaveLength(...)`}
685
+ * Negates: {@link Matcher.toHaveLength `toHaveLength(...)`}
604
686
  */
605
- toHaveLength(length: number): Matchers<T & { length: number }> {
687
+ toHaveLength(length: number): Matcher<T & { length: number }> {
606
688
  return this._push((e) => e.toHaveLength(length))
607
689
  }
608
690
 
@@ -611,9 +693,9 @@ export class NegativeMatchers<T = unknown> {
611
693
  /**
612
694
  * Expects the value _**NOT**_ to have the specified _property_.
613
695
  *
614
- * Negates: {@link Matchers.toHaveProperty `toHaveProperty(...)`}
696
+ * Negates: {@link Matcher.toHaveProperty `toHaveProperty(...)`}
615
697
  */
616
- toHaveProperty(property: string | number | symbol): Matchers<T> {
698
+ toHaveProperty(property: string | number | symbol): Matcher<T> {
617
699
  return this._push((e) => e.toHaveProperty(property))
618
700
  }
619
701
 
@@ -623,9 +705,9 @@ export class NegativeMatchers<T = unknown> {
623
705
  * Expects the value to have a `number` _property_ `size` _different_ from
624
706
  * the specified expected value.
625
707
  *
626
- * Negates: {@link Matchers.toHaveSize `toHaveSize(...)`}
708
+ * Negates: {@link Matcher.toHaveSize `toHaveSize(...)`}
627
709
  */
628
- toHaveSize(size: number): Matchers<T & { size: number }> {
710
+ toHaveSize(size: number): Matcher<T & { size: number }> {
629
711
  return this._push((e) => e.toHaveSize(size))
630
712
  }
631
713
 
@@ -638,37 +720,37 @@ export class NegativeMatchers<T = unknown> {
638
720
  * If the object being expected is a {@link Map}, the properties specified
639
721
  * here will be treated as _mappings_ for said {@link Map}.
640
722
  *
641
- * Negates: {@link Matchers.toInclude `toInclude(...)`}
723
+ * Negates: {@link Matcher.toInclude `toInclude(...)`}
642
724
  */
643
- toInclude<P extends Record<string, any>>(properties: P): Matchers<T>
725
+ toInclude<P extends Record<string, any>>(properties: P): Matcher<T>
644
726
 
645
727
  /**
646
728
  * Expect the value to include _none_ of the mappings from the specified
647
729
  * {@link Map}.
648
730
  *
649
- * Negates: {@link Matchers.toInclude `toInclude(...)`}
731
+ * Negates: {@link Matcher.toInclude `toInclude(...)`}
650
732
  */
651
- toInclude(mappings: Map<any, any>): Matchers<T>
733
+ toInclude(mappings: Map<any, any>): Matcher<T>
652
734
 
653
735
  /**
654
736
  * Expect the value to be an {@link Iterable} object includind _none_ of the
655
737
  * values from the specified {@link Set}.
656
738
  *
657
- * Negates: {@link Matchers.toInclude `toInclude(...)`}
739
+ * Negates: {@link Matcher.toInclude `toInclude(...)`}
658
740
  */
659
- toInclude(entries: Set<any>): Matchers<T>
741
+ toInclude(entries: Set<any>): Matcher<T>
660
742
 
661
743
  /**
662
744
  * Expect the value to be an {@link Iterable} object includind _none_ of the
663
745
  * values from the specified _array_.
664
746
  *
665
- * Negates: {@link Matchers.toInclude `toInclude(...)`}
747
+ * Negates: {@link Matcher.toInclude `toInclude(...)`}
666
748
  */
667
- toInclude(values: any[]): Matchers<T>
749
+ toInclude(values: any[]): Matcher<T>
668
750
 
669
751
  toInclude(
670
752
  contents: Record<string, any> | Map<any, any> | Set<any> | any[],
671
- ): Matchers {
753
+ ): Matcher {
672
754
  return this._push((e) => e.toInclude(contents))
673
755
  }
674
756
 
@@ -678,9 +760,9 @@ export class NegativeMatchers<T = unknown> {
678
760
  * Expects the value to be a `string` _**NOT MATCHING**_ the specified
679
761
  * sub-`string` or {@link RegExp}.
680
762
  *
681
- * Negates: {@link Matchers.toMatch `toMatch(...)`}
763
+ * Negates: {@link Matcher.toMatch `toMatch(...)`}
682
764
  */
683
- toMatch(matcher: string | RegExp): Matchers<string> {
765
+ toMatch(matcher: string | RegExp): Matcher<string> {
684
766
  return this._push((e) => e.toMatch(matcher))
685
767
  }
686
768
 
@@ -690,9 +772,9 @@ export class NegativeMatchers<T = unknown> {
690
772
  * Expects the value _**NOT**_ to be _strictly equal to_ the specified
691
773
  * expected one.
692
774
  *
693
- * Negates: {@link Matchers.toStrictlyEqual `toStrictlyEqual(...)`}
775
+ * Negates: {@link Matcher.toStrictlyEqual `toStrictlyEqual(...)`}
694
776
  */
695
- toStrictlyEqual(expected: any): Matchers<T> {
777
+ toStrictlyEqual(expected: any): Matcher<T> {
696
778
  return this._push((e) => e.toStrictlyEqual(expected))
697
779
  }
698
780
  }