@plugjs/expect5 0.4.1 → 0.4.3

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