feat(std/testing): Add support for object assertion against object subset (#8001)

This commit add supports for a new assertion function 
"assertObjectMatch" which allows to test an actual object 
against an expected object subset (i.e. inclusivity, not equality).
This commit is contained in:
Simon Lecoq 2020-10-21 18:53:27 +02:00 committed by GitHub
parent 322913ee5c
commit 23df1c563e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 219 additions and 0 deletions

View file

@ -429,6 +429,48 @@ export function assertNotMatch(
}
}
/**
* Make an assertion that `actual` object is a subset of `expected` object, deeply.
* If not, then throw.
*/
export function assertObjectMatch(
actual: Record<PropertyKey, unknown>,
expected: Record<PropertyKey, unknown>,
): void {
type loose = Record<PropertyKey, unknown>;
const seen = new WeakMap();
return assertEquals(
(function filter(a: loose, b: loose): loose {
// Prevent infinite loop with circular references with same filter
if ((seen.has(a)) && (seen.get(a) === b)) {
return a;
}
seen.set(a, b);
// Filter keys and symbols which are present in both actual and expected
const filtered = {} as loose;
const entries = [
...Object.getOwnPropertyNames(a),
...Object.getOwnPropertySymbols(a),
]
.filter((key) => key in b)
.map((key) => [key, a[key as string]]) as Array<[string, unknown]>;
// Build filtered object and filter recursively on nested objects references
for (const [key, value] of entries) {
if (typeof value === "object") {
const subset = (b as loose)[key];
if ((typeof subset === "object") && (subset)) {
filtered[key] = filter(value as loose, subset as loose);
continue;
}
}
filtered[key] = value;
}
return filtered;
})(actual, expected),
expected,
);
}
/**
* Forcefully throws a failed assertion
*/