Skip to content

Commit

Permalink
refactor: change rules a bit for request body names check
Browse files Browse the repository at this point in the history
  • Loading branch information
dpopp07 committed Apr 30, 2019
1 parent a229fc0 commit d87497e
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 12 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ The default values for each rule are described below.
| Rule | Default |
| --------------------------- | --------|
| no_request_body_content | error |
| no_request_body_name | error |
| no_request_body_name | warning |

###### parameters
| Rule | Default |
Expand Down
32 changes: 28 additions & 4 deletions src/plugins/validation/oas3/semantic-validators/operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

const pick = require('lodash/pick');
const each = require('lodash/each');
const at = require('lodash/at');

module.exports.validate = function({ resolvedSpec }, config) {
module.exports.validate = function({ resolvedSpec, jsSpec }, config) {
const result = {};
result.error = [];
result.warning = [];
Expand Down Expand Up @@ -42,9 +43,32 @@ module.exports.validate = function({ resolvedSpec }, config) {
} else {
// request body has content
const firstMimeType = requestBodyMimeTypes[0]; // code generation uses the first mime type
const oneContentType = requestBodyMimeTypes.length === 1;
const isJson = firstMimeType === 'application/json';

const hasArraySchema =
requestBodyContent[firstMimeType].schema &&
requestBodyContent[firstMimeType].schema.type === 'array';

const hasRequestBodyName =
op[REQUEST_BODY_NAME] && op[REQUEST_BODY_NAME].trim().length;
if (isBodyParameter(firstMimeType) && !hasRequestBodyName) {

// non-array json responses with only one content type will have
// the body exploded in sdk generation, no need for name
const explodingBody = oneContentType && isJson && !hasArraySchema;

// referenced request bodies have names
const referencedRequestBody = Boolean(
at(jsSpec, `paths.${pathName}.${opName}.requestBody`)[0].$ref
);

// form params do not need names
if (
!isFormParameter(firstMimeType) &&
!explodingBody &&
!referencedRequestBody &&
!hasRequestBodyName
) {
const checkStatus = config.no_request_body_name;
if (checkStatus != 'off') {
const message =
Expand All @@ -63,11 +87,11 @@ module.exports.validate = function({ resolvedSpec }, config) {
return { errors: result.error, warnings: result.warning };
};

function isBodyParameter(mimeType) {
function isFormParameter(mimeType) {
const formDataMimeTypes = [
'multipart/form-data',
'application/x-www-form-urlencoded',
'application/octet-stream'
];
return !formDataMimeTypes.includes(mimeType);
return formDataMimeTypes.includes(mimeType);
}
83 changes: 76 additions & 7 deletions test/plugins/validation/oas3/operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('validation plugin - semantic - operations - oas3', function() {
}
};

const res = validate({ resolvedSpec: spec }, config);
const res = validate({ resolvedSpec: spec, jsSpec: spec }, config);
expect(res.errors.length).toEqual(1);
expect(res.errors[0].path).toEqual('paths./pets.post.requestBody');
expect(res.errors[0].message).toEqual(
Expand All @@ -29,7 +29,7 @@ describe('validation plugin - semantic - operations - oas3', function() {
expect(res.warnings.length).toEqual(0);
});

it('should warn about an operation with a non-form request body that does not set a name', function() {
it('should warn about an operation with a non-form, array schema request body that does not set a name', function() {
const spec = {
paths: {
'/pets': {
Expand All @@ -41,7 +41,10 @@ describe('validation plugin - semantic - operations - oas3', function() {
content: {
'application/json': {
schema: {
type: 'string'
type: 'array',
items: {
type: 'string'
}
}
}
}
Expand All @@ -51,7 +54,7 @@ describe('validation plugin - semantic - operations - oas3', function() {
}
};

const res = validate({ resolvedSpec: spec }, config);
const res = validate({ resolvedSpec: spec, jsSpec: spec }, config);
expect(res.warnings.length).toEqual(1);
expect(res.warnings[0].path).toEqual('paths./pets.post');
expect(res.warnings[0].message).toEqual(
Expand All @@ -60,6 +63,33 @@ describe('validation plugin - semantic - operations - oas3', function() {
expect(res.errors.length).toEqual(0);
});

it('should not warn about an operation with a non-array json request body that does not set a name', function() {
const spec = {
paths: {
'/pets': {
post: {
summary: 'this is a summary',
operationId: 'operationId',
requestBody: {
description: 'body for request',
content: {
'application/json': {
schema: {
type: 'string'
}
}
}
}
}
}
}
};

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

it('should not warn about an operation with a non-form request body that sets a name', function() {
const spec = {
paths: {
Expand All @@ -83,12 +113,11 @@ describe('validation plugin - semantic - operations - oas3', function() {
}
};

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

// should not warn about a form request body
it('should not warn about an operation with a form request body that does not set a name', function() {
const spec = {
paths: {
Expand Down Expand Up @@ -116,7 +145,47 @@ describe('validation plugin - semantic - operations - oas3', function() {
}
};

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

it('should not warn about an operation with a referenced request body that does not set a name', function() {
const resolvedSpec = {
paths: {
'/pets': {
post: {
summary: 'this is a summary',
operationId: 'operationId',
requestBody: {
content: {
'application/json': {
schema: {
type: 'string'
}
}
}
}
}
}
}
};

const jsSpec = {
paths: {
'/pets': {
post: {
summary: 'this is a summary',
operationId: 'operationId',
requestBody: {
$ref: '#/components/requestBodies/SomeBody'
}
}
}
}
};

const res = validate({ resolvedSpec, jsSpec }, config);
expect(res.warnings.length).toEqual(0);
expect(res.errors.length).toEqual(0);
});
Expand Down

0 comments on commit d87497e

Please sign in to comment.