From 23df1c563efee65e6d549308ed0671a9e2933c05 Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Wed, 21 Oct 2020 18:53:27 +0200 Subject: 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). --- std/testing/asserts.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'std/testing/asserts.ts') 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 @@ -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, + expected: Record, +): void { + type loose = Record; + 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 */ -- cgit v1.2.3