From 20785fe256590c4c33f290e90483cb7d5a5db934 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 6 Dec 2018 17:01:33 -0800 Subject: [PATCH] `default` response is only applied for error status codes. (#64) * `default` response is only applied for error status codes. * 1.4.00 --- lib/types/operation.js | 21 ++++++++++--------- package.json | 2 +- test/test-operation.js | 46 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/lib/types/operation.js b/lib/types/operation.js index 91ac760..1fd6ac4 100644 --- a/lib/types/operation.js +++ b/lib/types/operation.js @@ -190,9 +190,10 @@ Operation.prototype.getResponse = function (statusCode) { statusCode = statusCode.toString(); } - return _.find(this.getResponses(), function (responseObject) { - return responseObject.statusCode === statusCode; - }); + return _.find( + this.getResponses(), + responseObject => responseObject.statusCode === statusCode + ); }; /** @@ -244,8 +245,8 @@ Operation.prototype.validateRequest = function (req) { warnings: [] }; - // Validate the Content-Type if there is a set of expected consumes. Also we will validate only if there - // is a content-type set in the request headers as many times it happens that it is not set at all and + // Validate the Content-Type if there is a set of expected consumes. Also we will validate only if there + // is a content-type set in the request headers as many times it happens that it is not set at all and // the service works fine. Going by the RFC www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1 mentioned above we would need to assume 'application/octet-stream' // which in most cases would not be true so it would produce a lot of noise without adding much value. if (this.consumes.length > 0 && helpers.getHeaderValue(req.headers, 'content-type')) { @@ -299,21 +300,21 @@ Operation.prototype.validateResponse = function (res) { var response = this.getResponse(realStatusCode); if (_.isUndefined(response)) { + const realCode = Number(realStatusCode) + // If there is no response for the requested status, use the default if there is one (This is Swagger's approach) - response = this.getResponse('default'); + response = (400 <= realCode && realCode <= 599) ? this.getResponse('default') : undefined; if (_.isUndefined(response)) { results.errors.push({ code: 'INVALID_RESPONSE_CODE', - message: 'This operation does not have a defined \'' + (realStatusCode === 'default' ? - realStatusCode : - realStatusCode + '\' or \'default') + '\' response code', + message: 'This operation does not have a defined \'' + realStatusCode + '\' response code', path: [] }); return results; } } - + results = response.validateResponse(res); return results; }; diff --git a/package.json b/package.json index ad9052a..de9bcc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yasway", - "version": "1.3.3", + "version": "1.4.0", "description": "A library that simplifies Swagger integrations.", "main": "index.js", "types": "index.d.ts", diff --git a/test/test-operation.js b/test/test-operation.js index f3360ae..8ab58ba 100644 --- a/test/test-operation.js +++ b/test/test-operation.js @@ -230,13 +230,13 @@ describe('Operation', function () { }; describe('operation level consumes - ignore when empty', function () { - var operation; + var operation; before(function () { // this path+op doesn't specify 'consumes' operation = swaggerApiRelativeRefs.getOperation('/pet/findByStatus', 'get'); }); - + it.skip('should not return an unsupported content-type error', function () { var request = { url: '/pet/findByStatus', @@ -487,19 +487,34 @@ describe('Operation', function () { assert.deepEqual(results.errors, [ { code: 'INVALID_RESPONSE_CODE', - message: 'This operation does not have a defined \'201\' or \'default\' response code', + message: 'This operation does not have a defined \'201\' response code', path: [] } ]); }); }); - it('should return the \'default\' response when validating an undefined response', function () { + it('should return the \'default\' response when validating an undefined response from [400..600) range', function () { + var results = swaggerApiRelativeRefs.getOperation('/user', 'post').validateResponse({ + statusCode: 599 + }); + + assert.deepEqual(results.errors, []); + assert.deepEqual(results.warnings, []); + }); + + it('should return an error for an undefined non-error response, even if `default` is present', function () { var results = swaggerApiRelativeRefs.getOperation('/user', 'post').validateResponse({ statusCode: 201 }); - assert.deepEqual(results.errors, []); + assert.deepEqual(results.errors, [ + { + code: 'INVALID_RESPONSE_CODE', + message: 'This operation does not have a defined \'201\' response code', + path: [] + } + ]); assert.deepEqual(results.warnings, []); }); }); @@ -926,21 +941,36 @@ describe('Operation', function () { assert.deepEqual(results.errors, [ { code: 'INVALID_RESPONSE_CODE', - message: 'This operation does not have a defined \'201\' or \'default\' response code', + message: 'This operation does not have a defined \'201\' response code', path: [] } ]); }); }); - it('should return the \'default\' response when validating an undefined response', function () { + it('should return the \'default\' response when validating an undefined response from 400-500 range', function () { var results = swaggerApi.getOperation('/user', 'post').validateResponse({ - statusCode: 201 + statusCode: 404 }); assert.deepEqual(results.errors, []); assert.deepEqual(results.warnings, []); }); + + it('should return an error for an undefined non-error response, even if `default` is present', function () { + var results = swaggerApi.getOperation('/user', 'post').validateResponse({ + statusCode: 201 + }); + + assert.deepEqual(results.errors, [ + { + code: 'INVALID_RESPONSE_CODE', + message: 'This operation does not have a defined \'201\' response code', + path: [] + } + ]); + assert.deepEqual(results.warnings, []); + }); }); }); });