diff --git a/CHANGE_HISTORY.md b/CHANGE_HISTORY.md index 88c1df1f..c82764b5 100644 --- a/CHANGE_HISTORY.md +++ b/CHANGE_HISTORY.md @@ -1,3 +1,14 @@ +## 4.2.1 (2020-10-14) + +* add readonly required test using allOf ([cbd6292](https://github.com/cdimascio/express-openapi-validator/commit/cbd6292)) +* increment patch version ([2231fde](https://github.com/cdimascio/express-openapi-validator/commit/2231fde)) +* update change history ([cae389c](https://github.com/cdimascio/express-openapi-validator/commit/cae389c)) +* Update README.md ([8e9678d](https://github.com/cdimascio/express-openapi-validator/commit/8e9678d)) +* docs: add ownagedj as a contributor (#399) ([1a8779f](https://github.com/cdimascio/express-openapi-validator/commit/1a8779f)), closes [#399](https://github.com/cdimascio/express-openapi-validator/issues/399) +* fix: optional requestBody handling / add tests (#398) ([5b3d32a](https://github.com/cdimascio/express-openapi-validator/commit/5b3d32a)), closes [#398](https://github.com/cdimascio/express-openapi-validator/issues/398) + + + ## 4.2.0 (2020-10-08) * Create dependabot.yml ([b57116c](https://github.com/cdimascio/express-openapi-validator/commit/b57116c)) diff --git a/src/middlewares/parsers/body.parse.ts b/src/middlewares/parsers/body.parse.ts index bd327efb..d5e7831e 100644 --- a/src/middlewares/parsers/body.parse.ts +++ b/src/middlewares/parsers/body.parse.ts @@ -68,17 +68,12 @@ export class BodySchemaParser { } if (!content) { - if (contentType.contentType !== undefined) { - const msg = - contentType.contentType === 'not_provided' - ? 'media type not specified' - : `unsupported media type ${contentType.contentType}`; - throw new UnsupportedMediaType({ path: path, message: msg }); - } else { - content = {}; - } + const msg = + contentType.contentType === 'not_provided' + ? 'media type not specified' + : `unsupported media type ${contentType.contentType}`; + throw new UnsupportedMediaType({ path: path, message: msg }); } - const schema = this.cleanseContentSchema(content); return schema ?? content.schema ?? {}; @@ -86,9 +81,7 @@ export class BodySchemaParser { return {}; } - private cleanseContentSchema( - content: OpenAPIV3.MediaTypeObject - ): BodySchema { + private cleanseContentSchema(content: OpenAPIV3.MediaTypeObject): BodySchema { let contentRefSchema = null; if (content.schema && '$ref' in content.schema) { const resolved = this.ajv.getSchema(content.schema.$ref); diff --git a/test/optional-request-body.spec.ts b/test/optional-request-body.spec.ts index e53f3202..9a0d2d58 100644 --- a/test/optional-request-body.spec.ts +++ b/test/optional-request-body.spec.ts @@ -15,7 +15,7 @@ describe(packageJson.name, () => { express.Router().post(`/documents`, (req, res) => res.status(201).json({ id: 123, - name: req.body ? req.body.name : '' + name: req.body ? req.body.name : '', }), ), ), @@ -29,6 +29,7 @@ describe(packageJson.name, () => { it('create document should return 201', async () => request(app) .post(`/documents`) + .set('Content-Type', 'application/json') .expect(201)); it('return 415', async () => diff --git a/test/request.bodies.ref.spec.ts b/test/request.bodies.ref.spec.ts index 9e9d7367..cfea33ba 100644 --- a/test/request.bodies.ref.spec.ts +++ b/test/request.bodies.ref.spec.ts @@ -17,19 +17,24 @@ describe(packageJson.name, () => { unknownFormats: ['phone-number'], }, 3005, - app => { + (app) => { // Define new coercion routes - app.post(`${app.basePath}/request_bodies_ref`, (req, res) => { - if (req.query.bad_body) { - const r = req.body; - r.unexpected_prop = 'bad'; - res.json(r); - } else if (req.header('accept')) { - res.type(req.header('accept')).send(req.body); - } else { - res.json(req.body); - } - }); + app + .post(`${app.basePath}/415_test`, (req, res) => ({ + success: true, + ...req, + })) + .post(`${app.basePath}/request_bodies_ref`, (req, res) => { + if (req.query.bad_body) { + const r = req.body; + r.unexpected_prop = 'bad'; + res.json(r); + } else if (req.header('accept')) { + res.type(req.header('accept')).send(req.body); + } else { + res.json(req.body); + } + }); }, true, ); @@ -39,6 +44,15 @@ describe(packageJson.name, () => { app.server.close(); }); + it('should return 415 for undeclared media type', async () => + request(app) + .post(`${app.basePath}/415_test`) + .set('accept', 'text/plain') + .expect(415) + .then((r) => { + expect(r.body.message).includes('unsupported media type'); + })); + it('should return 200 if text/plain request body is satisfied', async () => { const stringData = 'my string data'; return request(app) @@ -47,7 +61,7 @@ describe(packageJson.name, () => { .set('accept', 'text/plain') .send(stringData) .expect(200) - .then(r => { + .then((r) => { expect(r.text).equals(stringData); }); }); @@ -60,8 +74,8 @@ describe(packageJson.name, () => { .set('accept', 'text/html') .send(stringData) .expect(200) - .then(r => { - expect(r.get('content-type')).to.contain('text/html') + .then((r) => { + expect(r.get('content-type')).to.contain('text/html'); expect(r.text).equals(stringData); }); }); @@ -75,9 +89,9 @@ describe(packageJson.name, () => { testProperty: 'abc', }) .expect(200) - .then(r => { + .then((r) => { const { body } = r; - expect(r.get('content-type')).to.contain('application/ld+json') + expect(r.get('content-type')).to.contain('application/ld+json'); expect(body).to.have.property('testProperty'); }); }); @@ -91,10 +105,10 @@ describe(packageJson.name, () => { testPropertyTwo: 'abc', }) .expect(200) - .then(r => { + .then((r) => { const { body } = r; - expect(r.get('content-type')).to.contain('application/vnd.api+json') - expect(r.get('content-type')).to.contain(' type=two') + expect(r.get('content-type')).to.contain('application/vnd.api+json'); + expect(r.get('content-type')).to.contain(' type=two'); expect(body).to.have.property('testPropertyTwo'); }); }); @@ -104,7 +118,7 @@ describe(packageJson.name, () => { .post(`${app.basePath}/request_bodies_ref`) .send({}) .expect(400) - .then(r => { + .then((r) => { expect(r.body.errors).to.be.an('array'); expect(r.body.errors).to.have.length(1); const message = r.body.errors[0].message; @@ -120,7 +134,7 @@ describe(packageJson.name, () => { testProperty: 'abc', }) .expect(200) - .then(r => { + .then((r) => { const { body } = r; expect(body).to.have.property('testProperty'); })); @@ -134,9 +148,9 @@ describe(packageJson.name, () => { testProperty: 'abc', }) .expect(200) - .then(r => { + .then((r) => { const { body } = r; - expect(r.get('content-type')).to.contain('application/hal+json') + expect(r.get('content-type')).to.contain('application/hal+json'); expect(body).to.have.property('testProperty'); })); @@ -150,7 +164,7 @@ describe(packageJson.name, () => { testProperty: 'abc', }) .expect(500) - .then(r => { + .then((r) => { const { body } = r; expect(body.message).to.include( '.response should NOT have additional properties', @@ -169,11 +183,9 @@ describe(packageJson.name, () => { invalidProperty2: 'abc', }) .expect(400) - .then(r => { + .then((r) => { const errors = r.body.errors; - expect(errors) - .to.be.an('array') - .with.length(2); + expect(errors).to.be.an('array').with.length(2); expect(errors[0].path).to.equal('.body.invalidProperty'); expect(errors[0].message).to.equal( 'should NOT have additional properties', diff --git a/test/resources/request.bodies.ref.yaml b/test/resources/request.bodies.ref.yaml index 8f4b3cd1..9872fb11 100644 --- a/test/resources/request.bodies.ref.yaml +++ b/test/resources/request.bodies.ref.yaml @@ -8,6 +8,20 @@ servers: - url: /v1/ paths: + /415_test: + post: + requestBody: + content: + application/json: + schema: + properties: + id: + type: string + + responses: + '200': + description: OK + /request_bodies_ref: post: parameters: