diff --git a/packages/oas-to-har/__tests__/lib/remove-undefined-objects.test.js b/packages/oas-to-har/__tests__/lib/remove-undefined-objects.test.js index 27a122d7e..d658f2eaf 100644 --- a/packages/oas-to-har/__tests__/lib/remove-undefined-objects.test.js +++ b/packages/oas-to-har/__tests__/lib/remove-undefined-objects.test.js @@ -4,10 +4,21 @@ test('should remove empty objects with only undefined properties', () => { expect(removeUndefinedObjects({ a: { b: undefined, c: { d: undefined } } })).toBeUndefined(); }); -test('should not throw on arrays of primitives', () => { - expect(removeUndefinedObjects([null])).toStrictEqual([null]); +test('should remove empty arrays from within object', () => { + expect(removeUndefinedObjects({ a: { b: undefined, c: { d: undefined } }, d: [1234, undefined] })).toStrictEqual({ + d: [1234], + }); }); -test('should not throw for null', () => { - expect(removeUndefinedObjects({ a: null })).toStrictEqual({ a: null }); +test('should remove undefined and null values from arrays', () => { + expect(removeUndefinedObjects([undefined, undefined])).toBeUndefined(); + expect(removeUndefinedObjects([null])).toBeUndefined(); + expect(removeUndefinedObjects(['1234', null, undefined, { a: null, b: undefined }, ' ', ''])).toStrictEqual([ + '1234', + { + a: null, + }, + ' ', + '', + ]); }); diff --git a/packages/oas-to-har/src/lib/remove-undefined-objects.js b/packages/oas-to-har/src/lib/remove-undefined-objects.js index 1612578be..aa425c96d 100644 --- a/packages/oas-to-har/src/lib/remove-undefined-objects.js +++ b/packages/oas-to-har/src/lib/remove-undefined-objects.js @@ -5,26 +5,44 @@ function isEmptyObject(obj) { // Modified from here: https://stackoverflow.com/a/43781499 function stripEmptyObjects(obj) { - Object.keys(obj).forEach(key => { - const value = obj[key]; - if (typeof value === 'object' && !Array.isArray(obj) && value !== null) { + let cleanObj = obj; + + Object.keys(cleanObj).forEach(key => { + let value = cleanObj[key]; + + if (typeof value === 'object' && !Array.isArray(cleanObj) && value !== null) { // Recurse, strip out empty objects from children - stripEmptyObjects(value); + value = stripEmptyObjects(value); + // Then remove all empty objects from the top level object if (isEmptyObject(value)) { - // eslint-disable-next-line no-param-reassign - delete obj[key]; + delete cleanObj[key]; + } else { + cleanObj[key] = value; } + } else if (value === null) { + delete cleanObj[key]; } }); + + if (Array.isArray(cleanObj)) { + // Since deleting a key from an array will retain an undefined value in that array, we need to + // filter them out. + cleanObj = cleanObj.filter(function (el) { + return el !== undefined; + }); + } + + return cleanObj; } function removeUndefinedObjects(obj) { - // JSON.stringify removes undefined values - const withoutUndefined = JSON.parse(JSON.stringify(obj)); + // JSON.stringify removes undefined values. Though `[undefined]` will be converted with this to + // `[null]`, we'll clean that up next. + let withoutUndefined = JSON.parse(JSON.stringify(obj)); - // Then we recursively remove all empty objects - stripEmptyObjects(withoutUndefined); + // Then we recursively remove all empty objects and nullish arrays. + withoutUndefined = stripEmptyObjects(withoutUndefined); // If the only thing that's leftover is an empty object // then return nothing so we don't end up with default