as-test 1.0.0 → 1.0.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.
@@ -1,11 +1,13 @@
1
1
  import { visualize } from "../util/helpers";
2
2
  import { Tests } from "./tests";
3
3
  import { quote, stringifyValue } from "../util/json";
4
+ import { namedSnapshotKey, nextUnnamedSnapshotKey } from "..";
4
5
  import {
5
6
  sendAssertionFailure,
6
7
  sendWarning,
7
8
  snapshotAssert,
8
9
  } from "../util/wipc";
10
+ import { OBJECT, TOTAL_OVERHEAD } from "~lib/rt/common";
9
11
 
10
12
  let warnedToThrowDisabled = false;
11
13
 
@@ -78,6 +80,22 @@ export class Expectation<T> extends Tests {
78
80
  this.message = isFail ? this._message : "";
79
81
  if (isFail) {
80
82
  sendAssertionFailure(this._snapshotKey, instr, left, right, this.message);
83
+ // @ts-ignore
84
+ if (isDefined(AS_TEST_FUZZ)) {
85
+ // @ts-ignore
86
+ __as_test_fuzz_failed = true;
87
+ // @ts-ignore
88
+ if (!__as_test_fuzz_failure_instr.length) {
89
+ // @ts-ignore
90
+ __as_test_fuzz_failure_instr = instr;
91
+ // @ts-ignore
92
+ __as_test_fuzz_failure_left = left;
93
+ // @ts-ignore
94
+ __as_test_fuzz_failure_right = right;
95
+ // @ts-ignore
96
+ __as_test_fuzz_failure_message = this.message;
97
+ }
98
+ }
81
99
  }
82
100
  this._not = false;
83
101
  }
@@ -375,8 +393,9 @@ export class Expectation<T> extends Tests {
375
393
  * Tests if serialized value matches stored snapshot.
376
394
  */
377
395
  toMatchSnapshot(name: string = ""): void {
378
- let key = this._snapshotKey;
379
- if (name.length) key += "::" + name;
396
+ let key = name.length
397
+ ? namedSnapshotKey(this._snapshotKey, name)
398
+ : nextUnnamedSnapshotKey(this._snapshotKey);
380
399
 
381
400
  const actual = stringifyValue<T>(this._left);
382
401
  const res = snapshotAssert(key, actual);
@@ -413,21 +432,7 @@ export class Expectation<T> extends Tests {
413
432
  * Tests for equality
414
433
  */
415
434
  toBe(equals: T): void {
416
- let passed = false;
417
- if (isArray<T>()) {
418
- // @ts-ignore
419
- passed = arrayEquals(this._left, equals);
420
- } else if (
421
- isBoolean<T>() ||
422
- isString<T>() ||
423
- isInteger<T>() ||
424
- isFloat<T>()
425
- ) {
426
- passed = this._left === equals;
427
- } else {
428
- // Fallback for reference/value types where strict equality is not enough.
429
- passed = stringifyValue<T>(this._left) == stringifyValue<T>(equals);
430
- }
435
+ const passed = this._left === equals;
431
436
 
432
437
  this._resolve(
433
438
  passed,
@@ -436,11 +441,91 @@ export class Expectation<T> extends Tests {
436
441
  stringifyValue<T>(equals),
437
442
  );
438
443
  }
444
+
445
+ /**
446
+ * Tests for deep equality
447
+ */
448
+ toEqual(equals: T): void {
449
+ const passed = valueEquals<T>(this._left, equals, false);
450
+ this._resolve(
451
+ passed,
452
+ "toEqual",
453
+ stringifyValue<T>(this._left),
454
+ stringifyValue<T>(equals),
455
+ );
456
+ }
457
+
458
+ /**
459
+ * Tests for strict deep equality
460
+ */
461
+ toStrictEqual(equals: T): void {
462
+ const passed = valueEquals<T>(this._left, equals, true);
463
+ this._resolve(
464
+ passed,
465
+ "toStrictEqual",
466
+ stringifyValue<T>(this._left),
467
+ stringifyValue<T>(equals),
468
+ );
469
+ }
439
470
  }
440
471
 
441
- function arrayEquals<T extends any[]>(a: T, b: T): boolean {
472
+ function arrayEquals<T>(a: T[], b: T[], strict: bool): boolean {
442
473
  if (a.length != b.length) return false;
443
- return stringifyValue(a) == stringifyValue(b);
474
+ for (let i = 0; i < a.length; i++) {
475
+ if (!valueEquals<T>(unchecked(a[i]), unchecked(b[i]), strict)) {
476
+ return false;
477
+ }
478
+ }
479
+ return true;
480
+ }
481
+
482
+ function valueEquals<T>(left: T, right: T, strict: bool): bool {
483
+ if (isBoolean<T>() || isString<T>() || isInteger<T>() || isFloat<T>()) {
484
+ return left === right;
485
+ }
486
+
487
+ if (isNullable<T>()) {
488
+ const leftPtr = changetype<usize>(left);
489
+ const rightPtr = changetype<usize>(right);
490
+ if (leftPtr == 0 || rightPtr == 0) return leftPtr == rightPtr;
491
+ }
492
+
493
+ if (isArray<T>()) {
494
+ return arrayEquals<valueof<T>>(
495
+ changetype<valueof<T>[]>(left),
496
+ changetype<valueof<T>[]>(right),
497
+ strict,
498
+ );
499
+ }
500
+
501
+ if (isManaged<T>()) {
502
+ return managedEquals<T>(left, right, strict);
503
+ }
504
+
505
+ abort(
506
+ `Unsupported equality matcher for ${nameof<T>()}. Use toBe() for identity or compare fields explicitly.`,
507
+ );
508
+ return false;
509
+ }
510
+
511
+ export function __as_test_deep_equal<T>(left: T, right: T, strict: bool): bool {
512
+ return valueEquals<T>(left, right, strict);
513
+ }
514
+
515
+ function managedEquals<T>(left: T, right: T, strict: bool): bool {
516
+ const leftPtr = changetype<usize>(left);
517
+ const rightPtr = changetype<usize>(right);
518
+ if (leftPtr == rightPtr) return true;
519
+ if (leftPtr == 0 || rightPtr == 0) return false;
520
+
521
+ if (strict) {
522
+ const leftObject = changetype<OBJECT>(leftPtr - TOTAL_OVERHEAD);
523
+ const rightObject = changetype<OBJECT>(rightPtr - TOTAL_OVERHEAD);
524
+ if (leftObject.rtId != rightObject.rtId) return false;
525
+ }
526
+
527
+ // @ts-ignore
528
+ return left.__as_test_equals(right, strict);
444
529
  }
445
530
 
446
531
  function isTruthy<T>(value: T): bool {