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; }