From 2314e4916e54e3e3c083c82dfbf0e7b30ab71320 Mon Sep 17 00:00:00 2001 From: Giovanni Bucci Date: Wed, 11 Dec 2024 16:10:53 +0100 Subject: [PATCH] assert: make Maps be partially compared in partialDeepStrictEqual PR-URL: https://github.com/nodejs/node/pull/56195 Reviewed-By: Ruben Bridgewater Reviewed-By: Pietro Marchini Reviewed-By: Antoine du Hamel --- lib/assert.js | 18 ++++--- test/parallel/test-assert-objects.js | 75 +++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 9 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index ff1f1204f43057..a2991a096ac081 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -385,22 +385,26 @@ const typesToCallDeepStrictEqualWith = [ isKeyObject, isWeakSet, isWeakMap, Buffer.isBuffer, isSharedArrayBuffer, ]; -function compareMaps(actual, expected, comparedObjects) { - if (MapPrototypeGetSize(actual) !== MapPrototypeGetSize(expected)) { +function partiallyCompareMaps(actual, expected, comparedObjects) { + if (MapPrototypeGetSize(expected) > MapPrototypeGetSize(actual)) { return false; } - const safeIterator = FunctionPrototypeCall(SafeMap.prototype[SymbolIterator], actual); comparedObjects ??= new SafeWeakSet(); + const expectedIterator = FunctionPrototypeCall(SafeMap.prototype[SymbolIterator], expected); - for (const { 0: key, 1: val } of safeIterator) { - if (!MapPrototypeHas(expected, key)) { + for (const { 0: key, 1: expectedValue } of expectedIterator) { + if (!MapPrototypeHas(actual, key)) { return false; } - if (!compareBranch(val, MapPrototypeGet(expected, key), comparedObjects)) { + + const actualValue = MapPrototypeGet(actual, key); + + if (!compareBranch(actualValue, expectedValue, comparedObjects)) { return false; } } + return true; } @@ -553,7 +557,7 @@ function compareBranch( ) { // Check for Map object equality if (isMap(actual) && isMap(expected)) { - return compareMaps(actual, expected, comparedObjects); + return partiallyCompareMaps(actual, expected, comparedObjects); } if ( diff --git a/test/parallel/test-assert-objects.js b/test/parallel/test-assert-objects.js index 75d06927917911..3f02ff3c274daa 100644 --- a/test/parallel/test-assert-objects.js +++ b/test/parallel/test-assert-objects.js @@ -169,12 +169,26 @@ describe('Object Comparison Tests', () => { }, { description: - 'throws when comparing two Map objects with different length', + 'throws when the expected Map has more entries than the actual Map', actual: new Map([ ['key1', 'value1'], ['key2', 'value2'], ]), - expected: new Map([['key1', 'value1']]), + expected: new Map([ + ['key1', 'value1'], + ['key2', 'value2'], + ['key3', 'value3'], + ]), + }, + { + description: 'throws when the nested array in the Map is not a subset of the other nested array', + actual: new Map([ + ['key1', ['value1', 'value2']], + ['key2', 'value2'], + ]), + expected: new Map([ + ['key1', ['value3']], + ]), }, { description: @@ -564,6 +578,63 @@ describe('Object Comparison Tests', () => { ['key2', 'value2'], ]), }, + { + description: + 'compares two Map objects where expected is a subset of actual', + actual: new Map([ + ['key1', 'value1'], + ['key2', 'value2'], + ]), + expected: new Map([['key1', 'value1']]), + }, + { + description: + 'compares two deeply nested Maps', + actual: { + a: { + b: { + c: new Map([ + ['key1', 'value1'], + ['key2', 'value2'], + ]) + }, + z: [1, 2, 3] + } + }, + expected: { + a: { + z: [1, 2, 3], + b: { + c: new Map([['key1', 'value1']]) + } + } + }, + }, + { + description: 'compares Maps nested into Maps', + actual: new Map([ + ['key1', new Map([ + ['nestedKey1', 'nestedValue1'], + ['nestedKey2', 'nestedValue2'], + ])], + ['key2', 'value2'], + ]), + expected: new Map([ + ['key1', new Map([ + ['nestedKey1', 'nestedValue1'], + ])], + ]) + }, + { + description: 'compares Maps with nested arrays inside', + actual: new Map([ + ['key1', ['value1', 'value2']], + ['key2', 'value2'], + ]), + expected: new Map([ + ['key1', ['value1', 'value2']], + ]), + }, { description: 'compares two objects with identical getter/setter properties',