diff --git a/src/plugins/validation/oas3/semantic-validators/operations.js b/src/plugins/validation/oas3/semantic-validators/operations.js index bbb7bb9ad..365a4d152 100644 --- a/src/plugins/validation/oas3/semantic-validators/operations.js +++ b/src/plugins/validation/oas3/semantic-validators/operations.js @@ -59,7 +59,8 @@ module.exports.validate = function({ resolvedSpec, jsSpec }, config) { // referenced request bodies have names const referencedRequestBody = Boolean( - at(jsSpec, `paths.${pathName}.${opName}.requestBody`)[0].$ref + at(jsSpec, `paths['${pathName}']['${opName}']['requestBody']`)[0] + .$ref ); // form params do not need names diff --git a/test/plugins/validation/2and3/paths-ibm.js b/test/plugins/validation/2and3/paths-ibm.js index a9f4976ac..745273619 100644 --- a/test/plugins/validation/2and3/paths-ibm.js +++ b/test/plugins/validation/2and3/paths-ibm.js @@ -305,6 +305,40 @@ describe('validation plugin - semantic - paths-ibm', function() { ); }); + it('should flag a path segment with a period in the name', function() { + const config = { + paths: { + snake_case_only: 'off', + paths_case_convention: ['warning', 'lower_snake_case'] + } + }; + + const spec = { + paths: { + '/v1/api/not.good_.segment/{id}/resource': { + parameters: [ + { + in: 'path', + name: 'id', + description: 'id param', + type: 'string' + } + ] + } + } + }; + + const res = validate({ resolvedSpec: spec }, config); + expect(res.errors.length).toEqual(0); + expect(res.warnings.length).toEqual(1); + expect(res.warnings[0].path).toEqual( + 'paths./v1/api/not.good_.segment/{id}/resource' + ); + expect(res.warnings[0].message).toEqual( + 'Path segments must follow case convention: lower_snake_case' + ); + }); + it('should flag a path segment that does not follow paths_case_convention but should ignore path parameter', function() { const config = { paths: { diff --git a/test/plugins/validation/2and3/walker-ibm.js b/test/plugins/validation/2and3/walker-ibm.js index 65aac34e9..d70120141 100644 --- a/test/plugins/validation/2and3/walker-ibm.js +++ b/test/plugins/validation/2and3/walker-ibm.js @@ -179,4 +179,53 @@ describe('validation plugin - semantic - walker-ibm', () => { 'Description sibling to $ref matches that of the referenced schema. This is redundant and should be removed.' ); }); + + it('should not crash in duplicate description test if path contains a period', async () => { + const spec = { + paths: { + '/other.stuff': { + get: { + summary: 'list stuff', + operationId: 'listStuff', + produces: ['application/json'], + responses: { + 200: { + description: 'successful operation', + schema: { + $ref: '#/responses/Success', + description: 'simple success response' + } + } + } + } + } + }, + responses: { + Success: { + type: 'string', + description: 'simple success response' + } + } + }; + + // clone spec, otherwise 'dereference' will change the spec by reference + const specCopy = JSON.parse(JSON.stringify(spec)); + const resolvedSpec = await resolver.dereference(specCopy); + + const res = validate({ jsSpec: spec, resolvedSpec }, config); + expect(res.errors.length).toEqual(0); + expect(res.warnings.length).toEqual(1); + expect(res.warnings[0].path).toEqual([ + 'paths', + '/other.stuff', + 'get', + 'responses', + '200', + 'schema', + 'description' + ]); + expect(res.warnings[0].message).toEqual( + 'Description sibling to $ref matches that of the referenced schema. This is redundant and should be removed.' + ); + }); }); diff --git a/test/plugins/validation/oas3/operations.js b/test/plugins/validation/oas3/operations.js index 585f602f7..08f217d1f 100644 --- a/test/plugins/validation/oas3/operations.js +++ b/test/plugins/validation/oas3/operations.js @@ -189,4 +189,38 @@ describe('validation plugin - semantic - operations - oas3', function() { expect(res.warnings.length).toEqual(0); expect(res.errors.length).toEqual(0); }); + + it('should not crash in request body name check when path name contains a period', function() { + const spec = { + paths: { + '/other.pets': { + post: { + summary: 'this is a summary', + operationId: 'operationId', + requestBody: { + description: 'body for request', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'string' + } + } + } + } + } + } + } + } + }; + + const res = validate({ resolvedSpec: spec, jsSpec: spec }, config); + expect(res.warnings.length).toEqual(1); + expect(res.warnings[0].path).toEqual('paths./other.pets.post'); + expect(res.warnings[0].message).toEqual( + 'Operations with non-form request bodies should set a name with the x-codegen-request-body-name annotation.' + ); + expect(res.errors.length).toEqual(0); + }); });