Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Response schemas #70

Merged
merged 7 commits into from
Jun 28, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 50 additions & 13 deletions src/plugins/validation/2and3/semantic-validators/responses.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,60 @@ module.exports.validate = function({ jsSpec, isOAS3 }, config) {
each(obj, (response, responseKey) => {
if (isOAS3) {
each(response.content, (mediaType, mediaTypeKey) => {
const hasInlineSchema = mediaType.schema && !mediaType.schema.$ref;
const combinedSchemaTypes = ['allOf', 'oneOf', 'anyOf'];
const hasOfProperty =
mediaType.schema.allOf ||
mediaType.schema.anyOf ||
mediaType.schema.oneOf;
SamerJaser96 marked this conversation as resolved.
Show resolved Hide resolved

if (
hasInlineSchema &&
mediaType.schema &&
mediaTypeKey.startsWith('application/json')
) {
const checkStatus = config.inline_response_schema;
if (checkStatus !== 'off') {
result[checkStatus].push({
path: [
...path,
responseKey,
'content',
mediaTypeKey,
'schema'
],
message: INLINE_SCHEMA_MESSAGE
if (hasOfProperty) {
combinedSchemaTypes.forEach(schemaType => {
if (mediaType.schema[schemaType]) {
for (
let i = 0;
i < mediaType.schema[schemaType].length;
i++
) {
const hasInlineSchema = !mediaType.schema[schemaType][i]
.$ref;
if (hasInlineSchema) {
const checkStatus = config.inline_response_schema;
if (checkStatus !== 'off') {
result[checkStatus].push({
path: [
...path,
responseKey,
'content',
mediaTypeKey,
'schema',
schemaType,
i
],
message: INLINE_SCHEMA_MESSAGE
});
}
}
}
}
});
} else if (!mediaType.schema.$ref) {
const checkStatus = config.inline_response_schema;
if (checkStatus !== 'off') {
result[checkStatus].push({
path: [
...path,
responseKey,
'content',
mediaTypeKey,
'schema'
],
message: INLINE_SCHEMA_MESSAGE
});
}
}
}
});
Expand Down
263 changes: 263 additions & 0 deletions test/plugins/validation/2and3/responses.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,116 @@ describe('validation plugin - semantic - responses', function() {
expect(res.errors.length).toEqual(0);
});

it('should not complain for a valid response in oneOf', function() {
const spec = {
paths: {
'/stuff': {
get: {
summary: 'list stuff',
operationId: 'listStuff',
responses: {
200: {
description: 'successful operation',
content: {
'application/json': {
schema: {
oneOf: [
{
$ref:
'#/components/schemas/ListStuffResponseModel'
},
{
$ref: '#/components/schemas/ListStuffSecondModel'
}
]
}
}
}
}
}
}
}
}
};

const res = validate({ jsSpec: spec, isOAS3: true }, config);
expect(res.warnings.length).toEqual(0);
expect(res.errors.length).toEqual(0);
});

it('should not complain for a valid response in allOf', function() {
const spec = {
paths: {
'/stuff': {
get: {
summary: 'list stuff',
operationId: 'listStuff',
responses: {
200: {
description: 'successful operation',
content: {
'application/json': {
schema: {
allOf: [
{
$ref:
'#/components/schemas/ListStuffResponseModel'
},
{
$ref: '#/components/schemas/ListStuffSecondModel'
}
]
}
}
}
}
}
}
}
}
};

const res = validate({ jsSpec: spec, isOAS3: true }, config);
expect(res.warnings.length).toEqual(0);
expect(res.errors.length).toEqual(0);
});

it('should not complain for a valid response in anyOf', function() {
const spec = {
paths: {
'/stuff': {
get: {
summary: 'list stuff',
operationId: 'listStuff',
responses: {
200: {
description: 'successful operation',
content: {
'application/json': {
schema: {
anyOf: [
{
$ref:
'#/components/schemas/ListStuffResponseModel'
},
{
$ref: '#/components/schemas/ListStuffSecondModel'
}
]
}
}
}
}
}
}
}
}
};

const res = validate({ jsSpec: spec, isOAS3: true }, config);
expect(res.warnings.length).toEqual(0);
expect(res.errors.length).toEqual(0);
});
it('should complain about an inline schema', function() {
const spec = {
paths: {
Expand Down Expand Up @@ -208,6 +318,159 @@ describe('validation plugin - semantic - responses', function() {
expect(res.errors.length).toEqual(0);
});

it('should complain about an inline schema when using oneOf', function() {
const spec = {
paths: {
'/stuff': {
get: {
summary: 'list stuff',
operationId: 'listStuff',
responses: {
200: {
description: 'successful operation',
content: {
'application/json': {
schema: {
oneOf: [
SamerJaser96 marked this conversation as resolved.
Show resolved Hide resolved
{
type: 'object'
},
{
$ref: 'ref1'
}
]
}
}
}
}
}
}
}
}
};

const res = validate({ jsSpec: spec, isOAS3: true }, config);
expect(res.warnings.length).toEqual(1);
expect(res.warnings[0].path).toEqual([
'paths',
'/stuff',
'get',
'responses',
'200',
'content',
'application/json',
'schema',
'oneOf',
0
]);
expect(res.warnings[0].message).toEqual(
'Response schemas should be defined with a named ref.'
);
expect(res.errors.length).toEqual(0);
});

it('should complain about an inline schema when using allOf', function() {
const spec = {
paths: {
'/stuff': {
get: {
summary: 'list stuff',
operationId: 'listStuff',
responses: {
200: {
description: 'successful operation',
content: {
'application/json': {
schema: {
allOf: [
{
type: 'object'
},
{
$ref: 'ref1'
}
]
}
}
}
}
}
}
}
}
};

const res = validate({ jsSpec: spec, isOAS3: true }, config);
expect(res.warnings.length).toEqual(1);
expect(res.warnings[0].path).toEqual([
'paths',
'/stuff',
'get',
'responses',
'200',
'content',
'application/json',
'schema',
'allOf',
0
]);
expect(res.warnings[0].message).toEqual(
'Response schemas should be defined with a named ref.'
);
expect(res.errors.length).toEqual(0);
});

it('should complain about an inline schema when using anyOf', function() {
const spec = {
paths: {
'/stuff': {
get: {
summary: 'list stuff',
operationId: 'listStuff',
responses: {
200: {
description: 'successful operation',
content: {
'application/json': {
schema: {
anyOf: [
{
type: 'object'
},
{
$ref: 'ref1'
}
]
SamerJaser96 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
}
}
}
}
};

const res = validate({ jsSpec: spec, isOAS3: true }, config);
expect(res.warnings.length).toEqual(1);
expect(res.warnings[0].path).toEqual([
'paths',
'/stuff',
'get',
'responses',
'200',
'content',
'application/json',
'schema',
'anyOf',
0
]);
expect(res.warnings[0].message).toEqual(
'Response schemas should be defined with a named ref.'
);
expect(res.errors.length).toEqual(0);
});

it('should not complain for a response with no schema', function() {
const spec = {
paths: {
Expand Down