fix: properly host oneOf inside allOf

fixes #507
fixes #528
This commit is contained in:
Roman Hotsiy 2018-07-18 13:03:42 +03:00
parent e0f58dc601
commit 7e5b6d9029
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
4 changed files with 188 additions and 0 deletions

View File

@ -182,6 +182,8 @@ export class OpenAPIParser {
$ref?: string,
forceCircular: boolean = false,
): MergedOpenAPISchema {
schema = this.hoistOneOfs(schema);
if (schema.allOf === undefined) {
return schema;
}
@ -291,4 +293,28 @@ export class OpenAPIParser {
}
return res;
}
private hoistOneOfs(schema: OpenAPISchema) {
if (schema.allOf === undefined) {
return schema;
}
const allOf = schema.allOf;
for (let i = 0; i < allOf.length; i++) {
const sub = allOf[i];
if (Array.isArray(sub.oneOf)) {
const beforeAllOf = allOf.slice(0, i);
const afterAllOf = allOf.slice(i + 1);
return {
oneOf: sub.oneOf.map(part => {
return this.mergeAllOf({
allOf: [...beforeAllOf, part, ...afterAllOf],
});
}),
};
}
}
return schema;
}
}

View File

@ -0,0 +1,16 @@
import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
const opts = new RedocNormalizedOptions({});
describe('Models', () => {
describe('Schema', () => {
let parser;
test('should hoist oneOfs when mergin allOf', () => {
const spec = require('./fixtures/oneOfHoist.json');
parser = new OpenAPIParser(spec, undefined, opts);
expect(parser.mergeAllOf(spec.components.schemas.test)).toMatchSnapshot();
});
});
});

View File

@ -0,0 +1,84 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Models Schema should hoist oneOfs when mergin allOf 1`] = `
Object {
"oneOf": Array [
Object {
"oneOf": Array [
Object {
"allOf": undefined,
"parentRefs": Array [],
"properties": Object {
"extra": Object {
"type": "string",
},
"password": Object {
"description": "The user's password",
"type": "string",
},
"username": Object {
"description": "The user's name",
"type": "string",
},
},
},
Object {
"allOf": undefined,
"parentRefs": Array [],
"properties": Object {
"extra": Object {
"type": "string",
},
"mobile": Object {
"description": "The user's mobile",
"type": "string",
},
"username": Object {
"description": "The user's name",
"type": "string",
},
},
},
],
},
Object {
"oneOf": Array [
Object {
"allOf": undefined,
"parentRefs": Array [],
"properties": Object {
"email": Object {
"description": "The user's email",
"type": "string",
},
"extra": Object {
"type": "string",
},
"password": Object {
"description": "The user's password",
"type": "string",
},
},
},
Object {
"allOf": undefined,
"parentRefs": Array [],
"properties": Object {
"email": Object {
"description": "The user's email",
"type": "string",
},
"extra": Object {
"type": "string",
},
"mobile": Object {
"description": "The user's mobile",
"type": "string",
},
},
},
],
},
],
}
`;

View File

@ -0,0 +1,62 @@
{
"openapi": "3.0.0",
"info": {
"version": "1.0",
"title": "Foo"
},
"components": {
"schemas": {
"test": {
"allOf": [
{
"oneOf": [
{
"properties": {
"username": {
"description": "The user's name",
"type": "string"
}
}
},
{
"properties": {
"email": {
"description": "The user's email",
"type": "string"
}
}
}
]
},
{
"properties": {
"extra": {
"type": "string"
}
}
},
{
"oneOf": [
{
"properties": {
"password": {
"description": "The user's password",
"type": "string"
}
}
},
{
"properties": {
"mobile": {
"description": "The user's mobile",
"type": "string"
}
}
}
]
}
]
}
}
}
}