Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit 639ec82

Browse files
committed
fix(oas3): handle invalid schema components
1 parent 4139afa commit 639ec82

File tree

5 files changed

+87
-32
lines changed

5 files changed

+87
-32
lines changed

packages/fury-adapter-oas3-parser/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
- Added primitive support for generating a JSON message body from a schema for
1111
JSON media types. Referencing is not supported for this feature.
1212

13+
### Bug Fixes
14+
15+
- Prevents an exception being raised due to improper handling of invalid
16+
schemas found in the reusable components section of an OpenAPI 3 document.
17+
1318
## 0.6.0 (2019-02-26)
1419

1520
### Enhancements

packages/fury-adapter-oas3-parser/lib/parser/oas/parseComponentsObject.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,12 @@ function parseComponentsObject(context, element) {
120120
R.compose(parseObject(context, name, parseMember), getValue));
121121
};
122122

123-
// eslint-disable-next-line no-param-reassign
124-
const setDataStructureId = (dataStructure, key) => { dataStructure.content.id = key.clone(); };
123+
const setDataStructureId = (dataStructure, key) => {
124+
if (dataStructure) {
125+
// eslint-disable-next-line no-param-reassign
126+
dataStructure.content.id = key.clone();
127+
}
128+
};
125129
const parseSchemas = pipeParseResult(namespace,
126130
parseComponentObjectMember(parseSchemaObject),
127131
(object) => {

packages/fury-adapter-oas3-parser/lib/parser/oas/parseOpenAPIObject.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,14 @@ function parseOASObject(context, object) {
144144

145145
const components = object.get('components');
146146
if (components) {
147-
const schemas = components.get('schemas');
148-
if (schemas) {
147+
const schemas = R.or(components.get('schemas'), new namespace.elements.Array())
148+
.content
149+
.filter(member => member.value)
150+
.map(getValue);
151+
152+
if (schemas.length > 0) {
149153
const dataStructures = new namespace.elements.Category(
150-
schemas.content.map(getValue),
151-
{ classes: ['dataStructures'] }
154+
schemas, { classes: ['dataStructures'] }
152155
);
153156
api.push(dataStructures);
154157
}
@@ -157,7 +160,6 @@ function parseOASObject(context, object) {
157160
return api;
158161
});
159162

160-
161163
if (context.options.generateSourceMap) {
162164
return filterColumnLine(parseOASObject(object));
163165
}

packages/fury-adapter-oas3-parser/test/unit/parser/oas/parseComponentsObject-test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,27 @@ describe('Components Object', () => {
5050
expect(schemas).to.be.instanceof(namespace.elements.Object);
5151
expect(schemas.get('User')).to.be.instanceof(namespace.elements.DataStructure);
5252
});
53+
54+
it('parses invalid schema into empty member', () => {
55+
const components = new namespace.elements.Object({
56+
schemas: {
57+
User: null,
58+
},
59+
});
60+
61+
const parseResult = parse(context, components);
62+
expect(parseResult.length).to.equal(2);
63+
64+
const parsedComponents = parseResult.get(0);
65+
expect(parsedComponents).to.be.instanceof(namespace.elements.Object);
66+
67+
const schemas = parsedComponents.get('schemas');
68+
expect(schemas).to.be.instanceof(namespace.elements.Object);
69+
70+
const member = schemas.getMember('User');
71+
expect(member).to.be.instanceof(namespace.elements.Member);
72+
expect(member.value).to.be.undefined;
73+
});
5374
});
5475

5576
describe('#parameters', () => {

packages/fury-adapter-oas3-parser/test/unit/parser/oas/parseOpenAPIObject-test.js

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -47,36 +47,59 @@ describe('#parseOpenAPIObject', () => {
4747
expect(parseResult.api.get(0).href.toValue()).to.equal('/');
4848
});
4949

50-
it('can parse a document with schema components into data structures', () => {
51-
const object = new namespace.elements.Object({
52-
openapi: '3.0.0',
53-
info: {
54-
title: 'My API',
55-
version: '1.0.0',
56-
},
57-
paths: {},
58-
components: {
59-
schemas: {
60-
User: {
61-
type: 'object',
50+
describe('with schema components', () => {
51+
it('can parse a document with schema components into data structures', () => {
52+
const object = new namespace.elements.Object({
53+
openapi: '3.0.0',
54+
info: {
55+
title: 'My API',
56+
version: '1.0.0',
57+
},
58+
paths: {},
59+
components: {
60+
schemas: {
61+
User: {
62+
type: 'object',
63+
},
6264
},
6365
},
64-
},
65-
});
66+
});
6667

67-
const parseResult = parse(context, object);
68-
expect(parseResult.length).to.equal(1);
69-
expect(parseResult.api.title.toValue()).to.equal('My API');
70-
expect(parseResult.api.length).to.equal(1);
68+
const parseResult = parse(context, object);
69+
expect(parseResult.length).to.equal(1);
70+
expect(parseResult.api.title.toValue()).to.equal('My API');
71+
expect(parseResult.api.length).to.equal(1);
72+
73+
const dataStructures = parseResult.api.get(0);
74+
expect(dataStructures).to.be.instanceof(namespace.elements.Category);
75+
expect(dataStructures.classes.toValue()).to.deep.equal(['dataStructures']);
76+
expect(dataStructures.length).to.equal(1);
77+
78+
const userStructure = dataStructures.get(0);
79+
expect(userStructure).to.be.instanceof(namespace.elements.DataStructure);
80+
expect(userStructure.content.id.toValue()).to.equal('User');
81+
});
7182

72-
const dataStructures = parseResult.api.get(0);
73-
expect(dataStructures).to.be.instanceof(namespace.elements.Category);
74-
expect(dataStructures.classes.toValue()).to.deep.equal(['dataStructures']);
75-
expect(dataStructures.length).to.equal(1);
83+
it('can parse a document with invalid schema component', () => {
84+
const object = new namespace.elements.Object({
85+
openapi: '3.0.0',
86+
info: {
87+
title: 'My API',
88+
version: '1.0.0',
89+
},
90+
paths: {},
91+
components: {
92+
schemas: {
93+
User: null,
94+
},
95+
},
96+
});
7697

77-
const userStructure = dataStructures.get(0);
78-
expect(userStructure).to.be.instanceof(namespace.elements.DataStructure);
79-
expect(userStructure.content.id.toValue()).to.equal('User');
98+
const parseResult = parse(context, object);
99+
expect(parseResult.length).to.equal(2);
100+
expect(parseResult.api.title.toValue()).to.equal('My API');
101+
expect(parseResult.api.isEmpty).to.be.true;
102+
});
80103
});
81104

82105
it('provides error for missing openapi version', () => {

0 commit comments

Comments
 (0)