diff --git a/src/traverse.js b/src/traverse.js index bc9d2a8..b8d220d 100644 --- a/src/traverse.js +++ b/src/traverse.js @@ -112,14 +112,19 @@ export function traverse(schema, options, spec, context) { writeOnly: schema.writeOnly }, schema.oneOf[0]); - return ( - tryInferExample(schema) || traverse(firstOneOf, options, spec, context) - ); + return traverseOneOrAnyOf(schema, firstOneOf) } if (schema.anyOf && schema.anyOf.length) { popSchemaStack(seenSchemasStack, context); - return tryInferExample(schema) || traverse(schema.anyOf[0], options, spec, context); + + // Make sure to pass down readOnly and writeOnly annotations from the parent + const firstAnyOf = Object.assign({ + readOnly: schema.readOnly, + writeOnly: schema.writeOnly + }, schema.anyOf[0]); + + return traverseOneOrAnyOf(schema, firstAnyOf) } if (schema.if && schema.then) { @@ -151,4 +156,21 @@ export function traverse(schema, options, spec, context) { writeOnly: schema.writeOnly, type: type }; + + function traverseOneOrAnyOf(schema, selectedSubSchema) { + const inferred = tryInferExample(schema); + if (inferred !== undefined) { + return inferred; + } + + const localExample = traverse({...schema, oneOf: undefined, anyOf: undefined }, options, spec, context); + const subSchemaExample = traverse(selectedSubSchema, options, spec, context); + + if (typeof localExample.value === 'object' && typeof subSchemaExample.value === 'object') { + const mergedExample = mergeDeep(localExample.value, subSchemaExample.value); + return {...subSchemaExample, value: mergedExample }; + } + + return subSchemaExample; + } } diff --git a/src/utils.js b/src/utils.js index 9a68fc7..04f90aa 100644 --- a/src/utils.js +++ b/src/utils.js @@ -32,7 +32,7 @@ export function mergeDeep(...objects) { const isObject = obj => obj && typeof obj === 'object'; return objects.reduce((prev, obj) => { - Object.keys(obj).forEach(key => { + Object.keys(obj || {}).forEach(key => { const pVal = prev[key]; const oVal = obj[key]; diff --git a/test/integration.spec.js b/test/integration.spec.js index 3a3b94d..a87febd 100644 --- a/test/integration.spec.js +++ b/test/integration.spec.js @@ -522,6 +522,40 @@ describe('Integration', function() { expected = 0; expect(result).to.equal(expected); }); + + it('should work with nested circular oneOf', function () { + result = OpenAPISampler.sample({ $ref: '#/definitions/A' }, {}, { + definitions: { + A: { + properties: { + a: { type: 'string' } + }, + oneOf: [ + { $ref: '#/definitions/A' } + ] + } + } + }); + expected = { a: 'string' } + expect(result).to.deep.equal(expected); + }); + + it('should work with nested circular anyOf', function () { + result = OpenAPISampler.sample({ $ref: '#/definitions/A' }, {}, { + definitions: { + A: { + properties: { + a: { type: 'string' } + }, + anyOf: [ + { $ref: '#/definitions/A' } + ] + } + } + }); + expected = { a: 'string' } + expect(result).to.deep.equal(expected); + }); }); describe('inferring type from root schema', function() {