From 54d4687101818dede788a131ec3ab9dd65f4788c Mon Sep 17 00:00:00 2001 From: Adam Walker Date: Wed, 2 Mar 2022 15:55:46 -0500 Subject: [PATCH 1/2] Add handling for default response keyword - Minor change to use `default` if specific status code is not found is not found in responses - Updated tests and error messages - Incremented port number of exampleApp to 5001 to avoid UPNP conflicts --- .github/ISSUE_TEMPLATE/bug_report.md | 6 +---- .github/ISSUE_TEMPLATE/feature_request.md | 6 ----- commonTestResources/exampleApp.ts | 2 +- .../exampleOpenApiFiles/valid/openapi2.json | 10 +++++++ .../exampleOpenApiFiles/valid/openapi3.yml | 5 ++++ .../lib/assertions/satisfyApiSpec.ts | 2 +- .../noResponseComponents.test.ts | 2 +- .../satisfyApiSpec/satisfyApiSpec.test.ts | 26 ++++++++++++++++++- .../noResponseComponents.test.ts | 2 +- .../toSatisfyApiSpec/toSatisfyApiSpec.test.ts | 26 ++++++++++++++++++- .../src/matchers/toSatisfyApiSpec.ts | 2 +- .../lib/classes/AbstractOpenApiSpec.ts | 4 ++- 12 files changed, 74 insertions(+), 19 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 6a9ebb1..c551f08 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -4,19 +4,16 @@ about: Report a reproducible bug title: '' labels: bug assignees: '' - --- **Are you using jest or chai**? - **Are you using OpenAPI 2, 3.0.X, or 3.1.0?** - **Describe the bug clearly** - **Steps to reproduce the bug:** + 1. ... 2. ... 3. See error (please paste error output or a screenshot) @@ -25,5 +22,4 @@ assignees: '' **What did you expect to happen instead?** - **Are you going to resolve the issue?** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index cdd1c1a..e63410d 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -4,22 +4,16 @@ about: Suggest an idea for this project title: '' labels: enhancement assignees: '' - --- **Are you using OpenAPI 2, 3.0.X, or 3.1.0?** - **Would this solve a problem or make something easier?** - **What would you like to happen?** - **Describe alternatives you've considered** - **Additional context or screenshots** - **Are you going to resolve the issue?** diff --git a/commonTestResources/exampleApp.ts b/commonTestResources/exampleApp.ts index 684459b..06f96b9 100644 --- a/commonTestResources/exampleApp.ts +++ b/commonTestResources/exampleApp.ts @@ -28,4 +28,4 @@ app.get('/no/content-type/header/and/no/response/body', (_req, res) => export default app; -export const port = 5000; +export const port = 5001; diff --git a/commonTestResources/exampleOpenApiFiles/valid/openapi2.json b/commonTestResources/exampleOpenApiFiles/valid/openapi2.json index b618f45..29b8ca7 100644 --- a/commonTestResources/exampleOpenApiFiles/valid/openapi2.json +++ b/commonTestResources/exampleOpenApiFiles/valid/openapi2.json @@ -268,6 +268,16 @@ } } }, + "/responseStatus/default": { + "get": { + "parameters": [], + "responses": { + "default": { + "description": "No response body" + } + } + } + }, "/responseReferencesResponseDefinitionObject": { "get": { "produces": ["application/json"], diff --git a/commonTestResources/exampleOpenApiFiles/valid/openapi3.yml b/commonTestResources/exampleOpenApiFiles/valid/openapi3.yml index 803c2e0..83962a6 100644 --- a/commonTestResources/exampleOpenApiFiles/valid/openapi3.yml +++ b/commonTestResources/exampleOpenApiFiles/valid/openapi3.yml @@ -162,6 +162,11 @@ paths: description: No response body 204: description: No response body + /responseStatus/default: + get: + responses: + default: + description: No response body /HTTPMethod: get: responses: diff --git a/packages/chai-openapi-response-validator/lib/assertions/satisfyApiSpec.ts b/packages/chai-openapi-response-validator/lib/assertions/satisfyApiSpec.ts index c4b8819..3af5b44 100644 --- a/packages/chai-openapi-response-validator/lib/assertions/satisfyApiSpec.ts +++ b/packages/chai-openapi-response-validator/lib/assertions/satisfyApiSpec.ts @@ -127,7 +127,7 @@ function getExpectedResToSatisfyApiSpecMsg( return joinWithNewLines( hint, `expected res to satisfy a '${status}' response defined for endpoint '${endpoint}' in your API spec`, - `res had status '${status}', but your API spec has no '${status}' response defined for endpoint '${endpoint}'`, + `res had status '${status}', but your API spec has no '${status}' or 'default' response defined for endpoint '${endpoint}'`, `Response statuses found for endpoint '${endpoint}' in API spec: ${expectedResponseStatuses}`, ); } diff --git a/packages/chai-openapi-response-validator/test/assertions/satisfyApiSpec/noResponseComponents.test.ts b/packages/chai-openapi-response-validator/test/assertions/satisfyApiSpec/noResponseComponents.test.ts index 539f155..111d1b3 100644 --- a/packages/chai-openapi-response-validator/test/assertions/satisfyApiSpec/noResponseComponents.test.ts +++ b/packages/chai-openapi-response-validator/test/assertions/satisfyApiSpec/noResponseComponents.test.ts @@ -41,7 +41,7 @@ openApiSpecs.forEach((spec) => { expect(assertion).to.throw( joinWithNewLines( "expected res to satisfy a '204' response defined for endpoint 'GET /endpointPath' in your API spec", - "res had status '204', but your API spec has no '204' response defined for endpoint 'GET /endpointPath'", + "res had status '204', but your API spec has no '204' or 'default' response defined for endpoint 'GET /endpointPath'", ), ); }); diff --git a/packages/chai-openapi-response-validator/test/assertions/satisfyApiSpec/satisfyApiSpec.test.ts b/packages/chai-openapi-response-validator/test/assertions/satisfyApiSpec/satisfyApiSpec.test.ts index 1d9fd9d..cf5346b 100644 --- a/packages/chai-openapi-response-validator/test/assertions/satisfyApiSpec/satisfyApiSpec.test.ts +++ b/packages/chai-openapi-response-validator/test/assertions/satisfyApiSpec/satisfyApiSpec.test.ts @@ -455,7 +455,7 @@ openApiSpecs.forEach((spec) => { joinWithNewLines( 'expected res to satisfy API spec', "expected res to satisfy a '418' response defined for endpoint 'GET /responseStatus' in your API spec", - "res had status '418', but your API spec has no '418' response defined for endpoint 'GET /responseStatus'", + "res had status '418', but your API spec has no '418' or 'default' response defined for endpoint 'GET /responseStatus'", "Response statuses found for endpoint 'GET /responseStatus' in API spec: 200, 204", ), ); @@ -466,6 +466,30 @@ openApiSpecs.forEach((spec) => { }); }); + describe('res.status caught by default response', () => { + const res = { + status: 418, + req: { + method: 'GET', + path: '/responseStatus/default', + }, + }; + it('passes', () => { + expect(res).to.satisfyApiSpec; + }); + it('fails when using .not', () => { + const assertion = () => expect(res).to.not.satisfyApiSpec; + expect(assertion).to.throw( + joinWithNewLines( + 'expected res not to satisfy API spec', + "expected res not to satisfy the '418' response defined for endpoint 'GET /responseStatus/default' in your API spec", + 'res contained: { body: undefined }', + "The '418' response defined for endpoint 'GET /responseStatus/default' in API spec: { '418': { description: 'No response body' } }", + ), + ); + }); + }); + describe('wrong res.body (multiple errors)', () => { const res = { status: 200, diff --git a/packages/jest-openapi/__test__/matchers/toSatisfyApiSpec/noResponseComponents.test.ts b/packages/jest-openapi/__test__/matchers/toSatisfyApiSpec/noResponseComponents.test.ts index 5785931..ff96a88 100644 --- a/packages/jest-openapi/__test__/matchers/toSatisfyApiSpec/noResponseComponents.test.ts +++ b/packages/jest-openapi/__test__/matchers/toSatisfyApiSpec/noResponseComponents.test.ts @@ -40,7 +40,7 @@ openApiSpecs.forEach((spec) => { // prettier-ignore joinWithNewLines( `expected ${red('received')} to satisfy a '204' response defined for endpoint 'GET /endpointPath' in your API spec`, - `${red('received')} had status ${red('204')}, but your API spec has no ${red('204')} response defined for endpoint 'GET /endpointPath'`, + `${red('received')} had status ${red('204')}, but your API spec has no ${red('204')} or 'default' response defined for endpoint 'GET /endpointPath'`, ), ); }); diff --git a/packages/jest-openapi/__test__/matchers/toSatisfyApiSpec/toSatisfyApiSpec.test.ts b/packages/jest-openapi/__test__/matchers/toSatisfyApiSpec/toSatisfyApiSpec.test.ts index 25e073e..888e1e1 100644 --- a/packages/jest-openapi/__test__/matchers/toSatisfyApiSpec/toSatisfyApiSpec.test.ts +++ b/packages/jest-openapi/__test__/matchers/toSatisfyApiSpec/toSatisfyApiSpec.test.ts @@ -497,7 +497,7 @@ openApiSpecs.forEach((spec) => { joinWithNewLines( expectReceivedToSatisfyApiSpec, `expected ${red('received')} to satisfy a '418' response defined for endpoint 'GET /responseStatus' in your API spec`, - `${red('received')} had status ${red('418')}, but your API spec has no ${red('418')} response defined for endpoint 'GET /responseStatus'`, + `${red('received')} had status ${red('418')}, but your API spec has no ${red('418')} or 'default' response defined for endpoint 'GET /responseStatus'`, `Response statuses found for endpoint 'GET /responseStatus' in API spec: ${green('200, 204')}`, ), ); @@ -508,6 +508,30 @@ openApiSpecs.forEach((spec) => { }); }); + describe('res.status caught by default response', () => { + const res = { + status: 418, + req: { + method: 'GET', + path: '/responseStatus/default', + }, + }; + it('passes', () => { + expect(res).toSatisfyApiSpec(); + }); + it('fails when using .not', () => { + const assertion = () => expect(res).not.toSatisfyApiSpec(); + // prettier-ignore + expect(assertion).toThrow( + joinWithNewLines( + expectReceivedNotToSatisfyApiSpec, + `expected ${red('received')} not to satisfy the '418' response defined for endpoint 'GET /responseStatus/default' in your API spec`, + `${red('received')} contained: ${red(`{ body: undefined }`)}`, + `The '418' response defined for endpoint 'GET /responseStatus/default' in API spec: ${green(`{ '418': { description: 'No response body' } }`)}`, + )) + }); + }); + describe('wrong res.body (multiple errors)', () => { const res = { status: 200, diff --git a/packages/jest-openapi/src/matchers/toSatisfyApiSpec.ts b/packages/jest-openapi/src/matchers/toSatisfyApiSpec.ts index edc5949..21b4d10 100644 --- a/packages/jest-openapi/src/matchers/toSatisfyApiSpec.ts +++ b/packages/jest-openapi/src/matchers/toSatisfyApiSpec.ts @@ -150,7 +150,7 @@ function getExpectReceivedToSatisfyApiSpecMsg( return joinWithNewLines( hint, `expected ${RECEIVED_COLOR('received')} to satisfy a '${status}' response defined for endpoint '${endpoint}' in your API spec`, - `${RECEIVED_COLOR('received')} had status ${RECEIVED_COLOR(status)}, but your API spec has no ${RECEIVED_COLOR(status)} response defined for endpoint '${endpoint}'`, + `${RECEIVED_COLOR('received')} had status ${RECEIVED_COLOR(status)}, but your API spec has no ${RECEIVED_COLOR(status)} or 'default' response defined for endpoint '${endpoint}'`, `Response statuses found for endpoint '${endpoint}' in API spec: ${EXPECTED_COLOR(expectedResponseStatuses)}`, ); } diff --git a/packages/openapi-validator/lib/classes/AbstractOpenApiSpec.ts b/packages/openapi-validator/lib/classes/AbstractOpenApiSpec.ts index 57b5c32..3d3f55e 100644 --- a/packages/openapi-validator/lib/classes/AbstractOpenApiSpec.ts +++ b/packages/openapi-validator/lib/classes/AbstractOpenApiSpec.ts @@ -71,7 +71,9 @@ export default abstract class OpenApiSpec { responseOperation: Operation, status: ActualResponse['status'], ): ResponseObjectWithSchema | undefined { - const response = responseOperation.responses[status]; + const response = + responseOperation.responses[status] || + responseOperation.responses.default; if (!response) { return undefined; } From bc981af8fabc06287f2569dfafab6bf146a3d0c8 Mon Sep 17 00:00:00 2001 From: Adam Walker Date: Thu, 3 Mar 2022 09:24:39 -0500 Subject: [PATCH 2/2] Revert markdown file changes --- .github/ISSUE_TEMPLATE/bug_report.md | 6 +++++- .github/ISSUE_TEMPLATE/feature_request.md | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c551f08..6a9ebb1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -4,16 +4,19 @@ about: Report a reproducible bug title: '' labels: bug assignees: '' + --- **Are you using jest or chai**? + **Are you using OpenAPI 2, 3.0.X, or 3.1.0?** + **Describe the bug clearly** -**Steps to reproduce the bug:** +**Steps to reproduce the bug:** 1. ... 2. ... 3. See error (please paste error output or a screenshot) @@ -22,4 +25,5 @@ assignees: '' **What did you expect to happen instead?** + **Are you going to resolve the issue?** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index e63410d..cdd1c1a 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -4,16 +4,22 @@ about: Suggest an idea for this project title: '' labels: enhancement assignees: '' + --- **Are you using OpenAPI 2, 3.0.X, or 3.1.0?** + **Would this solve a problem or make something easier?** + **What would you like to happen?** + **Describe alternatives you've considered** + **Additional context or screenshots** + **Are you going to resolve the issue?**