diff options
author | Simon Lecoq <22963968+lowlighter@users.noreply.github.com> | 2020-10-21 18:53:27 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-21 18:53:27 +0200 |
commit | 23df1c563efee65e6d549308ed0671a9e2933c05 (patch) | |
tree | 4044912869283f4674467779fab9a56ff2ac3189 /std/testing/asserts.ts | |
parent | 322913ee5c73cd139a46dea593635c2d1a8d5f8c (diff) |
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).
Diffstat (limited to 'std/testing/asserts.ts')
-rw-r--r-- | std/testing/asserts.ts | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/std/testing/asserts.ts b/std/testing/asserts.ts index f93e043dc..1d58f0a00 100644 --- a/std/testing/asserts.ts +++ b/std/testing/asserts.ts @@ -430,6 +430,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 */ export function fail(msg?: string): void { |