@as-pect/assembly 6.1.0 → 7.0.1
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 +34 -34
- package/assembly/index.ts +24 -24
- package/assembly/internal/Actual.ts +20 -20
- package/assembly/internal/Expectation.ts +544 -481
- package/assembly/internal/Expected.ts +55 -55
- package/assembly/internal/Reflect.ts +698 -662
- package/assembly/internal/ReflectedValueType.ts +17 -17
- package/assembly/internal/Test.ts +81 -81
- package/assembly/internal/assert.ts +3 -3
- package/assembly/internal/call.ts +3 -3
- package/assembly/internal/comparison/toIncludeComparison.ts +67 -62
- package/assembly/internal/comparison/toIncludeEqualComparison.ts +91 -78
- package/assembly/internal/log.ts +19 -18
- package/assembly/internal/noOp.ts +3 -2
- package/package.json +17 -10
- package/types/as-pect.d.ts +733 -733
- package/types/as-pect.portable.d.ts +389 -389
- package/types/env.d.ts +1 -1
|
@@ -1,481 +1,544 @@
|
|
|
1
|
-
import { toIncludeComparison } from "./comparison/toIncludeComparison";
|
|
2
|
-
import { toIncludeEqualComparison } from "./comparison/toIncludeEqualComparison";
|
|
3
|
-
import { Actual } from "./Actual";
|
|
4
|
-
import { Expected } from "./Expected";
|
|
5
|
-
import { assert } from "./assert";
|
|
6
|
-
|
|
7
|
-
// @ts-ignore: Decorators *are* valid here
|
|
8
|
-
@external("__aspect", "tryCall")
|
|
9
|
-
declare function tryCall(func: () => void): bool;
|
|
10
|
-
|
|
11
|
-
// @ts-ignore: Decorators *are* valid here
|
|
12
|
-
@global
|
|
13
|
-
export class Expectation<T> {
|
|
14
|
-
/**
|
|
15
|
-
* This i32 is set to 1 if the expectation is negated. Using the _not (xor) condition assertion
|
|
16
|
-
* makes assertions very easy to write and understand.
|
|
17
|
-
*/
|
|
18
|
-
_not: i32 = 0;
|
|
19
|
-
|
|
20
|
-
actual: T;
|
|
21
|
-
|
|
22
|
-
constructor(actual: T) {
|
|
23
|
-
this.actual = actual;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public get not(): Expectation<T> {
|
|
27
|
-
this._not = 1;
|
|
28
|
-
return this;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
public toBe(expected: T, message: string = ""): void {
|
|
32
|
-
let actual = this.actual;
|
|
33
|
-
let equals =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
let
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
ERROR(
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
"
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
assert(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
"
|
|
258
|
-
);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
assert(
|
|
272
|
-
i32(!isNaN(
|
|
273
|
-
"Value comparison fails,
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
let
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if (isFloat(actual)) {
|
|
311
|
-
assert(
|
|
312
|
-
i32(!isNaN(expected)),
|
|
313
|
-
"Value comparison fails, expected value is NaN.",
|
|
314
|
-
);
|
|
315
|
-
assert(
|
|
316
|
-
i32(!isNaN(actual)),
|
|
317
|
-
"Value comparison fails, actual value is NaN.",
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// do actual less than comparison
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
);
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
if (
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
Actual.
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
1
|
+
import { toIncludeComparison } from "./comparison/toIncludeComparison";
|
|
2
|
+
import { toIncludeEqualComparison } from "./comparison/toIncludeEqualComparison";
|
|
3
|
+
import { Actual } from "./Actual";
|
|
4
|
+
import { Expected } from "./Expected";
|
|
5
|
+
import { assert } from "./assert";
|
|
6
|
+
|
|
7
|
+
// @ts-ignore: Decorators *are* valid here
|
|
8
|
+
@external("__aspect", "tryCall")
|
|
9
|
+
declare function tryCall(func: () => void): bool;
|
|
10
|
+
|
|
11
|
+
// @ts-ignore: Decorators *are* valid here
|
|
12
|
+
@global
|
|
13
|
+
export class Expectation<T> {
|
|
14
|
+
/**
|
|
15
|
+
* This i32 is set to 1 if the expectation is negated. Using the _not (xor) condition assertion
|
|
16
|
+
* makes assertions very easy to write and understand.
|
|
17
|
+
*/
|
|
18
|
+
_not: i32 = 0;
|
|
19
|
+
|
|
20
|
+
actual: T;
|
|
21
|
+
|
|
22
|
+
constructor(actual: T) {
|
|
23
|
+
this.actual = actual;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public get not(): Expectation<T> {
|
|
27
|
+
this._not = 1;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public toBe(expected: T, message: string = ""): void {
|
|
32
|
+
let actual = this.actual;
|
|
33
|
+
let equals = 0;
|
|
34
|
+
|
|
35
|
+
if (isReference<T>()) {
|
|
36
|
+
if (isNullable<T>()) {
|
|
37
|
+
if (changetype<usize>(actual) == 0 && changetype<usize>(expected) == 0) {
|
|
38
|
+
equals = 1;
|
|
39
|
+
} else {
|
|
40
|
+
if (
|
|
41
|
+
i32(changetype<usize>(actual) == 0)
|
|
42
|
+
^ i32(changetype<usize>(expected) == 0)
|
|
43
|
+
) {
|
|
44
|
+
equals = 0;
|
|
45
|
+
} else {
|
|
46
|
+
equals = i32(actual! == expected!);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
equals = i32(actual == expected);
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
equals = i32(actual == expected);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let negated = this._not;
|
|
57
|
+
|
|
58
|
+
Actual.report(actual);
|
|
59
|
+
|
|
60
|
+
if (isReference(actual) && !isFunction(actual)) {
|
|
61
|
+
if (
|
|
62
|
+
!negated &&
|
|
63
|
+
changetype<usize>(actual) !== 0 &&
|
|
64
|
+
changetype<usize>(expected) !== 0 &&
|
|
65
|
+
Reflect.equals(actual, expected) == Reflect.SUCCESSFUL_MATCH
|
|
66
|
+
) {
|
|
67
|
+
Expected.report("Serializes to same value.", 0);
|
|
68
|
+
} else {
|
|
69
|
+
Expected.report(expected, negated);
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
Expected.report(expected, negated);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The assertion is either the items equal, or the expectation is negated
|
|
76
|
+
assert(equals ^ negated, message);
|
|
77
|
+
Actual.clear();
|
|
78
|
+
Expected.clear();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public toStrictEqual(expected: T, message: string = ""): void {
|
|
82
|
+
let result = Reflect.FAILED_MATCH;
|
|
83
|
+
result = Reflect.equals(this.actual, expected);
|
|
84
|
+
|
|
85
|
+
let equals = i32(result == Reflect.SUCCESSFUL_MATCH);
|
|
86
|
+
Actual.report(this.actual);
|
|
87
|
+
Expected.report(expected);
|
|
88
|
+
|
|
89
|
+
assert(equals ^ this._not, message);
|
|
90
|
+
|
|
91
|
+
Actual.clear();
|
|
92
|
+
Expected.clear();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// @as-covers: ignore because this function is deprecated
|
|
96
|
+
public toBlockEqual(expected: T, message: string = ""): void {
|
|
97
|
+
WARNING(
|
|
98
|
+
"toBlockEqual has been deprecated and results in a toStrictEqual call.",
|
|
99
|
+
);
|
|
100
|
+
this.toStrictEqual(expected, message);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public toBeTruthy(message: string = ""): void {
|
|
104
|
+
let actual = this.actual;
|
|
105
|
+
Actual.report(actual);
|
|
106
|
+
let negated = this._not;
|
|
107
|
+
Expected.reportTruthy(negated);
|
|
108
|
+
|
|
109
|
+
if (isReference(actual)) {
|
|
110
|
+
if (actual instanceof String) {
|
|
111
|
+
let truthy = i32(
|
|
112
|
+
changetype<usize>(actual) != 0 &&
|
|
113
|
+
changetype<string>(actual).length > 0,
|
|
114
|
+
);
|
|
115
|
+
assert(truthy ^ negated, message);
|
|
116
|
+
} else {
|
|
117
|
+
let truthy = i32(changetype<usize>(actual) != 0);
|
|
118
|
+
assert(truthy ^ negated, message);
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
if (isFloat(actual)) {
|
|
122
|
+
let truthy = i32(!isNaN(actual) && actual != 0.0);
|
|
123
|
+
assert(truthy ^ negated, message);
|
|
124
|
+
} else if (isInteger(actual)) {
|
|
125
|
+
let truthy = i32(actual != 0);
|
|
126
|
+
assert(truthy ^ negated, message);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
Actual.clear();
|
|
131
|
+
Expected.clear();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public toBeFalsy(message: string = ""): void {
|
|
135
|
+
let actual = this.actual;
|
|
136
|
+
Actual.report(actual);
|
|
137
|
+
let negated = this._not;
|
|
138
|
+
Expected.reportFalsy(negated);
|
|
139
|
+
|
|
140
|
+
if (isReference(actual)) {
|
|
141
|
+
// strings require an extra length check
|
|
142
|
+
if (actual instanceof String) {
|
|
143
|
+
let falsy = i32(
|
|
144
|
+
changetype<usize>(actual) == 0 ||
|
|
145
|
+
changetype<string>(actual).length == 0,
|
|
146
|
+
);
|
|
147
|
+
assert(falsy ^ negated, message);
|
|
148
|
+
} else {
|
|
149
|
+
let falsy = i32(changetype<usize>(actual) == 0);
|
|
150
|
+
assert(falsy ^ negated, message);
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
if (isFloat(actual)) {
|
|
154
|
+
// @ts-ignore: actual is a float value
|
|
155
|
+
let falsy = i32(isNaN(actual) || actual == 0.0);
|
|
156
|
+
assert(falsy ^ negated, message);
|
|
157
|
+
} else if (isInteger(actual)) {
|
|
158
|
+
let falsy = i32(actual == 0);
|
|
159
|
+
assert(falsy ^ negated, message);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
Actual.clear();
|
|
164
|
+
Expected.clear();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public toThrow(message: string = ""): void {
|
|
168
|
+
let actual = this.actual;
|
|
169
|
+
let negated = this._not;
|
|
170
|
+
|
|
171
|
+
if (!isFunction(actual)) {
|
|
172
|
+
// @as-covers: ignore because this is a compile time error
|
|
173
|
+
ERROR(nameof<T>());
|
|
174
|
+
ERROR(
|
|
175
|
+
"Expectation#toThrow assertion called on actual T where T is not a function reference",
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
if (idof<T>() != idof<() => void>())
|
|
179
|
+
// @as-covers: ignore because this is a compile time error
|
|
180
|
+
ERROR(
|
|
181
|
+
"Expectation#toThrow assertion called on actual T where T is not a function reference with signature () => void",
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
// @ts-ignore: safe tryCall
|
|
185
|
+
let throws = i32(!tryCall(actual));
|
|
186
|
+
Actual.report(throws ? "Throws" : "Not Throws");
|
|
187
|
+
Expected.report("Throws", negated);
|
|
188
|
+
assert(negated ^ throws, message);
|
|
189
|
+
Actual.clear();
|
|
190
|
+
Expected.clear();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public toBeGreaterThan(expected: T, message: string = ""): void {
|
|
194
|
+
let actual = this.actual;
|
|
195
|
+
let negated = this._not;
|
|
196
|
+
Actual.report(actual);
|
|
197
|
+
Expected.report(expected, negated);
|
|
198
|
+
|
|
199
|
+
if (!isDefined(actual > expected))
|
|
200
|
+
// @as-covers: ignore because this is a compile time error
|
|
201
|
+
ERROR(
|
|
202
|
+
"Invalid call to toBeGreaterThan. Generic type T must have an operator implemented for the greaterThan (>) operation.",
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
if (isReference(actual)) {
|
|
206
|
+
// Perform reference type null checks
|
|
207
|
+
assert(
|
|
208
|
+
i32(changetype<usize>(expected) != 0),
|
|
209
|
+
"Value comparison fails, expected value is null.",
|
|
210
|
+
);
|
|
211
|
+
assert(
|
|
212
|
+
i32(changetype<usize>(actual) != 0),
|
|
213
|
+
"Value comparison fails, actual value is null.",
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Compare float types
|
|
218
|
+
if (isFloat(actual)) {
|
|
219
|
+
assert(
|
|
220
|
+
i32(!isNaN(expected)),
|
|
221
|
+
"Value comparison fails, expected value is NaN.",
|
|
222
|
+
);
|
|
223
|
+
assert(
|
|
224
|
+
i32(!isNaN(actual)),
|
|
225
|
+
"Value comparison fails, actual value is NaN.",
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// do actual greater than comparison
|
|
230
|
+
if (isNullable(actual)) {
|
|
231
|
+
assert(negated ^ i32(actual! > expected!), message);
|
|
232
|
+
} else {
|
|
233
|
+
assert(negated ^ i32(actual > expected), message);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
Actual.clear();
|
|
237
|
+
Expected.clear();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
public toBeGreaterThanOrEqual(expected: T, message: string = ""): void {
|
|
241
|
+
let actual = this.actual;
|
|
242
|
+
let negated = this._not;
|
|
243
|
+
|
|
244
|
+
Actual.report(actual);
|
|
245
|
+
Expected.report(expected, negated);
|
|
246
|
+
|
|
247
|
+
if (!isDefined(actual >= expected))
|
|
248
|
+
// @as-covers: ignore because this is a compile time error
|
|
249
|
+
ERROR(
|
|
250
|
+
"Invalid call to toBeGreaterThanOrEqual. Generic type T must have an operator implemented for the greaterThanOrEqual (>=) operation.",
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
// null checks
|
|
254
|
+
if (isReference(actual)) {
|
|
255
|
+
assert(
|
|
256
|
+
i32(changetype<usize>(expected) != 0),
|
|
257
|
+
"Value comparison fails, expected value is null.",
|
|
258
|
+
);
|
|
259
|
+
assert(
|
|
260
|
+
i32(changetype<usize>(actual) != 0),
|
|
261
|
+
"Value comparison fails, actual value is null.",
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Compare float types
|
|
266
|
+
if (isFloat(actual)) {
|
|
267
|
+
assert(
|
|
268
|
+
i32(!isNaN(expected)),
|
|
269
|
+
"Value comparison fails, expected value is NaN.",
|
|
270
|
+
);
|
|
271
|
+
assert(
|
|
272
|
+
i32(!isNaN(actual)),
|
|
273
|
+
"Value comparison fails, actual value is NaN.",
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// do actual greater than comparison
|
|
278
|
+
if (isNullable(actual)) {
|
|
279
|
+
assert(negated ^ i32(actual! >= expected!), message);
|
|
280
|
+
} else {
|
|
281
|
+
assert(negated ^ i32(actual >= expected), message);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
Actual.clear();
|
|
285
|
+
Expected.clear();
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
public toBeLessThan(expected: T, message: string = ""): void {
|
|
289
|
+
let actual = this.actual;
|
|
290
|
+
let negated = this._not;
|
|
291
|
+
Actual.report(actual);
|
|
292
|
+
Expected.report(expected, negated);
|
|
293
|
+
|
|
294
|
+
if (!isDefined(actual < expected))
|
|
295
|
+
// @as-covers: ignore because this is a compile time error
|
|
296
|
+
ERROR(
|
|
297
|
+
"Invalid call to toBeLessThan. Generic type T must have an operator implemented for the lessThan (<) operation.",
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
// null checks
|
|
301
|
+
if (isReference(actual)) {
|
|
302
|
+
assert(
|
|
303
|
+
i32(changetype<usize>(expected) != 0),
|
|
304
|
+
"Value comparison fails, expected value is null.",
|
|
305
|
+
);
|
|
306
|
+
assert(
|
|
307
|
+
i32(changetype<usize>(actual) != 0),
|
|
308
|
+
"Value comparison fails, actual value is null.",
|
|
309
|
+
);
|
|
310
|
+
} else if (isFloat(actual)) {
|
|
311
|
+
assert(
|
|
312
|
+
i32(!isNaN(expected)),
|
|
313
|
+
"Value comparison fails, expected value is NaN.",
|
|
314
|
+
);
|
|
315
|
+
assert(
|
|
316
|
+
i32(!isNaN(actual)),
|
|
317
|
+
"Value comparison fails, actual value is NaN.",
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// do actual less than comparison
|
|
322
|
+
if (isNullable(actual)) {
|
|
323
|
+
assert(negated ^ i32(actual! < expected!), message);
|
|
324
|
+
} else {
|
|
325
|
+
assert(negated ^ i32(actual < expected), message);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
Actual.clear();
|
|
329
|
+
Expected.clear();
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
public toBeLessThanOrEqual(expected: T, message: string = ""): void {
|
|
333
|
+
let actual = this.actual;
|
|
334
|
+
let negated = this._not;
|
|
335
|
+
Actual.report(actual);
|
|
336
|
+
Expected.report(expected, negated);
|
|
337
|
+
|
|
338
|
+
if (!isDefined(actual <= expected))
|
|
339
|
+
// @as-covers: ignore because this is a compile time error
|
|
340
|
+
ERROR(
|
|
341
|
+
"Invalid call to toBeLessThanOrEqual. Generic type T must have an operator implemented for the lessThanOrEqual (<=) operation.",
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
// null checks
|
|
345
|
+
if (isReference(actual)) {
|
|
346
|
+
assert(
|
|
347
|
+
i32(changetype<usize>(expected) != 0),
|
|
348
|
+
"Value comparison fails, expected value is null.",
|
|
349
|
+
);
|
|
350
|
+
assert(
|
|
351
|
+
i32(changetype<usize>(actual) != 0),
|
|
352
|
+
"Value comparison fails, actual value is null.",
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (isFloat(actual)) {
|
|
357
|
+
assert(
|
|
358
|
+
i32(!isNaN(expected)),
|
|
359
|
+
"Value comparison fails, expected value is NaN.",
|
|
360
|
+
);
|
|
361
|
+
assert(
|
|
362
|
+
i32(!isNaN(actual)),
|
|
363
|
+
"Value comparison fails, actual value is NaN.",
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// do actual less than comparison
|
|
368
|
+
if (isNullable(actual)) {
|
|
369
|
+
assert(negated ^ i32(actual! <= expected!), message);
|
|
370
|
+
} else {
|
|
371
|
+
assert(negated ^ i32(actual <= expected), message);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
Actual.clear();
|
|
375
|
+
Expected.clear();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
public toBeNull(message: string = ""): void {
|
|
379
|
+
let negated = this._not;
|
|
380
|
+
let actual = this.actual;
|
|
381
|
+
|
|
382
|
+
if (actual instanceof usize) {
|
|
383
|
+
Actual.report(actual);
|
|
384
|
+
Expected.report(<usize>0, negated);
|
|
385
|
+
// @ts-ignore: actual is instanceof number type
|
|
386
|
+
assert(negated ^ i32(actual == 0), message);
|
|
387
|
+
Actual.clear();
|
|
388
|
+
Expected.clear();
|
|
389
|
+
} else if (isReference(actual)) {
|
|
390
|
+
Actual.report(actual);
|
|
391
|
+
|
|
392
|
+
Expected.report(changetype<T>(0), negated);
|
|
393
|
+
assert(negated ^ i32(changetype<usize>(actual) == 0), message);
|
|
394
|
+
Actual.clear();
|
|
395
|
+
Expected.clear();
|
|
396
|
+
// @as-covers: ignore because this is a compile time error
|
|
397
|
+
} else {
|
|
398
|
+
ERROR(
|
|
399
|
+
"toBeNull assertion must be called with a reference type T or usize.",
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
public toBeCloseTo(
|
|
405
|
+
expected: T,
|
|
406
|
+
decimalPlaces: i32 = 2,
|
|
407
|
+
message: string = "",
|
|
408
|
+
): void {
|
|
409
|
+
let actual = this.actual;
|
|
410
|
+
let negated = this._not;
|
|
411
|
+
|
|
412
|
+
// must be called on a float T
|
|
413
|
+
if (!isFloat(actual))
|
|
414
|
+
// @as-covers: ignore because this is a compile time error
|
|
415
|
+
ERROR("toBeCloseTo must be called with a Float value type T.");
|
|
416
|
+
Actual.report(actual);
|
|
417
|
+
Expected.report(expected, negated);
|
|
418
|
+
|
|
419
|
+
// both actual and expected values must be finite
|
|
420
|
+
assert(
|
|
421
|
+
i32(isFinite(actual)),
|
|
422
|
+
"toBeCloseTo assertion fails because a actual value is not finite",
|
|
423
|
+
);
|
|
424
|
+
assert(
|
|
425
|
+
i32(isFinite(expected)),
|
|
426
|
+
"toBeCloseTo assertion fails because expected value is not finite.",
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
// calculated: `|expected - actual| < 1 / numberOfDigits`.
|
|
430
|
+
// @ts-ignore tooling errors because T does not extend a numeric value type. This compiles just fine.
|
|
431
|
+
let isClose = i32(abs(expected - actual) < Math.pow(10, -decimalPlaces));
|
|
432
|
+
assert(negated ^ isClose, message);
|
|
433
|
+
Actual.clear();
|
|
434
|
+
Expected.clear();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
public toBeNaN(message: string = ""): void {
|
|
438
|
+
let actual = this.actual;
|
|
439
|
+
let negated = this._not;
|
|
440
|
+
|
|
441
|
+
// must be called on a float T
|
|
442
|
+
if (!isFloat(actual))
|
|
443
|
+
// @as-covers: ignore because this is a compile time error
|
|
444
|
+
ERROR("toBeNaN must be called with a Float value type T.");
|
|
445
|
+
Actual.report(actual);
|
|
446
|
+
|
|
447
|
+
// @ts-ignore: The compiler should pass bit count (64/32 bit float to the report function)
|
|
448
|
+
Expected.report<T>(NaN, negated);
|
|
449
|
+
|
|
450
|
+
let isNaNValue = i32(isNaN(actual));
|
|
451
|
+
assert(isNaNValue ^ negated, message);
|
|
452
|
+
Actual.clear();
|
|
453
|
+
Expected.clear();
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
public toBeFinite(message: string = ""): void {
|
|
457
|
+
let actual = this.actual;
|
|
458
|
+
let negated = this._not;
|
|
459
|
+
|
|
460
|
+
// must be called on a float T
|
|
461
|
+
if (!isFloat(actual))
|
|
462
|
+
// @as-covers: ignore because this is a compile time error
|
|
463
|
+
ERROR("toBeNaN must be called with a Float value type T.");
|
|
464
|
+
Actual.report(actual);
|
|
465
|
+
Expected.reportFinite(negated);
|
|
466
|
+
|
|
467
|
+
let isFiniteValue = i32(isFinite(actual));
|
|
468
|
+
assert(isFiniteValue ^ negated, message);
|
|
469
|
+
Actual.clear();
|
|
470
|
+
Expected.clear();
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
public toHaveLength(expected: i32, message: string = ""): void {
|
|
474
|
+
let actual = this.actual;
|
|
475
|
+
let negated = this._not;
|
|
476
|
+
let length = 0;
|
|
477
|
+
if (actual instanceof ArrayBuffer) {
|
|
478
|
+
length = actual.byteLength;
|
|
479
|
+
} else {
|
|
480
|
+
// @ts-ignore: This results in a compile time check for a length property with a better error message
|
|
481
|
+
if (!isDefined(actual.length))
|
|
482
|
+
// @as-covers: ignore because this is a compile time error
|
|
483
|
+
ERROR(
|
|
484
|
+
"toHaveLength cannot be called on type T where T.length is not defined.",
|
|
485
|
+
);
|
|
486
|
+
if (isNullable(actual)) {
|
|
487
|
+
// @ts-ignore: This results in a compile time check for a length property with a better error message
|
|
488
|
+
length = <i32>actual!.length;
|
|
489
|
+
} else {
|
|
490
|
+
// @ts-ignore: This results in a compile time check for a length property with a better error message
|
|
491
|
+
length = <i32>actual.length;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
Actual.report(length);
|
|
496
|
+
Expected.report(expected, negated);
|
|
497
|
+
|
|
498
|
+
let lengthsEqual = i32(length == expected);
|
|
499
|
+
assert(lengthsEqual ^ negated, message);
|
|
500
|
+
Actual.clear();
|
|
501
|
+
Expected.clear();
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
public toInclude<U>(expected: U, message: string = ""): void {
|
|
505
|
+
toIncludeComparison<T, U>(this.actual, expected, this._not, message);
|
|
506
|
+
Actual.clear();
|
|
507
|
+
Expected.clear();
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// @ts-ignore: valueof<T> requires that T extends something with an @operator("[]")
|
|
511
|
+
// @as-covers: ignore because this is just an alias function
|
|
512
|
+
public toContain(expected: valueof<T>, message: string = ""): void {
|
|
513
|
+
this.toInclude(expected, message);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
public toIncludeEqual<U>(expected: U, message: string = ""): void {
|
|
517
|
+
toIncludeEqualComparison<T, U>(this.actual, expected, this._not, message);
|
|
518
|
+
Actual.clear();
|
|
519
|
+
Expected.clear();
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// @as-covers: ignore because this is an alias
|
|
523
|
+
public toContainEqual<U>(expected: U, message: string = ""): void {
|
|
524
|
+
this.toIncludeEqual(expected, message);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
public toMatchSnapshot(name: string | null = null): void {
|
|
528
|
+
assert(i32(!this._not), "Snapshots cannot be negated.");
|
|
529
|
+
Expected.reportSnapshot(this.actual, name);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// @ts-ignore: decorators *are* valid here
|
|
534
|
+
@global
|
|
535
|
+
export function expect<T>(actual: T): Expectation<T> {
|
|
536
|
+
return new Expectation(actual);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// @ts-ignore: decorators *are* valid here
|
|
540
|
+
// @as-covers: ignore because this is deprecated
|
|
541
|
+
@global export function expectFn(cb: () => void): Expectation<() => void> {
|
|
542
|
+
WARNING("expectFn() has been deprecated. Use expect() instead.");
|
|
543
|
+
return new Expectation(cb);
|
|
544
|
+
}
|