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

Commit f9724a0

Browse files
committed
feat(oas3): respect optional responses in Operation Object
This is a change in OpenAPI 3.1.0
1 parent 540facf commit f9724a0

File tree

3 files changed

+35
-14
lines changed

3 files changed

+35
-14
lines changed

packages/openapi3-parser/lib/context.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ class Context {
3636
hasScheme(id) {
3737
return this.state.hasScheme(id);
3838
}
39+
40+
// Versioning
41+
isOpenAPIVersionLessThan(major, minor) {
42+
return this.openapiVersion.major < major || (this.openapiVersion.major === major && this.openapiVersion.minor < minor);
43+
}
3944
}
4045

4146
module.exports = Context;

packages/openapi3-parser/lib/parser/oas/parseOperationObject.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const parseReference = require('../parseReference');
2121
const parseRequestBodyObjectOrRef = parseReference('requestBodies', parseRequestBodyObject);
2222

2323
const name = 'Operation Object';
24-
const requiredKeys = ['responses'];
2524
const unsupportedKeys = [
2625
'tags', 'externalDocs', 'callbacks', 'deprecated',
2726
];
@@ -31,12 +30,16 @@ const isRequestBody = R.both(isMember, hasKey('requestBody'));
3130

3231
function createTransactions(namespace, member, operation) {
3332
const requests = R.map(getValue, R.filter(isRequestBody, operation.content));
34-
const responses = operation.get('responses');
33+
const responses = R.or(operation.get('responses'), new namespace.elements.Array());
3534

3635
if (requests.length === 0) {
3736
requests.push(new namespace.elements.HttpRequest());
3837
}
3938

39+
if (responses.length === 0) {
40+
responses.push(new namespace.elements.HttpResponse());
41+
}
42+
4043
const transactions = [];
4144

4245
requests.forEach((request) => {
@@ -123,6 +126,11 @@ function parseOperationObject(context, path, member) {
123126
),
124127
]));
125128

129+
const requiredKeys = [];
130+
if (context.isOpenAPIVersionLessThan(3, 1)) {
131+
requiredKeys.push('responses');
132+
}
133+
126134
const parseMember = R.cond([
127135
[hasKey('summary'), parseString(context, name, false)],
128136
[hasKey('description'), parseCopy(context, name, false)],

packages/openapi3-parser/test/unit/parser/oas/parseOperationObject-test.js

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,18 +129,6 @@ describe('Operation Object', () => {
129129
expect(parseResult).to.contain.warning("'Operation Object' contains invalid key 'invalid'");
130130
});
131131

132-
describe('missing required properties', () => {
133-
it('provides error for missing responses', () => {
134-
const operation = new namespace.elements.Member('get', {});
135-
136-
const parseResult = parse(context, path, operation);
137-
138-
expect(parseResult.length).to.equal(1);
139-
expect(parseResult).to.contain.error("'Operation Object' is missing required property 'responses'");
140-
});
141-
});
142-
143-
144132
describe('#summary', () => {
145133
it('warns when summary is not a string', () => {
146134
const operation = new namespace.elements.Member('get', {
@@ -621,6 +609,26 @@ describe('Operation Object', () => {
621609
});
622610

623611
describe('#responses', () => {
612+
it('provides error for missing responses for OpenAPI 3.0', () => {
613+
const operation = new namespace.elements.Member('get', {});
614+
615+
const parseResult = parse(context, path, operation);
616+
617+
expect(parseResult.length).to.equal(1);
618+
expect(parseResult).to.contain.error("'Operation Object' is missing required property 'responses'");
619+
});
620+
621+
it('does not require responses for OpenAPI >= 3.1', () => {
622+
context.openapiVersion.minor = 1;
623+
const operation = new namespace.elements.Member('get', {});
624+
625+
const parseResult = parse(context, path, operation);
626+
627+
expect(parseResult.length).to.equal(1);
628+
const transition = parseResult.get(0);
629+
expect(transition).to.be.instanceof(namespace.elements.Transition);
630+
});
631+
624632
it('returns a transition including a transaction', () => {
625633
const operation = new namespace.elements.Member('get', {
626634
responses: {

0 commit comments

Comments
 (0)