Skip to content

Commit 008e32d

Browse files
authored
Merge pull request #681 from postmanlabs/feature/fix-outer-schema-allof
Fixed issue where outer schema along with allOf schema were not resolved correctly.
2 parents aef5871 + 26725a9 commit 008e32d

File tree

2 files changed

+120
-32
lines changed

2 files changed

+120
-32
lines changed

lib/deref.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ module.exports = {
9191
/**
9292
* Creates a schema that's a union of all input schemas (only type: object is supported)
9393
*
94-
* @param {array} schemaArr REQUIRED - array of schemas, all of which must be valid in the returned object
94+
* @param {*} schema REQUIRED - OpenAPI defined schema object to be resolved
9595
* @param {string} parameterSourceOption REQUIRED tells that the schema object is of request or response
9696
* @param {*} components REQUIRED components in openapi spec.
9797
* @param {object} options - REQUIRED a list of options to indicate the type of resolution needed.
@@ -103,7 +103,7 @@ module.exports = {
103103
* @param {*} options.stackLimit Depth to which the schema should be resolved.
104104
* @returns {*} schema - schema that adheres to all individual schemas in schemaArr
105105
*/
106-
resolveAllOf: function (schemaArr, parameterSourceOption, components, {
106+
resolveAllOf: function (schema, parameterSourceOption, components, {
107107
resolveFor = RESOLVE_REF_DEFAULTS.resolveFor,
108108
resolveTo = RESOLVE_REF_DEFAULTS.resolveTo,
109109
stack = RESOLVE_REF_DEFAULTS.stack,
@@ -112,23 +112,25 @@ module.exports = {
112112
analytics = {}
113113
}) {
114114

115-
if (!(schemaArr instanceof Array)) {
115+
if (_.isEmpty(schema)) {
116116
return null;
117117
}
118118

119-
if (schemaArr.length === 1) {
120-
// for just one entry in allOf, don't need to enforce type: object restriction
121-
return this.resolveRefs(schemaArr[0], parameterSourceOption, components,
122-
{ stack, seenRef: _.cloneDeep(seenRef), resolveFor, resolveTo, stackLimit, analytics });
119+
let resolvedNonAllOfSchema = {};
120+
121+
// Resolve schema excluding allOf keyword which will be further used to resolve entire schema along with allOf
122+
if (_.keys(schema).length > 1) {
123+
resolvedNonAllOfSchema = this.resolveRefs(_.omit(schema, 'allOf'), parameterSourceOption, components,
124+
{ stack, seenRef: _.cloneDeep(seenRef), resolveFor, resolveTo, stackLimit, isAllOf: true, analytics });
123125
}
124126

125127
try {
126-
return mergeAllOf({
127-
allOf: schemaArr.map((schema) => {
128+
return mergeAllOf(_.assign(resolvedNonAllOfSchema, {
129+
allOf: _.map(schema.allOf, (schema) => {
128130
return this.resolveRefs(schema, parameterSourceOption, components,
129131
{ stack, seenRef: _.cloneDeep(seenRef), resolveFor, resolveTo, stackLimit, isAllOf: true, analytics });
130132
})
131-
}, {
133+
}), {
132134
resolvers: {
133135
// for keywords in OpenAPI schema that are not standard defined JSON schema keywords, use default resolver
134136
defaultResolver: (compacted) => { return compacted[0]; }
@@ -246,7 +248,7 @@ module.exports = {
246248
}) };
247249
}
248250
if (schema.allOf) {
249-
return this.resolveAllOf(schema.allOf, parameterSourceOption, components,
251+
return this.resolveAllOf(schema, parameterSourceOption, components,
250252
{
251253
resolveFor,
252254
resolveTo,

test/unit/deref.test.js

Lines changed: 107 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -316,41 +316,127 @@ describe('DEREF FUNCTION TESTS ', function() {
316316
});
317317

318318
describe('resolveAllOf Function', function () {
319-
it('should resolve allOf schemas correctly', function (done) {
320-
var allOfschema = [
321-
{
322-
'type': 'object',
323-
'properties': {
324-
'source': {
325-
'type': 'string',
326-
'format': 'uuid'
319+
it('should resolve schemas containing allOf keyword correctly', function (done) {
320+
var schema = {
321+
'allOf': [
322+
{
323+
'type': 'object',
324+
'properties': {
325+
'source': {
326+
'type': 'string',
327+
'format': 'uuid'
328+
},
329+
'actionId': { 'type': 'integer', 'minimum': 5 },
330+
'result': { 'type': 'object' }
327331
},
328-
'actionId': { 'type': 'integer', 'minimum': 5 },
329-
'result': { 'type': 'object' }
332+
'required': ['source', 'actionId', 'result']
330333
},
331-
'required': ['source', 'actionId', 'result']
332-
},
333-
{
334-
'properties': {
335-
'result': {
336-
'type': 'object',
337-
'properties': {
338-
'err': { 'type': 'string' },
339-
'data': { 'type': 'object' }
334+
{
335+
'properties': {
336+
'result': {
337+
'type': 'object',
338+
'properties': {
339+
'err': { 'type': 'string' },
340+
'data': { 'type': 'object' }
341+
}
340342
}
341343
}
342344
}
345+
]
346+
};
347+
348+
expect(deref.resolveAllOf(
349+
schema,
350+
'REQUEST',
351+
{ concreteUtils: schemaUtils30X },
352+
{ resolveTo: 'example' }
353+
)).to.deep.include({
354+
type: 'object',
355+
properties: {
356+
source: {
357+
type: 'string',
358+
format: 'uuid'
359+
},
360+
actionId: { 'type': 'integer', 'minimum': 5 },
361+
result: {
362+
type: 'object',
363+
properties: {
364+
err: { 'type': 'string' },
365+
data: { 'type': 'object' }
366+
}
367+
}
343368
}
344-
];
369+
});
370+
done();
371+
});
372+
373+
it('should resolve schemas containing allOf keyword along with outer properties correctly', function (done) {
374+
var schema = {
375+
'properties': {
376+
'id': {
377+
'type': 'integer'
378+
},
379+
'name': {
380+
'type': 'string'
381+
},
382+
'type': {
383+
'type': 'string',
384+
'enum': ['capsule', 'probe', 'satellite', 'spaceplane', 'station']
385+
},
386+
'registerdDate': {
387+
'type': 'string',
388+
'format': 'date-time'
389+
}
390+
},
391+
'allOf': [
392+
{
393+
'type': 'object',
394+
'properties': {
395+
'source': {
396+
'type': 'string',
397+
'format': 'uuid'
398+
},
399+
'actionId': { 'type': 'integer', 'minimum': 5 },
400+
'result': { 'type': 'object' }
401+
},
402+
'required': ['source', 'actionId', 'result']
403+
},
404+
{
405+
'properties': {
406+
'result': {
407+
'type': 'object',
408+
'properties': {
409+
'err': { 'type': 'string' },
410+
'data': { 'type': 'object' }
411+
}
412+
}
413+
}
414+
}
415+
]
416+
};
345417

346418
expect(deref.resolveAllOf(
347-
allOfschema,
419+
schema,
348420
'REQUEST',
349421
{ concreteUtils: schemaUtils30X },
350422
{ resolveTo: 'example' }
351423
)).to.deep.include({
352424
type: 'object',
353425
properties: {
426+
id: {
427+
type: 'integer'
428+
},
429+
name: {
430+
type: 'string'
431+
},
432+
type: {
433+
type: 'string',
434+
enum: ['capsule', 'probe', 'satellite', 'spaceplane', 'station']
435+
},
436+
registerdDate: {
437+
type: 'string',
438+
format: 'date-time'
439+
},
354440
source: {
355441
type: 'string',
356442
format: 'uuid'

0 commit comments

Comments
 (0)