@plugjs/expect5 0.4.2 → 0.4.4

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 (59) hide show
  1. package/dist/cli.mjs +1 -1
  2. package/dist/expectation/async.cjs +73 -0
  3. package/dist/expectation/async.cjs.map +6 -0
  4. package/dist/expectation/async.d.ts +54 -0
  5. package/dist/expectation/async.mjs +46 -0
  6. package/dist/expectation/async.mjs.map +6 -0
  7. package/dist/expectation/basic.cjs +155 -183
  8. package/dist/expectation/basic.cjs.map +1 -1
  9. package/dist/expectation/basic.d.ts +90 -47
  10. package/dist/expectation/basic.mjs +142 -163
  11. package/dist/expectation/basic.mjs.map +1 -1
  12. package/dist/expectation/diff.cjs +7 -7
  13. package/dist/expectation/diff.cjs.map +1 -1
  14. package/dist/expectation/diff.mjs +7 -7
  15. package/dist/expectation/diff.mjs.map +1 -1
  16. package/dist/expectation/expect.cjs +94 -108
  17. package/dist/expectation/expect.cjs.map +2 -2
  18. package/dist/expectation/expect.d.ts +103 -130
  19. package/dist/expectation/expect.mjs +131 -137
  20. package/dist/expectation/expect.mjs.map +2 -2
  21. package/dist/expectation/include.cjs +50 -61
  22. package/dist/expectation/include.cjs.map +1 -1
  23. package/dist/expectation/include.d.ts +19 -10
  24. package/dist/expectation/include.mjs +53 -57
  25. package/dist/expectation/include.mjs.map +1 -1
  26. package/dist/expectation/throwing.cjs +27 -27
  27. package/dist/expectation/throwing.cjs.map +1 -1
  28. package/dist/expectation/throwing.d.ts +36 -8
  29. package/dist/expectation/throwing.mjs +26 -26
  30. package/dist/expectation/throwing.mjs.map +1 -1
  31. package/dist/expectation/trivial.cjs +96 -0
  32. package/dist/expectation/trivial.cjs.map +6 -0
  33. package/dist/expectation/trivial.d.ts +13 -0
  34. package/dist/expectation/trivial.mjs +61 -0
  35. package/dist/expectation/trivial.mjs.map +6 -0
  36. package/dist/expectation/types.cjs +9 -12
  37. package/dist/expectation/types.cjs.map +1 -1
  38. package/dist/expectation/types.d.ts +52 -10
  39. package/dist/expectation/types.mjs +8 -10
  40. package/dist/expectation/types.mjs.map +1 -1
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.mjs.map +1 -1
  44. package/package.json +2 -2
  45. package/src/expectation/async.ts +151 -0
  46. package/src/expectation/basic.ts +360 -156
  47. package/src/expectation/diff.ts +8 -9
  48. package/src/expectation/expect.ts +239 -268
  49. package/src/expectation/include.ts +93 -59
  50. package/src/expectation/throwing.ts +102 -41
  51. package/src/expectation/trivial.ts +107 -0
  52. package/src/expectation/types.ts +82 -25
  53. package/src/index.ts +2 -0
  54. package/dist/expectation/void.cjs +0 -111
  55. package/dist/expectation/void.cjs.map +0 -6
  56. package/dist/expectation/void.d.ts +0 -39
  57. package/dist/expectation/void.mjs +0 -77
  58. package/dist/expectation/void.mjs.map +0 -6
  59. package/src/expectation/void.ts +0 -80
@@ -1,209 +1,413 @@
1
1
  import { diff } from './diff'
2
- import { assertType, ExpectationError, isType, prefixType, stringifyConstructor, stringifyValue } from './types'
2
+ import {
3
+ assertContextType,
4
+ ExpectationError,
5
+ prefixType,
6
+ stringifyConstructor,
7
+ stringifyValue,
8
+ typeOf,
9
+ } from './types'
3
10
 
4
- import type { Constructor, TypeName, StringMatcher } from './types'
5
- import type { Expectation, Expectations } from './expect'
11
+ import type { Expectations } from './expect'
12
+ import type {
13
+ AssertedType,
14
+ AssertionFunction,
15
+ Constructor,
16
+ ExpectationsContext,
17
+ JoinExpectations,
18
+ TypeMappings,
19
+ TypeName,
20
+ } from './types'
6
21
 
7
- export class ToBeA implements Expectation {
8
- expect(context: Expectations, negative: boolean, type: TypeName): void {
9
- const match = isType(context, type)
10
- if (match !== negative) return
11
- throw new ExpectationError(context, negative, `to be ${prefixType(type)}`)
22
+ /* === TO BE A ============================================================== */
23
+
24
+ /** Expects the value to be of the specified {@link TypeName type}. */
25
+ function toBeA<N extends TypeName>(type: N): Expectations<TypeMappings[N]>
26
+
27
+ /**
28
+ * Expects the value to be of the specified {@link TypeName type}, and further
29
+ * asserts it with the specified callback.
30
+ */
31
+ function toBeA<T, N extends TypeName, A extends AssertionFunction<TypeMappings[N]>>(
32
+ this: T,
33
+ type: N,
34
+ assert: A,
35
+ ): Expectations<TypeMappings[N] & AssertedType<A>>
36
+
37
+ /* Overloaded function implementation */
38
+ function toBeA(
39
+ this: ExpectationsContext,
40
+ type: TypeName,
41
+ assert?: AssertionFunction,
42
+ ): Expectations {
43
+ const match = typeOf(this.value) === type
44
+ if (match === this.negative) {
45
+ throw new ExpectationError(this, `to be ${prefixType(type)}`)
46
+ } else if (assert) {
47
+ assert(this.expects)
12
48
  }
49
+ return this.expects
13
50
  }
14
51
 
15
- export class ToBeCloseTo implements Expectation {
16
- expect(
17
- context: Expectations,
18
- negative: boolean,
19
- ...[ value, delta ]:
20
- | [ value: number, delta: number ]
21
- | [ value: bigint, delta: bigint ]
22
- ): void {
23
- const min = (value as number) - (delta as number)
24
- const max = (value as number) + (delta as number)
25
- context.negated(negative).toBeWithinRange(min, max)
26
- }
52
+ /* === TO BE CLOSE TO ======================================================= */
53
+
54
+ /**
55
+ * Expects the value to be a `number` within a given +/- delta range of the
56
+ * specified `number`.
57
+ */
58
+ function toBeCloseTo(value: number, delta: number): Expectations<number>
59
+
60
+ /**
61
+ * Expects the value to be a a `bigint` within a given +/- delta range of the
62
+ * specified `bigint`.
63
+ */
64
+ function toBeCloseTo(value: bigint, delta: bigint): Expectations<bigint>
65
+
66
+ /* Overloaded function implementation */
67
+ function toBeCloseTo(
68
+ this: ExpectationsContext,
69
+ value: number | bigint,
70
+ delta: number | bigint,
71
+ ): Expectations {
72
+ const min = (value as number) - (delta as number)
73
+ const max = (value as number) + (delta as number)
74
+ return this.negated.toBeWithinRange(min, max)
27
75
  }
28
76
 
29
- export class ToBeError implements Expectation {
30
- expect(
31
- context: Expectations,
32
- negative: boolean,
33
- ...args:
34
- | []
35
- | [ message: StringMatcher ]
36
- | [ constructor: Constructor<Error> ]
37
- | [ constructor: Constructor<Error>, message: StringMatcher ]
38
- ): void {
39
- const [ constructor, message ] =
77
+ /* === TO BE ERROR ========================================================== */
78
+
79
+ /** Expects the value to be an {@link Error}. */
80
+ function toBeError(): Expectations<Error>
81
+
82
+ /** Expects the value to be an {@link Error} with the specified message. */
83
+ function toBeError(message: string): Expectations<Error>
84
+
85
+ /**
86
+ * Expects the value to be an {@link Error} with its message matching the
87
+ * specified {@link RegExp}.
88
+ */
89
+ function toBeError(matcher: RegExp): Expectations<Error>
90
+
91
+ /** Expects the value to be an {@link Error} of the specified _type_. */
92
+ function toBeError<C extends Constructor<Error>>(constructor: C): Expectations<InstanceType<C>>
93
+
94
+ /**
95
+ * Expects the value to be an {@link Error} of the specified _type_ with the
96
+ * specified message
97
+ */
98
+ function toBeError<C extends Constructor<Error>>(constructor: C, message: string): Expectations<InstanceType<C>>
99
+
100
+ /**
101
+ * Expects the value to be an {@link Error} of the specified _type_ with the
102
+ * specified message
103
+ */
104
+ function toBeError<C extends Constructor<Error>>(constructor: C, matcher: RegExp): Expectations<InstanceType<C>>
105
+
106
+ /* Overloaded function implementation */
107
+ function toBeError(
108
+ this: ExpectationsContext,
109
+ ...args:
110
+ | []
111
+ | [ message: string | RegExp ]
112
+ | [ constructor: Constructor<Error> ]
113
+ | [ constructor: Constructor<Error>, message: string | RegExp ]
114
+ ): Expectations {
115
+ const [ constructor, message ] =
40
116
  typeof args[0] === 'function' ?
41
117
  [ args[0], args[1] ] :
42
118
  [ Error, args[0] ]
43
119
 
44
- context.negated(negative).toBeInstanceOf(constructor)
45
- if (negative || (message === undefined)) return // if "not.toBeError" ignore the message
120
+ this.negated.toBeInstanceOf(constructor)
46
121
 
47
- context.toHaveProperty('message', (assert) => {
48
- assertType(assert, 'string')
49
- if (typeof message === 'string') assert.toStrictlyEqual(message)
50
- else assert.toMatch(message)
51
- })
52
- }
122
+ // if "not.toBeError" ignore the message
123
+ if (this.negative || (message === undefined)) return this.expects
124
+
125
+ return this.expects.toHaveProperty('message', (assert) => {
126
+ assert.toBeA('string')
127
+ return typeof message === 'string' ?
128
+ assert.toStrictlyEqual(message) :
129
+ assert.toMatch(message)
130
+ })
53
131
  }
54
132
 
55
- export class ToBeGreaterThan implements Expectation {
56
- expect(context: Expectations, negative: boolean, value: number | bigint): void {
57
- assertType(context, typeof value as 'number' | 'bigint')
58
- if ((context.value > value) !== negative) return
59
- throw new ExpectationError(context, negative, `to be greater than ${stringifyValue(value)}`)
60
- }
133
+
134
+ /* === TO BE GREATER THAN =================================================== */
135
+
136
+ /** Expects the value to be a `number` greater than the specified `number`. */
137
+ function toBeGreaterThan(value: number): Expectations<number>
138
+ /** Expects the value to be a `bigint` greater than the specified `bigint`. */
139
+ function toBeGreaterThan(value: bigint): Expectations<bigint>
140
+
141
+ /* Overloaded function implementation */
142
+ function toBeGreaterThan(
143
+ this: ExpectationsContext,
144
+ value: number | bigint,
145
+ ): Expectations {
146
+ assertContextType(this, typeof value as 'number' | 'bigint')
147
+ if ((this.value > value) !== this.negative) return this.expects
148
+ throw new ExpectationError(this, `to be greater than ${stringifyValue(value)}`)
61
149
  }
62
150
 
63
- export class ToBeGreaterThanOrEqual implements Expectation {
64
- expect(context: Expectations, negative: boolean, value: number | bigint): void {
65
- assertType(context, typeof value as 'number' | 'bigint')
66
- if ((context.value >= value) !== negative) return
67
- throw new ExpectationError(context, negative, `to be greater than or equal to ${stringifyValue(value)}`)
68
- }
151
+ /* === TO BE GREATER THAN OR EQUAL ========================================== */
152
+
153
+ /** Expects the value to be a `number` greater than or equal to the specified `number`. */
154
+ function toBeGreaterThanOrEqual(value: number): Expectations<number>
155
+ /** Expects the value to be a `bigint` greater than or equal to the specified `bigint`. */
156
+ function toBeGreaterThanOrEqual(value: bigint): Expectations<bigint>
157
+
158
+ /* Overloaded function implementation */
159
+ function toBeGreaterThanOrEqual(
160
+ this: ExpectationsContext,
161
+ value: number | bigint,
162
+ ): Expectations {
163
+ assertContextType(this, typeof value as 'number' | 'bigint')
164
+ if ((this.value >= value) !== this.negative) return this.expects
165
+ throw new ExpectationError(this, `to be greater than or equal to ${stringifyValue(value)}`)
69
166
  }
70
167
 
71
- export class ToBeInstanceOf implements Expectation {
72
- expect(context: Expectations, negative: boolean, value: Constructor): void {
73
- const match = context.value instanceof value
74
- if (match !== negative) return
75
- throw new ExpectationError(context, negative, `to be an instance of ${stringifyConstructor(value)}`)
76
- }
168
+ /* === TO BE INSTANCE OF ==================================================== */
169
+
170
+ /** Expects the value to be an instance of the specified _type_. */
171
+ function toBeInstanceOf<C extends Constructor>(value: C): Expectations<InstanceType<C>>
172
+
173
+ /* Overloaded function implementation */
174
+ function toBeInstanceOf(
175
+ this: ExpectationsContext,
176
+ value: Constructor,
177
+ ): Expectations {
178
+ const match = this.value instanceof value
179
+ if (match !== this.negative) return this.expects
180
+ throw new ExpectationError(this, `to be an instance of ${stringifyConstructor(value)}`)
77
181
  }
78
182
 
79
- export class ToBeLessThan implements Expectation {
80
- expect(context: Expectations, negative: boolean, value: number | bigint): void {
81
- assertType(context, typeof value as 'number' | 'bigint')
82
- if ((context.value < value) !== negative) return
83
- throw new ExpectationError(context, negative, `to be less than ${stringifyValue(value)}`)
84
- }
183
+ /* === TO BE LESS THAN ====================================================== */
184
+
185
+ /** Expects the value to be a `number` less than the specified `number`. */
186
+ function toBeLessThan(value: number): Expectations<number>
187
+ /** Expects the value to be a `bigint` less than the specified `bigint`. */
188
+ function toBeLessThan(value: bigint): Expectations<bigint>
189
+
190
+ /* Overloaded function implementation */
191
+ function toBeLessThan(
192
+ this: ExpectationsContext,
193
+ value: number | bigint,
194
+ ): Expectations {
195
+ assertContextType(this, typeof value as 'number' | 'bigint')
196
+ if ((this.value < value) !== this.negative) return this.expects
197
+ throw new ExpectationError(this, `to be less than ${stringifyValue(value)}`)
85
198
  }
86
199
 
87
- export class ToBeLessThanOrEqual implements Expectation {
88
- expect(context: Expectations, negative: boolean, value: number | bigint): void {
89
- assertType(context, typeof value as 'number' | 'bigint')
90
- if ((context.value <= value) !== negative) return
91
- throw new ExpectationError(context, negative, `to be less than or equal to ${stringifyValue(value)}`)
92
- }
200
+ /* === TO BE LESS THAN OR EQUAL ============================================= */
201
+
202
+ /** Expects the value to be a `number` less than or equal to the specified `number`. */
203
+ function toBeLessThanOrEqual(value: number): Expectations<number>
204
+ /** Expects the value to be a `bigint` less than or equal to the specified `bigint`. */
205
+ function toBeLessThanOrEqual(value: bigint): Expectations<bigint>
206
+
207
+ /* Overloaded function implementation */
208
+ function toBeLessThanOrEqual(
209
+ this: ExpectationsContext,
210
+ value: number | bigint,
211
+ ): Expectations {
212
+ assertContextType(this, typeof value as 'number' | 'bigint')
213
+ if ((this.value <= value) !== this.negative) return this.expects
214
+ throw new ExpectationError(this, `to be less than or equal to ${stringifyValue(value)}`)
93
215
  }
94
216
 
95
- export class ToBeWithinRange implements Expectation {
96
- expect(
97
- context: Expectations,
98
- negative: boolean,
99
- ...[ min, max ]:
100
- | [ min: number, max: number ]
101
- | [ min: bigint, max: bigint ]
102
- ): void {
103
- if (max < min) {
104
- const num = max
105
- max = min
106
- min = num
107
- }
217
+ /* === TO WITHIN RANGE ====================================================== */
218
+
219
+ /** Expects the value to be a `number` within the specified range (inclusive). */
220
+ function toBeWithinRange(min: number, max: number): Expectations<number>
221
+ /** Expects the value to be a `bigint` within the specified range (inclusive). */
222
+ function toBeWithinRange(min: bigint, max: bigint): Expectations<bigint>
108
223
 
109
- assertType(context, typeof min as 'number' | 'bigint')
110
- if (((context.value >= min) && (context.value <= max)) !== negative) return
111
- throw new ExpectationError(context, negative, `to be within ${stringifyValue(min)}...${stringifyValue(max)}`)
224
+ /* Overloaded function implementation */
225
+ function toBeWithinRange(
226
+ this: ExpectationsContext,
227
+ min: number | bigint,
228
+ max: number | bigint,
229
+ ): Expectations {
230
+ if (max < min) {
231
+ const num = max
232
+ max = min
233
+ min = num
112
234
  }
235
+
236
+ assertContextType(this, typeof min as 'number' | 'bigint')
237
+ if (((this.value >= min) && (this.value <= max)) !== this.negative) return this.expects
238
+ throw new ExpectationError(this, `to be within ${stringifyValue(min)}...${stringifyValue(max)}`)
113
239
  }
114
240
 
115
- export class ToEqual implements Expectation {
116
- expect(context: Expectations, negative: boolean, expected: any): void {
117
- const result = diff(context.value, expected)
118
- if (result.diff === negative) return
119
- throw new ExpectationError(context, negative, `to equal ${stringifyValue(expected)}`, result)
120
- }
241
+ /* === TO EQUAL ============================================================= */
242
+
243
+ /** Expects the value to _deeply equal_ to the specified expected value. */
244
+ function toEqual<T>(expected: T): Expectations<T>
245
+
246
+ /* Overloaded function implementation */
247
+ function toEqual(
248
+ this: ExpectationsContext,
249
+ expected: any,
250
+ ): Expectations {
251
+ const result = diff(this.value, expected)
252
+ if (result.diff === this.negative) return this.expects
253
+ throw new ExpectationError(this, `to equal ${stringifyValue(expected)}`, result)
121
254
  }
122
255
 
123
- export class ToHaveLength implements Expectation {
124
- expect(context: Expectations, negative: boolean, length: number): void {
125
- context.toBeDefined()
256
+ /* === TO HAVE LENGTH ======================================================= */
126
257
 
127
- const actualLength = (context.value as any).length
128
- if (typeof actualLength !== 'number') {
129
- throw new ExpectationError(context, false, 'to have a numeric "length" property')
130
- }
258
+ /** Expects the value to have a numerical `length` property with the specified value. */
259
+ function toHaveLength<T, N extends number>(this: T, length: N): JoinExpectations<T, { length: N }>
131
260
 
132
- if ((actualLength === length) === negative) {
133
- throw new ExpectationError(context, negative, `to have length ${stringifyValue(length)}`)
134
- }
261
+ /* Overloaded function implementation */
262
+ function toHaveLength(
263
+ this: ExpectationsContext,
264
+ length: number,
265
+ ): Expectations {
266
+ this.expects.toBeDefined()
267
+
268
+ const actualLength = (this.value as any).length
269
+ if (typeof actualLength !== 'number') {
270
+ throw new ExpectationError(this, 'to have a numeric "length" property', false)
271
+ }
272
+
273
+ if ((actualLength === length) === this.negative) {
274
+ throw new ExpectationError(this, `to have length ${stringifyValue(length)}`)
135
275
  }
276
+
277
+ return this.expects
136
278
  }
137
279
 
138
- export class ToHaveProperty implements Expectation {
139
- expect(
140
- context: Expectations,
141
- negative: boolean,
142
- prop: string | number | symbol,
143
- assert?: (propertyExpectations: Expectations) => void,
144
- ): void {
145
- context.toBeDefined()
146
-
147
- const match = (context.value as any)[prop] !== undefined
148
- if (match === negative) {
149
- throw new ExpectationError(context, negative, `to have property "${String(prop)}"`)
150
- } else if (match && assert) {
151
- try {
152
- assert(context.forProperty(prop))
153
- } catch (error) {
154
- // any caught error difference gets remapped as a property diff
155
- if ((error instanceof ExpectationError) && (error.diff)) {
156
- error.diff = {
157
- diff: true,
158
- value: context.value,
159
- props: { [prop]: error.diff },
160
- }
161
- }
280
+ /* === TO HAVE PROPERTY ===================================================== */
281
+
282
+ /** Expects the value to have a property. */
283
+ function toHaveProperty<T, P extends string | number | symbol>(
284
+ this: T,
285
+ prop: P,
286
+ ): JoinExpectations<T, { [key in P]: unknown }>
287
+
288
+ /**
289
+ * Expects the value to have a property, and further asserts the property
290
+ * value with the specified callback.
291
+ */
292
+ function toHaveProperty<T, P extends string | number | symbol, A extends AssertionFunction>(
293
+ this: T,
294
+ prop: P,
295
+ assert: A,
296
+ ): JoinExpectations<T, { [key in P]: AssertedType<A> }>
162
297
 
163
- // re-throw
164
- throw error
298
+ /* Overloaded function implementation */
299
+ function toHaveProperty(
300
+ this: ExpectationsContext,
301
+ prop: string | symbol | number,
302
+ assert?: AssertionFunction,
303
+ ): Expectations {
304
+ this.expects.toBeDefined()
305
+
306
+ const match = (this.value as any)[prop] !== undefined
307
+ if (match === this.negative) {
308
+ throw new ExpectationError(this, `to have property "${String(prop)}"`)
309
+ } else if (match && assert) {
310
+ try {
311
+ assert(this.forProperty(prop))
312
+ } catch (error) {
313
+ // any caught error difference gets remapped as a property diff
314
+ if ((error instanceof ExpectationError) && (error.diff)) {
315
+ error.diff = {
316
+ diff: true,
317
+ value: this.value,
318
+ props: { [prop]: error.diff },
319
+ }
165
320
  }
321
+
322
+ // re-throw
323
+ throw error
166
324
  }
167
325
  }
326
+
327
+ return this.expects
168
328
  }
169
329
 
170
- export class ToHaveSize implements Expectation {
171
- expect(context: Expectations, negative: boolean, size: number): void {
172
- context.toBeDefined()
173
330
 
174
- const actualSize = (context.value as any).size
175
- if (typeof actualSize !== 'number') {
176
- throw new ExpectationError(context, false, 'to have a numeric "size" property')
177
- }
331
+ /* === TO HAVE SIZE ========================================================= */
178
332
 
179
- if ((actualSize === size) === negative) {
180
- throw new ExpectationError(context, negative, `to have size ${stringifyValue(size)}`)
181
- }
333
+ /** Expects the value to have a numerical `size` property with the specified value. */
334
+ function toHaveSize<T, N extends number>(this: T, size: N): JoinExpectations<T, { size: N }>
335
+
336
+ /* Overloaded function implementation */
337
+ function toHaveSize(
338
+ this: ExpectationsContext,
339
+ size: number,
340
+ ): Expectations {
341
+ this.expects.toBeDefined()
342
+
343
+ const actualSize = (this.value as any).size
344
+ if (typeof actualSize !== 'number') {
345
+ throw new ExpectationError(this, 'to have a numeric "size" property', false)
182
346
  }
347
+
348
+ if ((actualSize === size) === this.negative) {
349
+ throw new ExpectationError(this, `to have size ${stringifyValue(size)}`)
350
+ }
351
+
352
+ return this.expects
183
353
  }
184
354
 
185
- export class ToMatch implements Expectation {
186
- expect(
187
- context: Expectations,
188
- negative: boolean,
189
- expr: StringMatcher,
190
- ): void {
191
- assertType(context, 'string')
355
+ /* === TO MATCH ============================================================= */
192
356
 
193
- const match = !! context.value.match(expr as string | RegExp) // meh, overloads
194
- if (match !== negative) return
357
+ /** Expects the value to be a `string` _matching_ the specified substring. */
358
+ function toMatch(substring: string): Expectations<string>
359
+ /** Expects the value to be a `string` _matching_ the specified {@link RegExp}. */
360
+ function toMatch(expression: RegExp): Expectations<string>
195
361
 
196
- throw new ExpectationError(context, negative, `to match ${stringifyValue(expr)}`)
197
- }
362
+ /* Overloaded function implementation */
363
+ function toMatch(
364
+ this: ExpectationsContext,
365
+ expr: string | RegExp,
366
+ ): Expectations {
367
+ assertContextType(this, 'string')
368
+
369
+ const match = !! this.value.match(expr)
370
+ if (match !== this.negative) return this.expects
371
+
372
+ throw new ExpectationError(this, `to match ${stringifyValue(expr)}`)
198
373
  }
199
374
 
200
- export class ToStrictlyEqual implements Expectation {
201
- expect(context: Expectations, negative: boolean, expected: any): void {
202
- const value = context.value
203
- const match = value === expected
204
- if (match !== negative) return
205
375
 
206
- const diff = negative ? undefined : { diff: true, value, expected }
207
- throw new ExpectationError(context, negative, `to strictly equal ${stringifyValue(expected)}`, diff)
208
- }
376
+ /* === TO STRICTLY EQUAL ==================================================== */
377
+
378
+ /** Expects the value to _strictly equal_ to the specified expected value. */
379
+ function toStrictlyEqual<T>(expected: T): Expectations<T>
380
+
381
+ /* Overloaded function implementation */
382
+ function toStrictlyEqual(
383
+ this: ExpectationsContext,
384
+ expected: any,
385
+ ): Expectations {
386
+ // const value = context.value
387
+ const match = this.value === expected
388
+ if (match !== this.negative) return this.expects
389
+
390
+ const diff = this.negative ? undefined : { diff: true, value: this.value, expected }
391
+ throw new ExpectationError(this, `to strictly equal ${stringifyValue(expected)}`, diff)
392
+ }
393
+
394
+ /* === EXPORTS ============================================================== */
395
+
396
+ /* coverage ignore next */
397
+ export {
398
+ toBeA,
399
+ toBeCloseTo,
400
+ toBeError,
401
+ toBeGreaterThan,
402
+ toBeGreaterThanOrEqual,
403
+ toBeInstanceOf,
404
+ toBeLessThan,
405
+ toBeLessThanOrEqual,
406
+ toBeWithinRange,
407
+ toEqual,
408
+ toHaveLength,
409
+ toHaveProperty,
410
+ toHaveSize,
411
+ toMatch,
412
+ toStrictlyEqual,
209
413
  }
@@ -77,15 +77,14 @@ function objectDiff<T extends Record<string, any>>(
77
77
  const act = actual[key]
78
78
  const exp = expected[key]
79
79
 
80
- let result = diffValues(act, exp, remarks)
81
-
82
- // if there is a difference, we _might_ have a missing/extra property
83
- if (result.diff) {
84
- if ((act === undefined) && (key in expected)) {
85
- result = { diff: true, missing: exp }
86
- } else if ((exp === undefined) && (key in actual)) {
87
- result = { diff: true, extra: act }
88
- }
80
+ // check for missing/extra property or differences
81
+ let result: Diff
82
+ if ((key in expected) && (!(key in actual))) {
83
+ result = { diff: true, missing: exp }
84
+ } else if ((key in actual) && (!(key in expected))) {
85
+ result = { diff: true, extra: act }
86
+ } else {
87
+ result = diffValues(act, exp, remarks)
89
88
  }
90
89
 
91
90
  props[key] = result