@locustjs/test 1.4.0 → 1.6.0

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/index.esm.js CHANGED
@@ -16,19 +16,27 @@ import {
16
16
  isIterable,
17
17
  isSomeArray,
18
18
  isSubClassOf,
19
+ isNullOrEmpty,
19
20
  } from "@locustjs/base";
20
21
  import { Exception } from "@locustjs/exception";
21
22
  import fs from "fs";
22
23
  import path from "path";
23
24
 
25
+ class TestException extends Exception {}
24
26
  class Expect {
25
27
  constructor(value) {
26
28
  this.value = value;
29
+ this._expected = false;
30
+ }
31
+ get expected() {
32
+ return this._expected;
27
33
  }
28
34
  toBe(value) {
35
+ this._expected = true;
36
+
29
37
  if (this.value === value) {
30
38
  } else {
31
- throw new Exception({
39
+ throw new TestException({
32
40
  message: `${this.value} is not equal to ${value}`,
33
41
  code: 1000,
34
42
  status: "not-eq",
@@ -37,9 +45,24 @@ class Expect {
37
45
 
38
46
  return this;
39
47
  }
48
+ notToBe(value) {
49
+ this._expected = true;
50
+
51
+ if (this.value === value) {
52
+ throw new TestException({
53
+ message: `${value} is equal to ${this.value}`,
54
+ code: 1005,
55
+ status: "eq",
56
+ });
57
+ }
58
+
59
+ return this;
60
+ }
40
61
  toBeGt(value) {
62
+ this._expected = true;
63
+
41
64
  if (this.value <= value) {
42
- throw new Exception({
65
+ throw new TestException({
43
66
  message: `${this.value} is not greater than ${value}`,
44
67
  code: 1001,
45
68
  status: "lte",
@@ -52,8 +75,10 @@ class Expect {
52
75
  return this.toBeGt(value);
53
76
  }
54
77
  toBeGte(value) {
78
+ this._expected = true;
79
+
55
80
  if (this.value < value) {
56
- throw new Exception({
81
+ throw new TestException({
57
82
  message: `${this.value} is not greater than or equal to ${value}`,
58
83
  code: 1002,
59
84
  status: "lt",
@@ -66,8 +91,10 @@ class Expect {
66
91
  return this.toBeGte(value);
67
92
  }
68
93
  toBeLt(value) {
94
+ this._expected = true;
95
+
69
96
  if (this.value >= value) {
70
- throw new Exception({
97
+ throw new TestException({
71
98
  message: `${this.value} is not less than ${value}`,
72
99
  code: 1003,
73
100
  status: "gte",
@@ -80,8 +107,10 @@ class Expect {
80
107
  return this.toBeLt(value);
81
108
  }
82
109
  toBeLte(value) {
110
+ this._expected = true;
111
+
83
112
  if (this.value > value) {
84
- throw new Exception({
113
+ throw new TestException({
85
114
  message: `${this.value} is not less than or equal to ${value}`,
86
115
  code: 1004,
87
116
  status: "gt",
@@ -94,8 +123,10 @@ class Expect {
94
123
  return this.toBeLte(value);
95
124
  }
96
125
  toBeBetween(n, m) {
126
+ this._expected = true;
127
+
97
128
  if (!(this.value >= n && this.value < m)) {
98
- throw new Exception({
129
+ throw new TestException({
99
130
  message: `${this.value} is not between ${n} and ${m}`,
100
131
  code: 1024,
101
132
  status: "between",
@@ -104,9 +135,24 @@ class Expect {
104
135
 
105
136
  return this;
106
137
  }
138
+ notToBeBetween(n, m) {
139
+ this._expected = true;
140
+
141
+ if (this.value >= n && this.value < m) {
142
+ throw new TestException({
143
+ message: `${this.value} is between ${n} and ${m}`,
144
+ code: 1044,
145
+ status: "not-between",
146
+ });
147
+ }
148
+
149
+ return this;
150
+ }
107
151
  toBeOfType(type) {
152
+ this._expected = true;
153
+
108
154
  if (typeof this.value !== type) {
109
- throw new Exception({
155
+ throw new TestException({
110
156
  message: `${this.value} is not of type ${type}`,
111
157
  code: 1025,
112
158
  status: "of-type",
@@ -115,9 +161,24 @@ class Expect {
115
161
 
116
162
  return this;
117
163
  }
164
+ notToBeOfType(type) {
165
+ this._expected = true;
166
+
167
+ if (typeof this.value === type) {
168
+ throw new TestException({
169
+ message: `${this.value} is of type ${type}`,
170
+ code: 1045,
171
+ status: "not-oftype",
172
+ });
173
+ }
174
+
175
+ return this;
176
+ }
118
177
  toBeString() {
178
+ this._expected = true;
179
+
119
180
  if (!isString(this.value)) {
120
- throw new Exception({
181
+ throw new TestException({
121
182
  message: `${this.value} is not string`,
122
183
  code: 1026,
123
184
  status: "is-string",
@@ -126,9 +187,23 @@ class Expect {
126
187
 
127
188
  return this;
128
189
  }
190
+ notToBeString() {
191
+ this._expected = true;
192
+
193
+ if (isString(this.value)) {
194
+ throw new TestException({
195
+ message: `${this.value} is string`,
196
+ code: 1046,
197
+ status: "not-is-string",
198
+ });
199
+ }
200
+
201
+ return this;
202
+ }
129
203
  toBeSomeString() {
204
+ this._expected = true;
130
205
  if (!isSomeString(this.value)) {
131
- throw new Exception({
206
+ throw new TestException({
132
207
  message: `${this.value} is not some string`,
133
208
  code: 1027,
134
209
  status: "is-some-string",
@@ -137,9 +212,24 @@ class Expect {
137
212
 
138
213
  return this;
139
214
  }
215
+ notToBeSomeString() {
216
+ this._expected = true;
217
+
218
+ if (isSomeString(this.value)) {
219
+ throw new TestException({
220
+ message: `${this.value} is some string`,
221
+ code: 1047,
222
+ status: "not-is-some-string",
223
+ });
224
+ }
225
+
226
+ return this;
227
+ }
140
228
  toBeNumber() {
229
+ this._expected = true;
230
+
141
231
  if (!isNumber(this.value)) {
142
- throw new Exception({
232
+ throw new TestException({
143
233
  message: `${this.value} is not number`,
144
234
  code: 1028,
145
235
  status: "is-number",
@@ -148,9 +238,24 @@ class Expect {
148
238
 
149
239
  return this;
150
240
  }
241
+ notToBeNumber() {
242
+ this._expected = true;
243
+
244
+ if (isNumber(this.value)) {
245
+ throw new TestException({
246
+ message: `${this.value} is number`,
247
+ code: 1048,
248
+ status: "not-is-number",
249
+ });
250
+ }
251
+
252
+ return this;
253
+ }
151
254
  toBeDate() {
255
+ this._expected = true;
256
+
152
257
  if (!isDate(this.value)) {
153
- throw new Exception({
258
+ throw new TestException({
154
259
  message: `${this.value} is not date`,
155
260
  code: 1029,
156
261
  status: "is-date",
@@ -159,9 +264,24 @@ class Expect {
159
264
 
160
265
  return this;
161
266
  }
267
+ notToBeDate() {
268
+ this._expected = true;
269
+
270
+ if (isDate(this.value)) {
271
+ throw new TestException({
272
+ message: `${this.value} is date`,
273
+ code: 1049,
274
+ status: "not-is-date",
275
+ });
276
+ }
277
+
278
+ return this;
279
+ }
162
280
  toBeBool() {
281
+ this._expected = true;
282
+
163
283
  if (!isBool(this.value)) {
164
- throw new Exception({
284
+ throw new TestException({
165
285
  message: `${this.value} is not bool`,
166
286
  code: 1030,
167
287
  status: "is-bool",
@@ -170,9 +290,24 @@ class Expect {
170
290
 
171
291
  return this;
172
292
  }
293
+ notToBeBool() {
294
+ this._expected = true;
295
+
296
+ if (isBool(this.value)) {
297
+ throw new TestException({
298
+ message: `${this.value} is bool`,
299
+ code: 1050,
300
+ status: "not-is-bool",
301
+ });
302
+ }
303
+
304
+ return this;
305
+ }
173
306
  toBeBasicType() {
307
+ this._expected = true;
308
+
174
309
  if (!isBasic(this.value)) {
175
- throw new Exception({
310
+ throw new TestException({
176
311
  message: `${this.value} is not basic type`,
177
312
  code: 1031,
178
313
  status: "is-basic-type",
@@ -181,9 +316,24 @@ class Expect {
181
316
 
182
317
  return this;
183
318
  }
319
+ notToBeBasicType() {
320
+ this._expected = true;
321
+
322
+ if (isBasic(this.value)) {
323
+ throw new TestException({
324
+ message: `${this.value} is basic type`,
325
+ code: 1051,
326
+ status: "not-is-basic-type",
327
+ });
328
+ }
329
+
330
+ return this;
331
+ }
184
332
  toBePrimitive() {
333
+ this._expected = true;
334
+
185
335
  if (!isPrimitive(this.value)) {
186
- throw new Exception({
336
+ throw new TestException({
187
337
  message: `${this.value} is not primitive type`,
188
338
  code: 1032,
189
339
  status: "is-primitive",
@@ -192,9 +342,24 @@ class Expect {
192
342
 
193
343
  return this;
194
344
  }
345
+ notToBePrimitive() {
346
+ this._expected = true;
347
+
348
+ if (isPrimitive(this.value)) {
349
+ throw new TestException({
350
+ message: `${this.value} is primitive type`,
351
+ code: 1052,
352
+ status: "not-is-primitive",
353
+ });
354
+ }
355
+
356
+ return this;
357
+ }
195
358
  toBeEmpty() {
359
+ this._expected = true;
360
+
196
361
  if (!isEmpty(this.value)) {
197
- throw new Exception({
362
+ throw new TestException({
198
363
  message: `${this.value} is not empty`,
199
364
  code: 1033,
200
365
  status: "is-empty",
@@ -203,9 +368,24 @@ class Expect {
203
368
 
204
369
  return this;
205
370
  }
371
+ notToBeEmpty() {
372
+ this._expected = true;
373
+
374
+ if (isEmpty(this.value)) {
375
+ throw new TestException({
376
+ message: `${this.value} is empty`,
377
+ code: 1053,
378
+ status: "not-is-empty",
379
+ });
380
+ }
381
+
382
+ return this;
383
+ }
206
384
  toBeObject() {
385
+ this._expected = true;
386
+
207
387
  if (!isObject(this.value)) {
208
- throw new Exception({
388
+ throw new TestException({
209
389
  message: `${this.value} is not object`,
210
390
  code: 1034,
211
391
  status: "is-object",
@@ -214,9 +394,24 @@ class Expect {
214
394
 
215
395
  return this;
216
396
  }
397
+ notToBeObject() {
398
+ this._expected = true;
399
+
400
+ if (isObject(this.value)) {
401
+ throw new TestException({
402
+ message: `${this.value} is object`,
403
+ code: 1054,
404
+ status: "not-is-object",
405
+ });
406
+ }
407
+
408
+ return this;
409
+ }
217
410
  toBeSomeObject() {
411
+ this._expected = true;
412
+
218
413
  if (!isSomeObject(this.value)) {
219
- throw new Exception({
414
+ throw new TestException({
220
415
  message: `${this.value} is not some object`,
221
416
  code: 1035,
222
417
  status: "is-some-object",
@@ -225,9 +420,24 @@ class Expect {
225
420
 
226
421
  return this;
227
422
  }
423
+ notToBeSomeObject() {
424
+ this._expected = true;
425
+
426
+ if (isSomeObject(this.value)) {
427
+ throw new TestException({
428
+ message: `${this.value} is some object`,
429
+ code: 1055,
430
+ status: "not-is-some-object",
431
+ });
432
+ }
433
+
434
+ return this;
435
+ }
228
436
  toBeFunction() {
437
+ this._expected = true;
438
+
229
439
  if (!isFunction(this.value)) {
230
- throw new Exception({
440
+ throw new TestException({
231
441
  message: `${this.value} is not function`,
232
442
  code: 1036,
233
443
  status: "is-function",
@@ -236,395 +446,357 @@ class Expect {
236
446
 
237
447
  return this;
238
448
  }
239
- toBeNumeric() {
240
- if (!isNumeric(this.value)) {
241
- throw new Exception({
242
- message: `${this.value} is not numeric`,
243
- code: 1037,
244
- status: "is-numeric",
245
- });
246
- }
449
+ notToBeFunction() {
450
+ this._expected = true;
247
451
 
248
- return this;
249
- }
250
- toBeArray() {
251
- if (!isArray(this.value)) {
252
- throw new Exception({
253
- message: `${this.value} is not array`,
254
- code: 1038,
255
- status: "is-array",
452
+ if (isFunction(this.value)) {
453
+ throw new TestException({
454
+ message: `${this.value} is function`,
455
+ code: 1056,
456
+ status: "not-is-function",
256
457
  });
257
458
  }
258
459
 
259
460
  return this;
260
461
  }
261
- toBeSomeArray() {
262
- if (!isSomeArray(this.value)) {
263
- throw new Exception({
264
- message: `${this.value} is not some array`,
265
- code: 1039,
266
- status: "is-some-array",
267
- });
268
- }
462
+ toBeNumeric() {
463
+ this._expected = true;
269
464
 
270
- return this;
271
- }
272
- toBeIterable() {
273
- if (!isIterable(this.value)) {
274
- throw new Exception({
275
- message: `${this.value} is not iterable`,
276
- code: 1040,
277
- status: "is-iterable",
465
+ if (!isNumeric(this.value)) {
466
+ throw new TestException({
467
+ message: `${this.value} is not numeric`,
468
+ code: 1037,
469
+ status: "is-numeric",
278
470
  });
279
471
  }
280
472
 
281
473
  return this;
282
474
  }
283
- toBeSubClassOf(type) {
284
- if (!isSubClassOf(this.value, type)) {
285
- throw new Exception({
286
- message: `${this.value} is not subclass of ${type}`,
287
- code: 1041,
288
- status: "is-subclass-of",
289
- });
290
- }
475
+ notToBeNumeric() {
476
+ this._expected = true;
291
477
 
292
- return this;
293
- }
294
- toBeInstanceOf(type) {
295
- if (!(this.value instanceof type)) {
296
- throw new Exception({
297
- message: `${this.value} is not instance of ${type}`,
298
- code: 1042,
299
- status: "instanceof",
478
+ if (isNumeric(this.value)) {
479
+ throw new TestException({
480
+ message: `${this.value} is numeric`,
481
+ code: 1057,
482
+ status: "not-is-numeric",
300
483
  });
301
484
  }
302
485
 
303
486
  return this;
304
487
  }
305
- toMatch(pattern, flags) {
306
- const r = new RegExp(pattern, flags);
488
+ toBeArray() {
489
+ this._expected = true;
307
490
 
308
- if (!r.test(this.value)) {
309
- throw new Exception({
310
- message: `${this.value} does not match ${pattern}`,
311
- code: 1043,
312
- status: "match",
491
+ if (!isArray(this.value)) {
492
+ throw new TestException({
493
+ message: `${this.value} is not array`,
494
+ code: 1038,
495
+ status: "is-array",
313
496
  });
314
497
  }
315
498
 
316
499
  return this;
317
500
  }
318
- notToBe(value) {
319
- if (this.value === value) {
320
- throw new Exception({
321
- message: `${value} is equal to ${this.value}`,
322
- code: 1005,
323
- status: "eq",
324
- });
325
- }
501
+ notToBeArray() {
502
+ this._expected = true;
326
503
 
327
- return this;
328
- }
329
- toBeDefined() {
330
- if (this.value === undefined) {
331
- throw new Exception({
332
- message: `value is undefined`,
333
- code: 1006,
334
- status: "undefined",
504
+ if (isArray(this.value)) {
505
+ throw new TestException({
506
+ message: `${this.value} is array`,
507
+ code: 1058,
508
+ status: "not-is-array",
335
509
  });
336
510
  }
337
511
 
338
512
  return this;
339
513
  }
340
- toBeUndefined() {
341
- if (this.value !== undefined) {
342
- throw new Exception({
343
- message: `value is defined`,
344
- code: 1007,
345
- status: "defined",
346
- });
347
- }
514
+ toBeSomeArray() {
515
+ this._expected = true;
348
516
 
349
- return this;
350
- }
351
- toBeNull() {
352
- if (this.value !== null) {
353
- throw new Exception({
354
- message: `value is not null`,
355
- code: 1008,
356
- status: "not-null",
517
+ if (!isSomeArray(this.value)) {
518
+ throw new TestException({
519
+ message: `${this.value} is not some array`,
520
+ code: 1039,
521
+ status: "is-some-array",
357
522
  });
358
523
  }
359
524
 
360
525
  return this;
361
526
  }
362
- notToBeNull() {
363
- if (this.value === null) {
364
- throw new Exception({
365
- message: `value is null`,
366
- code: 1009,
367
- status: "null",
368
- });
369
- }
527
+ notToBeSomeArray() {
528
+ this._expected = true;
370
529
 
371
- return this;
372
- }
373
- toBeNullOrUndefined() {
374
- if (this.value == null) {
375
- } else {
376
- throw new Exception({
377
- message: `value is not null/undefined`,
378
- code: 1010,
379
- status: "not-null-or-undefined",
530
+ if (isArray(this.value)) {
531
+ throw new TestException({
532
+ message: `${this.value} is array`,
533
+ code: 1068,
534
+ status: "is-array",
380
535
  });
381
536
  }
382
-
383
- return this;
384
- }
385
- notToBeNullOrUndefined() {
386
- if (this.value == null) {
387
- throw new Exception({
388
- message: `value is null/undefined`,
389
- code: 1011,
390
- status: "null-or-undefined",
537
+ if (this.value.length) {
538
+ throw new TestException({
539
+ message: `${this.value} is array`,
540
+ code: 1069,
541
+ status: "is-some-array",
391
542
  });
392
543
  }
393
544
 
394
545
  return this;
395
546
  }
396
- notToBeBetween(n, m) {
397
- if (this.value >= n && this.value < m) {
398
- throw new Exception({
399
- message: `${this.value} is between ${n} and ${m}`,
400
- code: 1044,
401
- status: "not-between",
402
- });
403
- }
547
+ toBeIterable() {
548
+ this._expected = true;
404
549
 
405
- return this;
406
- }
407
- notToBeOfType(type) {
408
- if (typeof this.value === type) {
409
- throw new Exception({
410
- message: `${this.value} is of type ${type}`,
411
- code: 1045,
412
- status: "not-oftype",
550
+ if (!isIterable(this.value)) {
551
+ throw new TestException({
552
+ message: `${this.value} is not iterable`,
553
+ code: 1040,
554
+ status: "is-iterable",
413
555
  });
414
556
  }
415
557
 
416
558
  return this;
417
559
  }
418
- notToBeString() {
419
- if (isString(this.value)) {
420
- throw new Exception({
421
- message: `${this.value} is string`,
422
- code: 1046,
423
- status: "not-is-string",
560
+ notToBeIterable() {
561
+ this._expected = true;
562
+
563
+ if (isIterable(this.value)) {
564
+ throw new TestException({
565
+ message: `${this.value} is iterable`,
566
+ code: 1060,
567
+ status: "not-iterable",
424
568
  });
425
569
  }
426
570
 
427
571
  return this;
428
572
  }
429
- notToBeSomeString() {
430
- if (isSomeString(this.value)) {
431
- throw new Exception({
432
- message: `${this.value} is some string`,
433
- code: 1047,
434
- status: "not-is-some-string",
573
+ toBeSubClassOf(type) {
574
+ this._expected = true;
575
+
576
+ if (!isSubClassOf(this.value, type)) {
577
+ throw new TestException({
578
+ message: `${this.value} is not subclass of ${type}`,
579
+ code: 1041,
580
+ status: "is-subclass-of",
435
581
  });
436
582
  }
437
583
 
438
584
  return this;
439
585
  }
440
- notToBeNumber() {
441
- if (isNumber(this.value)) {
442
- throw new Exception({
443
- message: `${this.value} is number`,
444
- code: 1048,
445
- status: "not-is-number",
446
- });
447
- }
586
+ notToBeSubClassOf(type) {
587
+ this._expected = true;
448
588
 
449
- return this;
450
- }
451
- notToBeDate() {
452
- if (isDate(this.value)) {
453
- throw new Exception({
454
- message: `${this.value} is date`,
455
- code: 1049,
456
- status: "not-is-date",
589
+ if (isSubClassOf(this.value, type)) {
590
+ throw new TestException({
591
+ message: `${this.value} is subclass of ${type}`,
592
+ code: 1061,
593
+ status: "not-subclassof",
457
594
  });
458
595
  }
459
596
 
460
597
  return this;
461
598
  }
462
- notToBeBool() {
463
- if (isBool(this.value)) {
464
- throw new Exception({
465
- message: `${this.value} is bool`,
466
- code: 1050,
467
- status: "not-is-bool",
599
+ toBeInstanceOf(type) {
600
+ this._expected = true;
601
+
602
+ if (!(this.value instanceof type)) {
603
+ throw new TestException({
604
+ message: `${this.value} is not instance of ${type}`,
605
+ code: 1042,
606
+ status: "instanceof",
468
607
  });
469
608
  }
470
609
 
471
610
  return this;
472
611
  }
473
- notToBeBasicType() {
474
- if (isBasic(this.value)) {
475
- throw new Exception({
476
- message: `${this.value} is basic type`,
477
- code: 1051,
478
- status: "not-is-basic-type",
612
+ notToBeInstanceOf(type) {
613
+ this._expected = true;
614
+
615
+ if (this.value instanceof type) {
616
+ throw new TestException({
617
+ message: `${this.value} is instance of ${type}`,
618
+ code: 1062,
619
+ status: "not-instanceof",
479
620
  });
480
621
  }
481
622
 
482
623
  return this;
483
624
  }
484
- notToBePrimitive() {
485
- if (isPrimitive(this.value)) {
486
- throw new Exception({
487
- message: `${this.value} is primitive type`,
488
- code: 1052,
489
- status: "not-is-primitive",
625
+ toMatch(pattern, flags) {
626
+ this._expected = true;
627
+
628
+ const r = new RegExp(pattern, flags);
629
+
630
+ if (!r.test(this.value)) {
631
+ throw new TestException({
632
+ message: `${this.value} does not match ${pattern}`,
633
+ code: 1043,
634
+ status: "match",
490
635
  });
491
636
  }
492
637
 
493
638
  return this;
494
639
  }
495
- notToBeEmpty() {
496
- if (isEmpty(this.value)) {
497
- throw new Exception({
498
- message: `${this.value} is empty`,
499
- code: 1053,
500
- status: "not-is-empty",
640
+ notToMatch(pattern, flags) {
641
+ this._expected = true;
642
+
643
+ const r = new RegExp(pattern, flags);
644
+
645
+ if (r.test(this.value)) {
646
+ throw new TestException({
647
+ message: `${this.value} matches ${pattern}`,
648
+ code: 1070,
649
+ status: "match",
501
650
  });
502
651
  }
503
652
 
504
653
  return this;
505
654
  }
506
- notToBeObject() {
507
- if (isObject(this.value)) {
508
- throw new Exception({
509
- message: `${this.value} is object`,
510
- code: 1054,
511
- status: "not-is-object",
655
+ doesNotMatch(pattern, flags) {
656
+ this._expected = true;
657
+
658
+ const r = new RegExp(pattern, flags);
659
+
660
+ if (r.test(this.value)) {
661
+ throw new TestException({
662
+ message: `${this.value} matches ${pattern}`,
663
+ code: 1063,
664
+ status: "not-match",
512
665
  });
513
666
  }
514
667
 
515
668
  return this;
516
669
  }
517
- notToBeSomeObject() {
518
- if (isSomeObject(this.value)) {
519
- throw new Exception({
520
- message: `${this.value} is some object`,
521
- code: 1055,
522
- status: "not-is-some-object",
670
+ toBeDefined() {
671
+ this._expected = true;
672
+
673
+ if (this.value === undefined) {
674
+ throw new TestException({
675
+ message: `value is undefined`,
676
+ code: 1006,
677
+ status: "undefined",
523
678
  });
524
679
  }
525
680
 
526
681
  return this;
527
682
  }
528
- notToBeFunction() {
529
- if (isFunction(this.value)) {
530
- throw new Exception({
531
- message: `${this.value} is function`,
532
- code: 1056,
533
- status: "not-is-function",
683
+ notToBeDefined() {
684
+ this._expected = true;
685
+
686
+ if (this.value !== undefined) {
687
+ throw new TestException({
688
+ message: `value is defined`,
689
+ code: 1071,
690
+ status: "defined",
534
691
  });
535
692
  }
536
693
 
537
694
  return this;
538
695
  }
539
- notToBeNumeric() {
540
- if (isNumeric(this.value)) {
541
- throw new Exception({
542
- message: `${this.value} is numeric`,
543
- code: 1057,
544
- status: "not-is-numeric",
696
+ toBeUndefined() {
697
+ this._expected = true;
698
+
699
+ if (this.value !== undefined) {
700
+ throw new TestException({
701
+ message: `value is defined`,
702
+ code: 1007,
703
+ status: "defined",
545
704
  });
546
705
  }
547
706
 
548
707
  return this;
549
708
  }
550
- notToBeArray() {
551
- if (isArray(this.value)) {
552
- throw new Exception({
553
- message: `${this.value} is array`,
554
- code: 1058,
555
- status: "not-is-array",
709
+ notToBeUndefined() {
710
+ this._expected = true;
711
+
712
+ if (this.value === undefined) {
713
+ throw new TestException({
714
+ message: `value is undefined`,
715
+ code: 1072,
716
+ status: "undefined",
556
717
  });
557
718
  }
558
719
 
559
720
  return this;
560
721
  }
561
- toBeEmptyArray() {
562
- if (isSomeArray(this.value)) {
563
- throw new Exception({
564
- message: `${this.value} is some array`,
565
- code: 1059,
566
- status: "to-be-empty-array",
722
+ toBeNull() {
723
+ this._expected = true;
724
+
725
+ if (this.value !== null) {
726
+ throw new TestException({
727
+ message: `value is not null`,
728
+ code: 1008,
729
+ status: "not-null",
567
730
  });
568
731
  }
569
732
 
570
733
  return this;
571
734
  }
572
- notToBeIterable() {
573
- if (isIterable(this.value)) {
574
- throw new Exception({
575
- message: `${this.value} is iterable`,
576
- code: 1060,
577
- status: "not-iterable",
735
+ notToBeNull() {
736
+ this._expected = true;
737
+
738
+ if (this.value === null) {
739
+ throw new TestException({
740
+ message: `value is null`,
741
+ code: 1009,
742
+ status: "null",
578
743
  });
579
744
  }
580
745
 
581
746
  return this;
582
747
  }
583
- notToBeSubClassOf(type) {
584
- if (isSubClassOf(this.value, type)) {
585
- throw new Exception({
586
- message: `${this.value} is subclass of ${type}`,
587
- code: 1061,
588
- status: "not-subclassof",
748
+ toBeNullOrUndefined() {
749
+ this._expected = true;
750
+
751
+ if (this.value == null) {
752
+ } else {
753
+ throw new TestException({
754
+ message: `value is not null/undefined`,
755
+ code: 1010,
756
+ status: "not-null-or-undefined",
589
757
  });
590
758
  }
591
759
 
592
760
  return this;
593
761
  }
594
- notToBeInstanceOf(type) {
595
- if (this.value instanceof type) {
596
- throw new Exception({
597
- message: `${this.value} is instance of ${type}`,
598
- code: 1062,
599
- status: "not-instanceof",
762
+ notToBeNullOrUndefined() {
763
+ this._expected = true;
764
+
765
+ if (this.value == null) {
766
+ throw new TestException({
767
+ message: `value is null/undefined`,
768
+ code: 1011,
769
+ status: "null-or-undefined",
600
770
  });
601
771
  }
602
772
 
603
773
  return this;
604
774
  }
605
- doesNotMatch(pattern, flags) {
606
- const r = new RegExp(pattern, flags);
775
+ toBeEmptyArray() {
776
+ this._expected = true;
607
777
 
608
- if (r.test(this.value)) {
609
- throw new Exception({
610
- message: `${this.value} matches ${pattern}`,
611
- code: 1063,
612
- status: "not-match",
778
+ if (isSomeArray(this.value)) {
779
+ throw new TestException({
780
+ message: `${this.value} is some array`,
781
+ code: 1059,
782
+ status: "to-be-empty-array",
613
783
  });
614
784
  }
615
785
 
616
786
  return this;
617
787
  }
618
788
  toBeValid(fnValidation) {
789
+ this._expected = true;
790
+
619
791
  if (!isFunction(fnValidation)) {
620
- throw new Exception({
792
+ throw new TestException({
621
793
  message: `fnValidation is not function`,
622
794
  code: 1064,
623
795
  status: "to-be-valid",
624
796
  });
625
797
  }
626
798
  if (!fnValidation(this.value)) {
627
- throw new Exception({
799
+ throw new TestException({
628
800
  message: `${this.value} is not valid`,
629
801
  code: 1065,
630
802
  status: "to-be-valid",
@@ -634,15 +806,17 @@ class Expect {
634
806
  return this;
635
807
  }
636
808
  notToBeValid(fnValidation) {
809
+ this._expected = true;
810
+
637
811
  if (!isFunction(fnValidation)) {
638
- throw new Exception({
812
+ throw new TestException({
639
813
  message: `fnValidation is not function`,
640
814
  code: 1066,
641
815
  status: "not-to-be-valid",
642
816
  });
643
817
  }
644
818
  if (fnValidation(this.value)) {
645
- throw new Exception({
819
+ throw new TestException({
646
820
  message: `${this.value} is valid`,
647
821
  code: 1067,
648
822
  status: "not-to-be-valid",
@@ -652,8 +826,10 @@ class Expect {
652
826
  return this;
653
827
  }
654
828
  toThrow(ex, shape = false, strict = false) {
829
+ this._expected = true;
830
+
655
831
  if (!isFunction(this.value)) {
656
- throw new Exception({
832
+ throw new TestException({
657
833
  message: `given argument is not a function.`,
658
834
  code: 1012,
659
835
  status: "not-func",
@@ -670,7 +846,7 @@ class Expect {
670
846
  if (ex !== undefined) {
671
847
  if (isPrimitive(ex)) {
672
848
  if (e !== ex) {
673
- throw new Exception({
849
+ throw new TestException({
674
850
  message: `given function threw incorrect error.`,
675
851
  code: 1018,
676
852
  status: "incorrect-throw-error",
@@ -678,7 +854,7 @@ class Expect {
678
854
  }
679
855
  } else if (isFunction(ex)) {
680
856
  if (!(e instanceof ex)) {
681
- throw new Exception({
857
+ throw new TestException({
682
858
  message: `given function threw incorrect instance.`,
683
859
  code: 1019,
684
860
  status: "incorrect-throw-instance",
@@ -687,7 +863,7 @@ class Expect {
687
863
  } else if (isObject(ex)) {
688
864
  if (shape) {
689
865
  if (!equals(e, ex, strict)) {
690
- throw new Exception({
866
+ throw new TestException({
691
867
  message: `given function threw incorrect object shape.`,
692
868
  code: 1020,
693
869
  status: "incorrect-throw-shape",
@@ -695,7 +871,7 @@ class Expect {
695
871
  }
696
872
  } else {
697
873
  if (e !== ex) {
698
- throw new Exception({
874
+ throw new TestException({
699
875
  message: `given function threw incorrect object.`,
700
876
  code: 1021,
701
877
  status: "incorrect-throw-object",
@@ -704,7 +880,7 @@ class Expect {
704
880
  }
705
881
  } else {
706
882
  if (e !== ex) {
707
- throw new Exception({
883
+ throw new TestException({
708
884
  message: `given function threw incorrect value.`,
709
885
  code: 1022,
710
886
  status: "incorrect-throw-value",
@@ -715,7 +891,7 @@ class Expect {
715
891
  }
716
892
 
717
893
  if (ok) {
718
- throw new Exception({
894
+ throw new TestException({
719
895
  message: `given function ran without throwing any errors.`,
720
896
  code: 1013,
721
897
  status: "ran-to-completion",
@@ -724,34 +900,39 @@ class Expect {
724
900
 
725
901
  return this;
726
902
  }
727
- async toThrowAsync(ex, shape = false, strict = false) {
903
+ notToThrow(ex, shape = false, strict = false) {
904
+ this._expected = true;
905
+
728
906
  if (!isFunction(this.value)) {
729
- throw new Exception({
907
+ throw new TestException({
730
908
  message: `given argument is not a function.`,
731
909
  code: 1012,
732
910
  status: "not-func",
733
911
  });
734
912
  }
735
913
 
736
- let ok = false;
914
+ let ok = true;
915
+ let error;
737
916
 
738
917
  try {
739
- await this.value();
918
+ this.value();
740
919
 
741
- ok = true;
920
+ ok = false;
742
921
  } catch (e) {
922
+ error = e;
923
+
743
924
  if (ex !== undefined) {
744
925
  if (isPrimitive(ex)) {
745
- if (e !== ex) {
746
- throw new Exception({
926
+ if (e === ex) {
927
+ throw new TestException({
747
928
  message: `given function threw incorrect error.`,
748
929
  code: 1018,
749
930
  status: "incorrect-throw-error",
750
931
  });
751
932
  }
752
933
  } else if (isFunction(ex)) {
753
- if (!(e instanceof ex)) {
754
- throw new Exception({
934
+ if (e instanceof ex) {
935
+ throw new TestException({
755
936
  message: `given function threw incorrect instance.`,
756
937
  code: 1019,
757
938
  status: "incorrect-throw-instance",
@@ -759,16 +940,16 @@ class Expect {
759
940
  }
760
941
  } else if (isObject(ex)) {
761
942
  if (shape) {
762
- if (!equals(e, ex, strict)) {
763
- throw new Exception({
943
+ if (equals(e, ex, strict)) {
944
+ throw new TestException({
764
945
  message: `given function threw incorrect object shape.`,
765
946
  code: 1020,
766
947
  status: "incorrect-throw-shape",
767
948
  });
768
949
  }
769
950
  } else {
770
- if (e !== ex) {
771
- throw new Exception({
951
+ if (e === ex) {
952
+ throw new TestException({
772
953
  message: `given function threw incorrect object.`,
773
954
  code: 1021,
774
955
  status: "incorrect-throw-object",
@@ -776,8 +957,8 @@ class Expect {
776
957
  }
777
958
  }
778
959
  } else {
779
- if (e !== ex) {
780
- throw new Exception({
960
+ if (e === ex) {
961
+ throw new TestException({
781
962
  message: `given function threw incorrect value.`,
782
963
  code: 1022,
783
964
  status: "incorrect-throw-value",
@@ -788,46 +969,46 @@ class Expect {
788
969
  }
789
970
 
790
971
  if (ok) {
791
- throw new Exception({
792
- message: `given function ran without throwing any errors.`,
793
- code: 1013,
794
- status: "ran-to-completion",
972
+ throw new TestException({
973
+ message: `given function threw an error.`,
974
+ code: 1014,
975
+ status: "ran-to-error",
976
+ innerException: error,
795
977
  });
796
978
  }
797
979
 
798
980
  return this;
799
981
  }
800
- notToThrow(ex, shape = false, strict = false) {
982
+ async toThrowAsync(ex, shape = false, strict = false) {
983
+ this._expected = true;
984
+
801
985
  if (!isFunction(this.value)) {
802
- throw new Exception({
986
+ throw new TestException({
803
987
  message: `given argument is not a function.`,
804
988
  code: 1012,
805
989
  status: "not-func",
806
990
  });
807
991
  }
808
992
 
809
- let ok = true;
810
- let error;
993
+ let ok = false;
811
994
 
812
995
  try {
813
- this.value();
996
+ await this.value();
814
997
 
815
- ok = false;
998
+ ok = true;
816
999
  } catch (e) {
817
- error = e;
818
-
819
1000
  if (ex !== undefined) {
820
1001
  if (isPrimitive(ex)) {
821
- if (e === ex) {
822
- throw new Exception({
1002
+ if (e !== ex) {
1003
+ throw new TestException({
823
1004
  message: `given function threw incorrect error.`,
824
1005
  code: 1018,
825
1006
  status: "incorrect-throw-error",
826
1007
  });
827
1008
  }
828
1009
  } else if (isFunction(ex)) {
829
- if (e instanceof ex) {
830
- throw new Exception({
1010
+ if (!(e instanceof ex)) {
1011
+ throw new TestException({
831
1012
  message: `given function threw incorrect instance.`,
832
1013
  code: 1019,
833
1014
  status: "incorrect-throw-instance",
@@ -835,16 +1016,16 @@ class Expect {
835
1016
  }
836
1017
  } else if (isObject(ex)) {
837
1018
  if (shape) {
838
- if (equals(e, ex, strict)) {
839
- throw new Exception({
1019
+ if (!equals(e, ex, strict)) {
1020
+ throw new TestException({
840
1021
  message: `given function threw incorrect object shape.`,
841
1022
  code: 1020,
842
1023
  status: "incorrect-throw-shape",
843
1024
  });
844
1025
  }
845
1026
  } else {
846
- if (e === ex) {
847
- throw new Exception({
1027
+ if (e !== ex) {
1028
+ throw new TestException({
848
1029
  message: `given function threw incorrect object.`,
849
1030
  code: 1021,
850
1031
  status: "incorrect-throw-object",
@@ -852,8 +1033,8 @@ class Expect {
852
1033
  }
853
1034
  }
854
1035
  } else {
855
- if (e === ex) {
856
- throw new Exception({
1036
+ if (e !== ex) {
1037
+ throw new TestException({
857
1038
  message: `given function threw incorrect value.`,
858
1039
  code: 1022,
859
1040
  status: "incorrect-throw-value",
@@ -864,19 +1045,20 @@ class Expect {
864
1045
  }
865
1046
 
866
1047
  if (ok) {
867
- throw new Exception({
868
- message: `given function threw an error.`,
869
- code: 1014,
870
- status: "ran-to-error",
871
- innerException: error,
1048
+ throw new TestException({
1049
+ message: `given function ran without throwing any errors.`,
1050
+ code: 1013,
1051
+ status: "ran-to-completion",
872
1052
  });
873
1053
  }
874
1054
 
875
1055
  return this;
876
1056
  }
877
1057
  async notToThrowAsync(ex, shape = false, strict = false) {
1058
+ this._expected = true;
1059
+
878
1060
  if (!isFunction(this.value)) {
879
- throw new Exception({
1061
+ throw new TestException({
880
1062
  message: `given argument is not a function.`,
881
1063
  code: 1012,
882
1064
  status: "not-func",
@@ -896,7 +1078,7 @@ class Expect {
896
1078
  if (ex !== undefined) {
897
1079
  if (isPrimitive(ex)) {
898
1080
  if (e === ex) {
899
- throw new Exception({
1081
+ throw new TestException({
900
1082
  message: `given function threw incorrect error.`,
901
1083
  code: 1018,
902
1084
  status: "incorrect-throw-error",
@@ -904,7 +1086,7 @@ class Expect {
904
1086
  }
905
1087
  } else if (isFunction(ex)) {
906
1088
  if (e instanceof ex) {
907
- throw new Exception({
1089
+ throw new TestException({
908
1090
  message: `given function threw incorrect instance.`,
909
1091
  code: 1019,
910
1092
  status: "incorrect-throw-instance",
@@ -913,7 +1095,7 @@ class Expect {
913
1095
  } else if (isObject(ex)) {
914
1096
  if (shape) {
915
1097
  if (equals(e, ex, strict)) {
916
- throw new Exception({
1098
+ throw new TestException({
917
1099
  message: `given function threw incorrect object shape.`,
918
1100
  code: 1020,
919
1101
  status: "incorrect-throw-shape",
@@ -921,7 +1103,7 @@ class Expect {
921
1103
  }
922
1104
  } else {
923
1105
  if (e === ex) {
924
- throw new Exception({
1106
+ throw new TestException({
925
1107
  message: `given function threw incorrect object.`,
926
1108
  code: 1021,
927
1109
  status: "incorrect-throw-object",
@@ -930,7 +1112,7 @@ class Expect {
930
1112
  }
931
1113
  } else {
932
1114
  if (e === ex) {
933
- throw new Exception({
1115
+ throw new TestException({
934
1116
  message: `given function threw incorrect value.`,
935
1117
  code: 1022,
936
1118
  status: "incorrect-throw-value",
@@ -941,7 +1123,7 @@ class Expect {
941
1123
  }
942
1124
 
943
1125
  if (ok) {
944
- throw new Exception({
1126
+ throw new TestException({
945
1127
  message: `given function threw an error.`,
946
1128
  code: 1014,
947
1129
  status: "ran-to-error",
@@ -952,9 +1134,11 @@ class Expect {
952
1134
  return this;
953
1135
  }
954
1136
  toBeTruthy() {
1137
+ this._expected = true;
1138
+
955
1139
  if (this.value) {
956
1140
  } else {
957
- throw new Exception({
1141
+ throw new TestException({
958
1142
  message: `${this.value} is not truthy`,
959
1143
  code: 1015,
960
1144
  status: "not-truthy",
@@ -967,9 +1151,11 @@ class Expect {
967
1151
  return this.toBeTruthy();
968
1152
  }
969
1153
  toBeFalsy() {
1154
+ this._expected = true;
1155
+
970
1156
  if (!this.value) {
971
1157
  } else {
972
- throw new Exception({
1158
+ throw new TestException({
973
1159
  message: `${this.value} is not falsy`,
974
1160
  code: 1016,
975
1161
  status: "not-falsy",
@@ -982,9 +1168,11 @@ class Expect {
982
1168
  return this.toBeFalsy();
983
1169
  }
984
1170
  toBeNaN() {
1171
+ this._expected = true;
1172
+
985
1173
  if (isNaN(this.value)) {
986
1174
  } else {
987
- throw new Exception({
1175
+ throw new TestException({
988
1176
  message: `${this.value} is not NaN`,
989
1177
  code: 1017,
990
1178
  status: "not-nan",
@@ -994,9 +1182,11 @@ class Expect {
994
1182
  return this;
995
1183
  }
996
1184
  notToBeNaN() {
1185
+ this._expected = true;
1186
+
997
1187
  if (!isNaN(this.value)) {
998
1188
  } else {
999
- throw new Exception({
1189
+ throw new TestException({
1000
1190
  message: `${this.value} is NaN`,
1001
1191
  code: 1023,
1002
1192
  status: "is-nan",
@@ -1007,8 +1197,6 @@ class Expect {
1007
1197
  }
1008
1198
  }
1009
1199
 
1010
- const expect = (x) => new Expect(x);
1011
-
1012
1200
  class Test {
1013
1201
  constructor(name, fn) {
1014
1202
  this.name = name;
@@ -1019,8 +1207,14 @@ class Test {
1019
1207
  const start = new Date();
1020
1208
 
1021
1209
  if (isFunction(this.fn)) {
1210
+ const _expect = new Expect();
1211
+
1022
1212
  try {
1023
- const _result = this.fn(expect);
1213
+ const _result = this.fn((x) => {
1214
+ _expect.value = x;
1215
+
1216
+ return _expect;
1217
+ });
1024
1218
 
1025
1219
  if (_result && isFunction(_result.then)) {
1026
1220
  _result
@@ -1030,6 +1224,7 @@ class Test {
1030
1224
  test: this.name,
1031
1225
  result,
1032
1226
  time: new Date() - start,
1227
+ expected: _expect.expected,
1033
1228
  });
1034
1229
  })
1035
1230
  .catch((ex) => {
@@ -1037,7 +1232,8 @@ class Test {
1037
1232
  success: false,
1038
1233
  test: this.name,
1039
1234
  time: new Date() - start,
1040
- err: new Exception({
1235
+ expected: _expect.expected,
1236
+ err: new TestException({
1041
1237
  message: `test '${this.name}' failed.`,
1042
1238
  code: 501,
1043
1239
  status: "failed",
@@ -1051,6 +1247,7 @@ class Test {
1051
1247
  test: this.name,
1052
1248
  time: new Date() - start,
1053
1249
  result: _result,
1250
+ expected: _expect.expected,
1054
1251
  });
1055
1252
  }
1056
1253
  } catch (ex) {
@@ -1058,7 +1255,8 @@ class Test {
1058
1255
  success: false,
1059
1256
  test: this.name,
1060
1257
  time: new Date() - start,
1061
- err: new Exception({
1258
+ expected: _expect.expected,
1259
+ err: new TestException({
1062
1260
  message: `test '${this.name}' failed.`,
1063
1261
  code: 501,
1064
1262
  status: "failed",
@@ -1071,7 +1269,7 @@ class Test {
1071
1269
  success: false,
1072
1270
  test: this.name,
1073
1271
  time: new Date() - start,
1074
- err: new Exception({
1272
+ err: new TestException({
1075
1273
  message: `test '${this.name}' does not have a function to be called.`,
1076
1274
  code: 500,
1077
1275
  status: "no-func",
@@ -1082,50 +1280,51 @@ class Test {
1082
1280
  }
1083
1281
  }
1084
1282
 
1085
- const reset = "\x1b[0m"
1086
- const bright = "\x1b[1m"
1087
- const dim = "\x1b[2m"
1088
- const underscore = "\x1b[4m"
1089
- const blink = "\x1b[5m"
1090
- const reverse = "\x1b[7m"
1091
- const hidden = "\x1b[8m"
1092
-
1093
- const fgBlack = "\x1b[30m"
1094
- const fgRed = "\x1b[31m"
1095
- const fgGreen = "\x1b[32m"
1096
- const fgYellow = "\x1b[33m"
1097
- const fgBlue = "\x1b[34m"
1098
- const fgMagenta = "\x1b[35m"
1099
- const fgCyan = "\x1b[36m"
1100
- const fgWhite = "\x1b[37m"
1101
- const fgGray = "\x1b[90m"
1102
-
1103
- const bgBlack = "\x1b[40m"
1104
- const bgRed = "\x1b[41m"
1105
- const bgGreen = "\x1b[42m"
1106
- const bgYellow = "\x1b[43m"
1107
- const bgBlue = "\x1b[44m"
1108
- const bgMagenta = "\x1b[45m"
1109
- const bgCyan = "\x1b[46m"
1110
- const bgWhite = "\x1b[47m"
1111
- const bgGray = "\x1b[100m"
1283
+ const reset = "\x1b[0m";
1284
+ const bright = "\x1b[1m";
1285
+ const dim = "\x1b[2m";
1286
+ const underscore = "\x1b[4m";
1287
+ const blink = "\x1b[5m";
1288
+ const reverse = "\x1b[7m";
1289
+ const hidden = "\x1b[8m";
1290
+
1291
+ const fgBlack = "\x1b[30m";
1292
+ const fgRed = "\x1b[31m";
1293
+ const fgGreen = "\x1b[32m";
1294
+ const fgYellow = "\x1b[33m";
1295
+ const fgBlue = "\x1b[34m";
1296
+ const fgMagenta = "\x1b[35m";
1297
+ const fgCyan = "\x1b[36m";
1298
+ const fgWhite = "\x1b[37m";
1299
+ const fgGray = "\x1b[90m";
1300
+
1301
+ const bgBlack = "\x1b[40m";
1302
+ const bgRed = "\x1b[41m";
1303
+ const bgGreen = "\x1b[42m";
1304
+ const bgYellow = "\x1b[43m";
1305
+ const bgBlue = "\x1b[44m";
1306
+ const bgMagenta = "\x1b[45m";
1307
+ const bgCyan = "\x1b[46m";
1308
+ const bgWhite = "\x1b[47m";
1309
+ const bgGray = "\x1b[100m";
1112
1310
 
1113
1311
  class TestRunner {
1114
1312
  constructor() {
1115
1313
  this._passed = 0;
1116
1314
  this._failed = 0;
1315
+ this._unknown = 0;
1117
1316
  this._results = [];
1118
1317
  this._errors = [];
1119
1318
  }
1120
1319
  async _runSingle(test, onProgress, i) {
1121
1320
  if (isFunction(onProgress)) {
1122
1321
  try {
1123
- onProgress(i, test);
1322
+ onProgress({ source: this, test, index: i });
1124
1323
  } catch (ex) {
1125
1324
  this._errors.push({
1126
1325
  index: i,
1127
1326
  test: test.name,
1128
- err: new Exception({
1327
+ err: new TestException({
1129
1328
  message: `onProgress failed for test '${test.name} at index ${i}'.`,
1130
1329
  code: 1500,
1131
1330
  status: "progress-failed",
@@ -1139,7 +1338,9 @@ class TestRunner {
1139
1338
 
1140
1339
  this._results.push(tr);
1141
1340
 
1142
- if (tr.success) {
1341
+ if (!tr.expected) {
1342
+ this._unknown++;
1343
+ } else if (tr.success) {
1143
1344
  this._passed++;
1144
1345
  } else {
1145
1346
  this._failed++;
@@ -1185,7 +1386,7 @@ class TestRunner {
1185
1386
  .then((_) => res(this.result))
1186
1387
  .catch((ex) => {
1187
1388
  this._errors.push({
1188
- err: new Exception({
1389
+ err: new TestException({
1189
1390
  message: `not all tests succeeded. check errors.`,
1190
1391
  code: 1503,
1191
1392
  status: "partial-finished",
@@ -1197,7 +1398,7 @@ class TestRunner {
1197
1398
  });
1198
1399
  } else {
1199
1400
  this._errors.push({
1200
- err: new Exception({
1401
+ err: new TestException({
1201
1402
  message: `invalid tests. expected array or a single test.`,
1202
1403
  code: 1502,
1203
1404
  status: "invalid-tests",
@@ -1208,7 +1409,7 @@ class TestRunner {
1208
1409
  }
1209
1410
  } else {
1210
1411
  this._errors.push({
1211
- err: new Exception({
1412
+ err: new TestException({
1212
1413
  message: `no tests given to be ran.`,
1213
1414
  code: 1501,
1214
1415
  status: "no-tests",
@@ -1228,38 +1429,45 @@ class TestRunner {
1228
1429
  console.log("Finished.\n");
1229
1430
 
1230
1431
  for (let i = 0; i < this._results.length; i++) {
1231
- const result = this._results[i];
1232
- const t = `(${this._getTime(result.time)})`;
1432
+ const testResult = this._results[i];
1433
+ const t = `(${this._getTime(testResult.time)})`;
1233
1434
 
1234
1435
  if (detailed) {
1235
1436
  let message = "\n" + (i + 1) + ". ";
1236
-
1237
- if (result.success) {
1238
- message += `${fgWhite}${result.test}: ${fgGreen}passed${reset} ${t}`;
1437
+ let err = !isNullOrEmpty(testResult.err)
1438
+ ? testResult.err.toString().split("\n")
1439
+ : [];
1440
+
1441
+ err = err
1442
+ .map(
1443
+ (msg, i) =>
1444
+ `\t${
1445
+ i == err.length - 1
1446
+ ? `${fgYellow}`
1447
+ : `${fgGray}error ${testResult.err.code}: `
1448
+ }${msg}${reset}`
1449
+ )
1450
+ .join("\n");
1451
+
1452
+ if (!testResult.expected) {
1453
+ message += `${bright}${fgWhite}${testResult.test}: ${fgMagenta}expect not used${reset} ${t}`;
1454
+
1455
+ if (testResult.err) {
1456
+ message += "\n";
1457
+ message += `${fgGray}${err} ${reset}`;
1458
+ }
1459
+ } else if (testResult.success) {
1460
+ message += `${fgWhite}${testResult.test}: ${fgGreen}passed${reset} ${t}`;
1239
1461
  } else {
1240
- message += `${bright}${fgWhite}${result.test}: ${fgRed}failed${reset} ${t}`;
1462
+ message += `${bright}${fgWhite}${testResult.test}: ${fgRed}failed${reset} ${t}`;
1241
1463
  message += "\n";
1242
-
1243
- let err = result.err.toString().split("\n");
1244
-
1245
- err = err
1246
- .map(
1247
- (msg, i) =>
1248
- `\t${
1249
- i == err.length - 1
1250
- ? `${fgYellow}`
1251
- : `${fgGray}error ${result.err.code}: `
1252
- }${msg}${reset}`
1253
- )
1254
- .join("\n");
1255
-
1256
1464
  message += `${fgGray}${err} ${reset}`;
1257
1465
  }
1258
1466
 
1259
1467
  console.log(message);
1260
1468
  }
1261
1469
 
1262
- time += result.time;
1470
+ time += testResult.time;
1263
1471
  }
1264
1472
 
1265
1473
  if (detailed && this._errors.length) {
@@ -1291,6 +1499,9 @@ class TestRunner {
1291
1499
  (this._failed > 0
1292
1500
  ? `${fgRed} ${this._failed} test(s) failed${reset}`
1293
1501
  : `0 tests failed${reset}`) +
1502
+ (this._unknown > 0
1503
+ ? `, ${fgMagenta} ${this._unknown} test(s) are unknown${reset}`
1504
+ : ``) +
1294
1505
  "\n";
1295
1506
 
1296
1507
  console.log(text);
@@ -1328,12 +1539,29 @@ class TestRunner {
1328
1539
  console.log("writing tests outcome failed.\n" + ex);
1329
1540
  }
1330
1541
  }
1331
- static start(tests) {
1542
+ static async start(...tests) {
1332
1543
  const tr = new TestRunner();
1544
+ const lastArg = tests[tests.length - 1];
1545
+ const detailed = tests.length && isBool(lastArg) ? lastArg : false;
1546
+ let _tests = [];
1547
+
1548
+ for (let i = 0; i < tests.length; i++) {
1549
+ const t = tests[i];
1550
+
1551
+ if (i != tests.length - 1 || !isBool(t)) {
1552
+ if (isIterable(t)) {
1553
+ _tests = [..._tests, ...t];
1554
+ }
1555
+ }
1556
+ }
1557
+
1558
+ const result = await tr.run(_tests);
1559
+
1560
+ tr.report(detailed || result.failed > 0);
1333
1561
 
1334
- tr.run(tests).then((result) => tr.report(result.failed > 0));
1562
+ return { runner: tr, result };
1335
1563
  }
1336
1564
  }
1337
1565
 
1338
1566
  export default TestRunner;
1339
- export { Test, Expect, expect };
1567
+ export { Test, Expect, TestException };