From 3740d746edbcf2392e6088e722ae009b1bfdf07f Mon Sep 17 00:00:00 2001 From: eagletrhost Date: Wed, 10 Sep 2025 11:16:16 +1000 Subject: [PATCH 1/3] feat: modify remove undefined objects & encode array to not remove nulls from arrays --- packages/oas-to-har/src/index.ts | 7 +- .../src/lib/remove-undefined-objects.ts | 116 ++++++++++++++++++ .../lib/style-formatting/style-serializer.ts | 12 +- .../test/lib/remove-undefined-objects.test.ts | 115 +++++++++++++++++ packages/oas-to-har/test/parameters.test.ts | 4 +- 5 files changed, 247 insertions(+), 7 deletions(-) create mode 100644 packages/oas-to-har/src/lib/remove-undefined-objects.ts create mode 100644 packages/oas-to-har/test/lib/remove-undefined-objects.test.ts diff --git a/packages/oas-to-har/src/index.ts b/packages/oas-to-har/src/index.ts index 04d08e40..a882eab6 100644 --- a/packages/oas-to-har/src/index.ts +++ b/packages/oas-to-har/src/index.ts @@ -21,7 +21,7 @@ import { HEADERS, PROXY_ENABLED } from 'oas/extensions'; import { Operation } from 'oas/operation'; import { isRef } from 'oas/types'; import { jsonSchemaTypes, matchesMimeType } from 'oas/utils'; -import removeUndefinedObjects from 'remove-undefined-objects'; +import removeUndefinedObjects from './lib/remove-undefined-objects.js'; import configureSecurity from './lib/configure-security.js'; import { get, set } from './lib/lodash.js'; @@ -420,7 +420,8 @@ export default function oasToHar( if (operation.isFormUrlEncoded()) { if (Object.keys(formData.formData || {}).length) { - const cleanFormData = removeUndefinedObjects(JSON.parse(JSON.stringify(formData.formData))); + const cleanFormData = removeUndefinedObjects(formData.formData); + if (cleanFormData !== undefined) { const postData: PostData = { params: [], mimeType: 'application/x-www-form-urlencoded' }; @@ -444,7 +445,7 @@ export default function oasToHar( if (isMultipart || isJSON) { try { - let cleanBody = removeUndefinedObjects(JSON.parse(JSON.stringify(formData.body))); + let cleanBody = removeUndefinedObjects(formData.body); if (isMultipart) { har.postData = { params: [], mimeType: 'multipart/form-data' }; diff --git a/packages/oas-to-har/src/lib/remove-undefined-objects.ts b/packages/oas-to-har/src/lib/remove-undefined-objects.ts new file mode 100644 index 00000000..491cfe7d --- /dev/null +++ b/packages/oas-to-har/src/lib/remove-undefined-objects.ts @@ -0,0 +1,116 @@ +function isObject(obj: unknown) { + return typeof obj === 'object' && obj !== null && !Array.isArray(obj); +} + +function isEmptyObject(obj: unknown) { + return typeof obj === 'object' && obj !== null && !Object.keys(obj).length; +} + +interface RemovalOptions { + removeAllFalsy?: boolean; +} + +// Modified from here: https://stackoverflow.com/a/43781499 +function stripEmptyObjects(obj: any, options: RemovalOptions = {}) { + const cleanObj = obj; + + if (obj === null && options.removeAllFalsy) { + return undefined; + } + + if (!isObject(obj) && !Array.isArray(cleanObj)) { + return cleanObj; + } + + if (!Array.isArray(cleanObj)) { + + Object.keys(cleanObj).forEach(key => { + let value = cleanObj[key]; + + if (typeof value !== 'object') { + return; + } + + if (value === null) { + if (options.removeAllFalsy) { + delete cleanObj[key]; + } + return; + } + + value = stripEmptyObjects(value, options); + + if (isEmptyObject(value)) { + delete cleanObj[key]; + } else { + cleanObj[key] = value; + } + }); + + return cleanObj; + } + + cleanObj.forEach((o, idx) => { + let value = o; + if (typeof value === 'object' && value !== null) { + value = stripEmptyObjects(value, options); + + if (isEmptyObject(value)) { + delete cleanObj[idx]; + } else { + cleanObj[idx] = value; + } + } else if (value === null && options.removeAllFalsy) { + delete cleanObj[idx]; + } + }); + + // Since deleting a key from an array will retain an undefined value in that array, we need to + // filter them out. + return cleanObj.filter(el => el !== undefined); +} + +export default function removeUndefinedObjects(obj?: T, options?: RemovalOptions): T | undefined { + if (obj === undefined) { + return undefined; + } + + // Remove objects that recursively contain undefined values + // E.g. { a: { b: undefined } } -> { a: {} } + let withoutUndefined = removeUndefined(obj); + + // Then we recursively remove all empty objects and nullish arrays + withoutUndefined = stripEmptyObjects(withoutUndefined, options); + + // If the only thing that's leftover is an empty object then return nothing. + if (isEmptyObject(withoutUndefined)) return undefined; + + return withoutUndefined; +} + +function removeUndefined(obj: any): any { + if (obj === undefined) { + return undefined; + } + // Preserve null + if (obj === null) { + return null; + } + // Remove undefined in arrays + if (Array.isArray(obj)) { + return obj + .map(removeUndefined) + .filter(item => item !== undefined); + } + if (typeof obj === 'object') { + const cleaned: any = {}; + for (const [key, value] of Object.entries(obj)) { + const cleanedValue = removeUndefined(value); + if (cleanedValue !== undefined) { + cleaned[key] = cleanedValue; + } + } + return cleaned; + } + return obj; +} \ No newline at end of file diff --git a/packages/oas-to-har/src/lib/style-formatting/style-serializer.ts b/packages/oas-to-har/src/lib/style-formatting/style-serializer.ts index 257061bd..ca000e65 100644 --- a/packages/oas-to-har/src/lib/style-formatting/style-serializer.ts +++ b/packages/oas-to-har/src/lib/style-formatting/style-serializer.ts @@ -119,13 +119,21 @@ function encodeArray({ escape, isAllowedReserved = false, }: Omit & { value: string[] }) { - const valueEncoder = (str: string) => - encodeDisallowedCharacters(str, { + const valueEncoder = (str: string) => { + // Handle null values explicitly to prevent join() from converting to empty string + if (str === null) { + return 'null'; + } + + const result = encodeDisallowedCharacters(str, { escape, returnIfEncoded: location === 'query', isAllowedReserved, }); + return result; + }; + switch (style) { /** * @example `style: simple` diff --git a/packages/oas-to-har/test/lib/remove-undefined-objects.test.ts b/packages/oas-to-har/test/lib/remove-undefined-objects.test.ts new file mode 100644 index 00000000..34ec88f0 --- /dev/null +++ b/packages/oas-to-har/test/lib/remove-undefined-objects.test.ts @@ -0,0 +1,115 @@ +import { describe, test, it, expect } from 'vitest'; + +import removeUndefinedObjects from '../../src/lib/remove-undefined-objects.js'; + +describe('typings', () => { + it('should not blow away typings from supplied objects', () => { + const obj = removeUndefinedObjects({ + key: 'buster', + }); + + expect(obj).toBeDefined(); + }); +}); + +test('should leave primitives alone', () => { + expect(removeUndefinedObjects(1234)).toBe(1234); + expect(removeUndefinedObjects('1234')).toBe('1234'); + expect(removeUndefinedObjects(null)).toBeNull(); + expect(removeUndefinedObjects()).toBeUndefined(); + expect(removeUndefinedObjects(undefined)).toBeUndefined(); +}); + +test('should leave only truthy primitives alone when removeAllFalsy is true', () => { + expect(removeUndefinedObjects(1234, { removeAllFalsy: true })).toBe(1234); + expect(removeUndefinedObjects('1234', { removeAllFalsy: true })).toBe('1234'); + expect(removeUndefinedObjects(null, { removeAllFalsy: true })).toBeUndefined(); + expect(removeUndefinedObjects(undefined, { removeAllFalsy: true })).toBeUndefined(); +}); + +test("should also remove '' and null values when removeAllFalsy is true", () => { + expect(removeUndefinedObjects({ value: 1234 }, { removeAllFalsy: true })).toStrictEqual({ value: 1234 }); + expect(removeUndefinedObjects({ value: '1234' }, { removeAllFalsy: true })).toStrictEqual({ value: '1234' }); + expect(removeUndefinedObjects({ value: null }, { removeAllFalsy: true })).toBeUndefined(); + expect(removeUndefinedObjects({ value: undefined }, { removeAllFalsy: true })).toBeUndefined(); +}); + +test('should remove empty objects with only empty properties', () => { + const obj = { + a: { + b: {}, + c: { + d: {}, + }, + }, + }; + + expect(removeUndefinedObjects(obj)).toBeUndefined(); +}); + +test('should remove empty objects with only undefined properties', () => { + const obj = { + a: { + b: undefined, + c: { + d: undefined, + }, + }, + }; + + expect(removeUndefinedObjects(obj)).toBeUndefined(); +}); + +test('should remove empty arrays from within object', () => { + const obj = { + a: { + b: undefined, + c: { + d: undefined, + }, + }, + d: [1234, undefined], + e: [], + f: null, + g: [null, undefined, null], + }; + + expect(removeUndefinedObjects(obj)).toStrictEqual({ + d: [1234], + f: null, + g: [null, null], + }); +}); + +test('should remove empty arrays and falsy values from within object when removeAllFalsy is true', () => { + const obj = { + a: { + b: undefined, + c: { + d: undefined, + }, + }, + d: [1234, undefined], + e: [], + f: null, + g: [null, undefined, null], + }; + + expect(removeUndefinedObjects(obj, { removeAllFalsy: true })).toStrictEqual({ + d: [1234], + }); +}); + +test('should remove undefined values from arrays & not null values', () => { + expect(removeUndefinedObjects([undefined, undefined])).toBeUndefined(); + expect(removeUndefinedObjects([null])).toStrictEqual([null]); + expect(removeUndefinedObjects(['1234', null, undefined, { a: null, b: undefined }, ' ', ''])).toStrictEqual([ + '1234', + null, + { + a: null, + }, + ' ', + '', + ]); +}); diff --git a/packages/oas-to-har/test/parameters.test.ts b/packages/oas-to-har/test/parameters.test.ts index d21f40de..7b367fe3 100644 --- a/packages/oas-to-har/test/parameters.test.ts +++ b/packages/oas-to-har/test/parameters.test.ts @@ -172,7 +172,7 @@ describe('parameter handling', () => { parameters: [{ name: 'id', in: 'query' }], }, { query: { id: [null, null] } }, - [{ name: 'id', value: '&id=' }], + [{ name: 'id', value: 'null&id=null' }], ), ); @@ -207,7 +207,7 @@ describe('parameter handling', () => { ], }, { query: {} }, - [{ name: 'id', value: '&id=' }], + [{ name: 'id', value: 'null&id=null' }], ), ); From acb367498bd3990e4ef927a80ed03a2fc8c3447b Mon Sep 17 00:00:00 2001 From: eagletrhost Date: Wed, 10 Sep 2025 20:52:52 +1000 Subject: [PATCH 2/3] clean: delete cloned removed-undefined-objects --- packages/oas-to-har/src/index.ts | 2 +- .../src/lib/remove-undefined-objects.ts | 116 ------------------ .../test/lib/remove-undefined-objects.test.ts | 115 ----------------- 3 files changed, 1 insertion(+), 232 deletions(-) delete mode 100644 packages/oas-to-har/src/lib/remove-undefined-objects.ts delete mode 100644 packages/oas-to-har/test/lib/remove-undefined-objects.test.ts diff --git a/packages/oas-to-har/src/index.ts b/packages/oas-to-har/src/index.ts index a882eab6..e9438bed 100644 --- a/packages/oas-to-har/src/index.ts +++ b/packages/oas-to-har/src/index.ts @@ -21,7 +21,7 @@ import { HEADERS, PROXY_ENABLED } from 'oas/extensions'; import { Operation } from 'oas/operation'; import { isRef } from 'oas/types'; import { jsonSchemaTypes, matchesMimeType } from 'oas/utils'; -import removeUndefinedObjects from './lib/remove-undefined-objects.js'; +import removeUndefinedObjects from 'remove-undefined-objects'; import configureSecurity from './lib/configure-security.js'; import { get, set } from './lib/lodash.js'; diff --git a/packages/oas-to-har/src/lib/remove-undefined-objects.ts b/packages/oas-to-har/src/lib/remove-undefined-objects.ts deleted file mode 100644 index 491cfe7d..00000000 --- a/packages/oas-to-har/src/lib/remove-undefined-objects.ts +++ /dev/null @@ -1,116 +0,0 @@ -function isObject(obj: unknown) { - return typeof obj === 'object' && obj !== null && !Array.isArray(obj); -} - -function isEmptyObject(obj: unknown) { - return typeof obj === 'object' && obj !== null && !Object.keys(obj).length; -} - -interface RemovalOptions { - removeAllFalsy?: boolean; -} - -// Modified from here: https://stackoverflow.com/a/43781499 -function stripEmptyObjects(obj: any, options: RemovalOptions = {}) { - const cleanObj = obj; - - if (obj === null && options.removeAllFalsy) { - return undefined; - } - - if (!isObject(obj) && !Array.isArray(cleanObj)) { - return cleanObj; - } - - if (!Array.isArray(cleanObj)) { - - Object.keys(cleanObj).forEach(key => { - let value = cleanObj[key]; - - if (typeof value !== 'object') { - return; - } - - if (value === null) { - if (options.removeAllFalsy) { - delete cleanObj[key]; - } - return; - } - - value = stripEmptyObjects(value, options); - - if (isEmptyObject(value)) { - delete cleanObj[key]; - } else { - cleanObj[key] = value; - } - }); - - return cleanObj; - } - - cleanObj.forEach((o, idx) => { - let value = o; - if (typeof value === 'object' && value !== null) { - value = stripEmptyObjects(value, options); - - if (isEmptyObject(value)) { - delete cleanObj[idx]; - } else { - cleanObj[idx] = value; - } - } else if (value === null && options.removeAllFalsy) { - delete cleanObj[idx]; - } - }); - - // Since deleting a key from an array will retain an undefined value in that array, we need to - // filter them out. - return cleanObj.filter(el => el !== undefined); -} - -export default function removeUndefinedObjects(obj?: T, options?: RemovalOptions): T | undefined { - if (obj === undefined) { - return undefined; - } - - // Remove objects that recursively contain undefined values - // E.g. { a: { b: undefined } } -> { a: {} } - let withoutUndefined = removeUndefined(obj); - - // Then we recursively remove all empty objects and nullish arrays - withoutUndefined = stripEmptyObjects(withoutUndefined, options); - - // If the only thing that's leftover is an empty object then return nothing. - if (isEmptyObject(withoutUndefined)) return undefined; - - return withoutUndefined; -} - -function removeUndefined(obj: any): any { - if (obj === undefined) { - return undefined; - } - // Preserve null - if (obj === null) { - return null; - } - // Remove undefined in arrays - if (Array.isArray(obj)) { - return obj - .map(removeUndefined) - .filter(item => item !== undefined); - } - if (typeof obj === 'object') { - const cleaned: any = {}; - for (const [key, value] of Object.entries(obj)) { - const cleanedValue = removeUndefined(value); - if (cleanedValue !== undefined) { - cleaned[key] = cleanedValue; - } - } - return cleaned; - } - return obj; -} \ No newline at end of file diff --git a/packages/oas-to-har/test/lib/remove-undefined-objects.test.ts b/packages/oas-to-har/test/lib/remove-undefined-objects.test.ts deleted file mode 100644 index 34ec88f0..00000000 --- a/packages/oas-to-har/test/lib/remove-undefined-objects.test.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { describe, test, it, expect } from 'vitest'; - -import removeUndefinedObjects from '../../src/lib/remove-undefined-objects.js'; - -describe('typings', () => { - it('should not blow away typings from supplied objects', () => { - const obj = removeUndefinedObjects({ - key: 'buster', - }); - - expect(obj).toBeDefined(); - }); -}); - -test('should leave primitives alone', () => { - expect(removeUndefinedObjects(1234)).toBe(1234); - expect(removeUndefinedObjects('1234')).toBe('1234'); - expect(removeUndefinedObjects(null)).toBeNull(); - expect(removeUndefinedObjects()).toBeUndefined(); - expect(removeUndefinedObjects(undefined)).toBeUndefined(); -}); - -test('should leave only truthy primitives alone when removeAllFalsy is true', () => { - expect(removeUndefinedObjects(1234, { removeAllFalsy: true })).toBe(1234); - expect(removeUndefinedObjects('1234', { removeAllFalsy: true })).toBe('1234'); - expect(removeUndefinedObjects(null, { removeAllFalsy: true })).toBeUndefined(); - expect(removeUndefinedObjects(undefined, { removeAllFalsy: true })).toBeUndefined(); -}); - -test("should also remove '' and null values when removeAllFalsy is true", () => { - expect(removeUndefinedObjects({ value: 1234 }, { removeAllFalsy: true })).toStrictEqual({ value: 1234 }); - expect(removeUndefinedObjects({ value: '1234' }, { removeAllFalsy: true })).toStrictEqual({ value: '1234' }); - expect(removeUndefinedObjects({ value: null }, { removeAllFalsy: true })).toBeUndefined(); - expect(removeUndefinedObjects({ value: undefined }, { removeAllFalsy: true })).toBeUndefined(); -}); - -test('should remove empty objects with only empty properties', () => { - const obj = { - a: { - b: {}, - c: { - d: {}, - }, - }, - }; - - expect(removeUndefinedObjects(obj)).toBeUndefined(); -}); - -test('should remove empty objects with only undefined properties', () => { - const obj = { - a: { - b: undefined, - c: { - d: undefined, - }, - }, - }; - - expect(removeUndefinedObjects(obj)).toBeUndefined(); -}); - -test('should remove empty arrays from within object', () => { - const obj = { - a: { - b: undefined, - c: { - d: undefined, - }, - }, - d: [1234, undefined], - e: [], - f: null, - g: [null, undefined, null], - }; - - expect(removeUndefinedObjects(obj)).toStrictEqual({ - d: [1234], - f: null, - g: [null, null], - }); -}); - -test('should remove empty arrays and falsy values from within object when removeAllFalsy is true', () => { - const obj = { - a: { - b: undefined, - c: { - d: undefined, - }, - }, - d: [1234, undefined], - e: [], - f: null, - g: [null, undefined, null], - }; - - expect(removeUndefinedObjects(obj, { removeAllFalsy: true })).toStrictEqual({ - d: [1234], - }); -}); - -test('should remove undefined values from arrays & not null values', () => { - expect(removeUndefinedObjects([undefined, undefined])).toBeUndefined(); - expect(removeUndefinedObjects([null])).toStrictEqual([null]); - expect(removeUndefinedObjects(['1234', null, undefined, { a: null, b: undefined }, ' ', ''])).toStrictEqual([ - '1234', - null, - { - a: null, - }, - ' ', - '', - ]); -}); From e4e9028633c6274da30b523fbe731572f405475a Mon Sep 17 00:00:00 2001 From: eagletrhost Date: Sat, 13 Sep 2025 17:39:43 +1000 Subject: [PATCH 3/3] feat: update remove undefined package, update code & tests --- package-lock.json | 11 ++++- packages/oas-to-har/package.json | 2 +- packages/oas-to-har/src/index.ts | 6 +-- packages/oas-to-har/test/parameters.test.ts | 22 ++++++++++ packages/oas-to-har/test/requestBody.test.ts | 46 ++++++++++++++++++++ 5 files changed, 82 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ac1919af..a6687b1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17528,7 +17528,7 @@ "@readme/data-urls": "^3.0.0", "oas": "file:../oas", "qs": "^6.12.0", - "remove-undefined-objects": "^6.0.0" + "remove-undefined-objects": "^7.0.0" }, "devDependencies": { "@readme/oas-examples": "file:../oas-examples", @@ -17543,6 +17543,15 @@ "node": ">=20" } }, + "packages/oas-to-har/node_modules/remove-undefined-objects": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/remove-undefined-objects/-/remove-undefined-objects-7.0.0.tgz", + "integrity": "sha512-+9ycqqqpv6EdaOvHpyOkf81SXJ4MjARKX450Je6AmshEYeqAuiVcfbLx1coNICO3KulleXlOHd0GSHFkEdB3YQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "packages/oas-to-snippet": { "name": "@readme/oas-to-snippet", "version": "29.0.1", diff --git a/packages/oas-to-har/package.json b/packages/oas-to-har/package.json index ae7c6776..666d5378 100644 --- a/packages/oas-to-har/package.json +++ b/packages/oas-to-har/package.json @@ -51,7 +51,7 @@ "@readme/data-urls": "^3.0.0", "oas": "file:../oas", "qs": "^6.12.0", - "remove-undefined-objects": "^6.0.0" + "remove-undefined-objects": "^7.0.0" }, "devDependencies": { "@readme/oas-examples": "file:../oas-examples", diff --git a/packages/oas-to-har/src/index.ts b/packages/oas-to-har/src/index.ts index e9438bed..3362a37d 100644 --- a/packages/oas-to-har/src/index.ts +++ b/packages/oas-to-har/src/index.ts @@ -150,7 +150,7 @@ function isPrimitive(val: unknown) { } function stringify(json: Record) { - return JSON.stringify(removeUndefinedObjects(typeof json.RAW_BODY !== 'undefined' ? json.RAW_BODY : json)); + return JSON.stringify(removeUndefinedObjects(typeof json.RAW_BODY !== 'undefined' ? json.RAW_BODY : json, { preserveNullishArrays: true })); } function stringifyParameter(param: any): string { @@ -420,7 +420,7 @@ export default function oasToHar( if (operation.isFormUrlEncoded()) { if (Object.keys(formData.formData || {}).length) { - const cleanFormData = removeUndefinedObjects(formData.formData); + const cleanFormData = removeUndefinedObjects(formData.formData, { preserveNullishArrays: true }); if (cleanFormData !== undefined) { const postData: PostData = { params: [], mimeType: 'application/x-www-form-urlencoded' }; @@ -445,7 +445,7 @@ export default function oasToHar( if (isMultipart || isJSON) { try { - let cleanBody = removeUndefinedObjects(formData.body); + let cleanBody = removeUndefinedObjects(formData.body, { preserveNullishArrays: true }); if (isMultipart) { har.postData = { params: [], mimeType: 'multipart/form-data' }; diff --git a/packages/oas-to-har/test/parameters.test.ts b/packages/oas-to-har/test/parameters.test.ts index 7b367fe3..0c1d0be1 100644 --- a/packages/oas-to-har/test/parameters.test.ts +++ b/packages/oas-to-har/test/parameters.test.ts @@ -211,6 +211,28 @@ describe('parameter handling', () => { ), ); + it( + 'should handle mixed array with null, undefined, and normal values', + assertQueryParams( + { + parameters: [{ name: 'id', in: 'query' }], + }, + { query: { id: [null, undefined, 'normal', null, 'test'] } }, + [{ name: 'id', value: 'null&id=&id=normal&id=null&id=test' }], + ), + ); + + it( + 'should handle array with only undefined values', + assertQueryParams( + { + parameters: [{ name: 'id', in: 'query' }], + }, + { query: { id: [undefined, undefined] } }, + [{ name: 'id', value: '&id=' }], + ), + ); + describe('URI encoding', () => { let spec: Oas; diff --git a/packages/oas-to-har/test/requestBody.test.ts b/packages/oas-to-har/test/requestBody.test.ts index 66bc8f70..8ad6dbb1 100644 --- a/packages/oas-to-har/test/requestBody.test.ts +++ b/packages/oas-to-har/test/requestBody.test.ts @@ -1085,6 +1085,52 @@ describe('request body handling', () => { expect(har.log.entries[0].request.postData).toBeUndefined(); }); + it('should preserve null values in arrays & still remove undefined values', () => { + const spec = Oas.init({ + paths: { + '/requestBody': { + post: { + requestBody: { + content: { + 'application/x-www-form-urlencoded': { + schema: { + type: 'object', + properties: { + foo: { + type: 'array', + items: { + type: 'string', + nullable: true, + }, + }, + foo2: { + type: 'array', + items: { + type: 'number', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }); + + const har = oasToHar(spec, spec.operation('/requestBody', 'post'), { + formData: { foo: [null, null, undefined], foo2: [1, 2] }, + }); + + expect(har.log.entries[0].request.postData?.params).toStrictEqual([ + // Since null is not a primitive, it will be JSON stringified which retains the square brackets + // See line 156-164 of src/index.ts + { name: 'foo', value: '[null,null]' }, + { name: 'foo2', value: '1,2' }, + ]); + }); + it('should pass in value if one is set and prioritize provided values', () => { const spec = Oas.init({ paths: {