diff --git a/src/plugins/validation/2and3/semantic-validators/parameters-ibm.js b/src/plugins/validation/2and3/semantic-validators/parameters-ibm.js index c56d8a963..77dffed7d 100644 --- a/src/plugins/validation/2and3/semantic-validators/parameters-ibm.js +++ b/src/plugins/validation/2and3/semantic-validators/parameters-ibm.js @@ -26,10 +26,10 @@ module.exports.validate = function({ jsSpec, isOAS3 }, config) { return; } - const contentsOfParameterObject = path[path.length - 2] === 'parameters'; + const contentsOfParameterObject = isParameter(path, isOAS3); - // obj is a parameter object if (contentsOfParameterObject) { + // obj is a parameter object const isRef = !!obj.$ref; const hasDescription = !!obj.description; @@ -157,6 +157,36 @@ 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)) { diff --git a/test/plugins/validation/2and3/parameters-ibm.js b/test/plugins/validation/2and3/parameters-ibm.js index 4fe9c35cd..0731604e6 100644 --- a/test/plugins/validation/2and3/parameters-ibm.js +++ b/test/plugins/validation/2and3/parameters-ibm.js @@ -299,9 +299,58 @@ describe('validation plugin - semantic - parameters-ibm', () => { expect(res.errors.length).toEqual(0); expect(res.warnings.length).toEqual(0); }); + + it('should return an error for bad parameters that live in the top level', () => { + const spec = { + parameters: [ + { + name: 'someparam', + in: 'header', + type: 'string', + required: true + } + ] + }; + + const res = validate({ jsSpec: spec, isOAS3: false }, config); + expect(res.errors.length).toEqual(1); + expect(res.errors[0].message).toEqual( + 'Parameter objects must have a `description` field.' + ); + expect(res.warnings.length).toEqual(0); + }); }); describe('OpenAPI 3', () => { + it('should not complain about a property named parameters that is not a parameter object', () => { + const spec = { + components: { + responses: { + parameters: { + description: 'successful operation', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + parameters: { + type: 'string', + description: 'this is a description', + additionalProperties: {} + } + } + } + } + } + } + } + } + }; + const res = validate({ jsSpec: spec, isOAS3: true }, config); + expect(res.warnings.length).toEqual(0); + expect(res.errors.length).toEqual(0); + }); + it('should return an error when a parameter defines content-type, accept, or authorization', () => { const spec = { paths: { @@ -510,5 +559,31 @@ describe('validation plugin - semantic - parameters-ibm', () => { expect(res.warnings.length).toEqual(0); expect(res.errors.length).toEqual(0); }); + + it('should complain about parameters not defined properly in a path item ', () => { + const spec = { + paths: { + '/pets': { + parameters: [ + { + name: 'tags', + in: 'query', + schema: { + type: 'string', + format: 'binary' + } + } + ] + } + } + }; + + const res = validate({ jsSpec: spec, isOAS3: true }, config); + expect(res.warnings.length).toEqual(0); + expect(res.errors.length).toEqual(1); + expect(res.errors[0].message).toEqual( + 'Parameter objects must have a `description` field.' + ); + }); }); });