Skip to content

Commit

Permalink
fix: use parameter-determining method in all parameters validations (#97
Browse files Browse the repository at this point in the history
)

* before, it was only used in the shared validations
* also, refactor validator utils into single module
* also, remove checkSnakeCase module - it was replaced by caseConventionCheck
  • Loading branch information
dpopp07 committed Aug 6, 2019
1 parent 6540256 commit ee1168f
Show file tree
Hide file tree
Showing 15 changed files with 80 additions and 114 deletions.
9 changes: 0 additions & 9 deletions src/plugins/utils/checkSnakeCase.js

This file was deleted.

5 changes: 5 additions & 0 deletions src/plugins/utils/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Expose validator utils as a module with each sub-module as a property

module.exports.checkCase = require('./caseConventionCheck');
module.exports.walk = require('./walk');
module.exports.isParameterObject = require('./isParameter');
29 changes: 29 additions & 0 deletions src/plugins/utils/isParameter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module.exports = (path, isOAS3) => {
const pathsForParameters = [
'get',
'put',
'post',
'delete',
'options',
'head',
'patch',
'trace',
'components'
];

const inParametersSection = path[path.length - 2] === 'parameters';

// the above check is a necessary but not sufficient check for a parameter object
// use the following checks to verify the object is where a parameter is supposed to be.
// without these, a schema property named "parameters" would get validated as a parameter
const isParameterByPath = pathsForParameters.includes(path[path.length - 3]);
const isPathItemParameter =
path[path.length - 4] === 'paths' && path.length === 4;
const isTopLevelParameter =
!isOAS3 && path[0] === 'parameters' && path.length === 2;

return (
inParametersSection &&
(isParameterByPath || isPathItemParameter || isTopLevelParameter)
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// (For Swagger 2 specs. In the OAS 3 spec, headers do not have types. Their schemas will be checked by Assertation 1):
// Headers with 'array' type require an 'items' property

const walk = require('../../../utils/walk');
const { walk } = require('../../../utils');

module.exports.validate = function({ jsSpec }) {
const errors = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const pick = require('lodash/pick');
const map = require('lodash/map');
const each = require('lodash/each');
const findIndex = require('lodash/findIndex');
const checkCase = require('../../../utils/caseConventionCheck');
const { checkCase } = require('../../../utils');

module.exports.validate = function({ resolvedSpec, isOAS3 }, config) {
const result = {};
Expand Down
35 changes: 2 additions & 33 deletions src/plugins/validation/2and3/semantic-validators/parameters-ibm.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

const pick = require('lodash/pick');
const includes = require('lodash/includes');
const checkCase = require('../../../utils/caseConventionCheck');
const walk = require('../../../utils/walk');
const { checkCase, isParameterObject, walk } = require('../../../utils');

module.exports.validate = function({ jsSpec, isOAS3 }, config) {
const result = {};
Expand All @@ -26,7 +25,7 @@ module.exports.validate = function({ jsSpec, isOAS3 }, config) {
return;
}

const contentsOfParameterObject = isParameter(path, isOAS3);
const contentsOfParameterObject = isParameterObject(path, isOAS3);

if (contentsOfParameterObject) {
// obj is a parameter object
Expand Down Expand Up @@ -158,36 +157,6 @@ module.exports.validate = function({ jsSpec, isOAS3 }, config) {
return { errors: result.error, warnings: result.warning };
};

function isParameter(path, isOAS3) {
const pathsForParameters = [
'get',
'put',
'post',
'delete',
'options',
'head',
'patch',
'trace',
'components'
];

const inParametersSection = path[path.length - 2] === 'parameters';

// the above check is a necessary but not sufficient check for a parameter object
// use the following checks to verify the object is where a parameter is supposed to be.
// without these, a schema property named "parameters" would get validated as a parameter
const isParameterByPath = pathsForParameters.includes(path[path.length - 3]);
const isPathItemParameter =
path[path.length - 4] === 'paths' && path.length === 4;
const isTopLevelParameter =
!isOAS3 && path[0] === 'parameters' && path.length === 2;

return (
inParametersSection &&
(isParameterByPath || isPathItemParameter || isTopLevelParameter)
);
}

function formatValid(obj, isOAS3) {
// References will be checked when the parameters / definitions / components are scanned.
if (obj.$ref || (obj.schema && obj.schema.$ref)) {
Expand Down
5 changes: 2 additions & 3 deletions src/plugins/validation/2and3/semantic-validators/paths-ibm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

// Assertation 3. All path segments are lower snake case

const isSnakecase = require('../../../utils/checkSnakeCase');
const checkCase = require('../../../utils/caseConventionCheck');
const { checkCase } = require('../../../utils');

module.exports.validate = function({ resolvedSpec }, config) {
const result = {};
Expand Down Expand Up @@ -128,7 +127,7 @@ module.exports.validate = function({ resolvedSpec }, config) {
if (segment === '' || segment[0] === '{') {
return;
}
if (!isSnakecase(segment)) {
if (!checkCase(segment, 'lower_snake_case')) {
result[checkStatus].push({
path: `paths.${pathName}`,
message: `Path segments must be lower snake case.`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const each = require('lodash/each');
const walk = require('../../../utils/walk');
const { walk } = require('../../../utils');

const INLINE_SCHEMA_MESSAGE =
'Response schemas should be defined with a named ref.';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@

const forIn = require('lodash/forIn');
const includes = require('lodash/includes');
const isSnakecase = require('../../../utils/checkSnakeCase');
const checkCase = require('../../../utils/caseConventionCheck');
const walk = require('../../../utils/walk');
const { checkCase, walk } = require('../../../utils');

module.exports.validate = function({ jsSpec, isOAS3 }, config) {
const errors = [];
Expand Down Expand Up @@ -304,7 +302,7 @@ function checkPropNames(schema, contextPath, config) {

const checkStatus = config.snake_case_only || 'off';
if (checkStatus.match('error|warning')) {
if (!isSnakecase(propName)) {
if (!checkCase(propName, 'lower_snake_case')) {
result[checkStatus].push({
path: contextPath.concat(['properties', propName]),
message: 'Property names must be lower snake case.'
Expand Down Expand Up @@ -372,7 +370,7 @@ function checkEnumValues(schema, contextPath, config) {
if (typeof enumValue === 'string') {
const checkStatus = config.snake_case_only || 'off';
if (checkStatus.match('error|warning')) {
if (!isSnakecase(enumValue)) {
if (!checkCase(enumValue, 'lower_snake_case')) {
result[checkStatus].push({
path: contextPath.concat(['enum', i.toString()]),
message: 'Enum values must be lower snake case.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Description siblings to $refs should not exist if identical to referenced description

const at = require('lodash/at');
const walk = require('../../../utils/walk');
const { walk } = require('../../../utils');

// Walks an entire spec.
module.exports.validate = function({ jsSpec, resolvedSpec }, config) {
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/validation/2and3/semantic-validators/walker.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// http://watson-developer-cloud.github.io/api-guidelines/swagger-coding-style#sibling-elements-for-refs

const match = require('matcher');
const walk = require('../../../utils/walk');
const { walk } = require('../../../utils');

module.exports.validate = function({ jsSpec, isOAS3 }, config) {
const result = {};
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/validation/oas3/semantic-validators/parameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#parameterObject

const walk = require('../../../utils/walk');
const { isParameterObject, walk } = require('../../../utils');

module.exports.validate = function({ jsSpec }, config) {
const result = {};
Expand All @@ -17,7 +17,7 @@ module.exports.validate = function({ jsSpec }, config) {
config = config.parameters;

walk(jsSpec, [], function(obj, path) {
const isContentsOfParameterObject = path[path.length - 2] === 'parameters';
const isContentsOfParameterObject = isParameterObject(path, true); // 2nd arg is isOAS3
const isRef = !!obj.$ref;

// obj is a parameter object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Assertation 2:
// At least one response "SHOULD be the response for a successful operation call"

const walk = require('../../../utils/walk');
const { walk } = require('../../../utils');

module.exports.validate = function({ jsSpec }, config) {
const result = {};
Expand Down
20 changes: 6 additions & 14 deletions src/plugins/validation/swagger2/semantic-validators/parameters.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
// Assertation 1:
// The items property for a parameter is required when its type is set to array

const { isParameterObject, walk } = require('../../../utils');

module.exports.validate = function({ resolvedSpec }) {
const errors = [];
const warnings = [];

function walk(obj, path) {
if (typeof obj !== 'object' || obj === null) {
return;
}
walk(resolvedSpec, [], (obj, path) => {
const isContentsOfParameterObject = isParameterObject(path, false); // 2nd arg is isOAS3

// 1
if (path[path.length - 2] === 'parameters') {
if (isContentsOfParameterObject) {
if (obj.type === 'array' && typeof obj.items !== 'object') {
errors.push({
path,
message: "Parameters with 'array' type require an 'items' property."
});
}
}

if (Object.keys(obj).length) {
return Object.keys(obj).map(k => walk(obj[k], [...path, k]));
} else {
return null;
}
}

walk(resolvedSpec, []);
});

return { errors, warnings };
};
67 changes: 25 additions & 42 deletions test/plugins/validation/oas3/parameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,10 @@ const expect = require('expect');
const {
validate
} = require('../../../../src/plugins/validation/oas3/semantic-validators/parameters');
const config = require('../../../../src/.defaultsForValidator').defaults.oas3;

describe('validation plugin - semantic - parameters - oas3', function() {
it('should not complain when parameter is valid', function() {
const config = {
parameters: {
no_in_property: 'error',
invalid_in_property: 'error',
missing_schema_or_content: 'error',
has_schema_and_content: 'error'
}
};

const spec = {
paths: {
'/pets': {
Expand Down Expand Up @@ -53,12 +45,6 @@ describe('validation plugin - semantic - parameters - oas3', function() {
});

it('should complain when `in` is missing', function() {
const config = {
parameters: {
no_in_property: 'error'
}
};

const spec = {
paths: {
'/pets': {
Expand Down Expand Up @@ -107,12 +93,6 @@ describe('validation plugin - semantic - parameters - oas3', function() {
});

it('should complain when `in` is an invalid value', function() {
const config = {
parameters: {
invalid_in_property: 'error'
}
};

const spec = {
paths: {
'/pets': {
Expand Down Expand Up @@ -163,12 +143,6 @@ describe('validation plugin - semantic - parameters - oas3', function() {
});

it('should complain when the parameter has an undescribed data type', function() {
const config = {
parameters: {
missing_schema_or_content: 'error'
}
};

const spec = {
paths: {
'/pets': {
Expand Down Expand Up @@ -215,12 +189,6 @@ describe('validation plugin - semantic - parameters - oas3', function() {
});

it('should complain when a parameter describes data type with both `schema` and `content`', function() {
const config = {
parameters: {
has_schema_and_content: 'error'
}
};

const spec = {
components: {
parameters: {
Expand Down Expand Up @@ -257,15 +225,6 @@ describe('validation plugin - semantic - parameters - oas3', function() {
});

it('should not complain when parameter is a ref', function() {
const config = {
parameters: {
no_in_property: 'error',
invalid_in_property: 'error',
missing_schema_or_content: 'error',
has_schema_and_content: 'error'
}
};

const spec = {
paths: {
'/pets': {
Expand Down Expand Up @@ -310,4 +269,28 @@ describe('validation plugin - semantic - parameters - oas3', function() {
expect(res.errors.length).toEqual(0);
expect(res.warnings.length).toEqual(0);
});

it('should not complain about a schema property named `parameters`', function() {
const spec = {
components: {
schemas: {
SomeModel: {
properties: {
parameters: {
type: 'object',
description: 'A map of key/value pairs',
additionalProperties: {
description: 'A parameter. But not an OpenAPI parameter ;)'
}
}
}
}
}
}
};

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

0 comments on commit ee1168f

Please sign in to comment.