From 9f786d90ffa4bc0a76fa2a80eb63bcba64ae4057 Mon Sep 17 00:00:00 2001 From: Carmine DiMascio Date: Sat, 7 Sep 2019 23:53:40 -0400 Subject: [PATCH] add option to disable type coercion --- src/index.ts | 5 ++- test/nullable.spec.ts | 63 ++++++++++++++++++++++++++++-------- test/resources/nullable.yaml | 1 + 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/index.ts b/src/index.ts index af965e8a..63f81112 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,11 +8,13 @@ import { OpenAPIV3, OpenApiRequest } from './framework/types'; export interface OpenApiValidatorOpts { apiSpecPath?: string; apiSpec?: OpenAPIV3.Document | string; + coerceTypes?: boolean; multerOpts?: {}; } export class OpenApiValidator { private context: OpenApiContext; + private coerceTypes: boolean; private multerOpts: {}; constructor(options: OpenApiValidatorOpts) { @@ -21,6 +23,7 @@ export class OpenApiValidator { if (options.apiSpecPath && options.apiSpec) throw ono('apiSpecPath or apiSpec required. not both.'); + this.coerceTypes = options.coerceTypes == null ? true : options.coerceTypes; this.multerOpts = options.multerOpts; const openApiContext = new OpenApiContext({ @@ -51,7 +54,7 @@ export class OpenApiValidator { const aoav = new middlewares.RequestValidator(this.context.apiDoc, { nullable: true, - coerceTypes: true, + coerceTypes: this.coerceTypes, removeAdditional: false, useDefaults: true, }); diff --git a/test/nullable.spec.ts b/test/nullable.spec.ts index df5bf5e9..3ff36ce4 100644 --- a/test/nullable.spec.ts +++ b/test/nullable.spec.ts @@ -13,14 +13,12 @@ describe(packageJson.name, () => { before(async () => { // Set up the express app const apiSpec = path.join('test', 'resources', 'nullable.yaml'); - app = await createApp({ apiSpec }, 3005); + app = await createApp({ apiSpec, coerceTypes: false }, 3005); basePath = app.basePath; app.use( `${basePath}`, - express - .Router() - .post(`/pets/nullable`, (req, res) => res.json(req.body)), + express.Router().post(`/pets/nullable`, (req, res) => res.json(req.body)), ); }); @@ -39,14 +37,51 @@ describe(packageJson.name, () => { expect(r.body.name).to.be.null; })); - it('should fill null with default (name: nullable false/default)', async () => - request(app) - .post(`${basePath}/pets`) - .send({ - name: null, - }) - .expect(200) - .then(r => { - expect(r.body.name).to.equal(''); - })); + it('should not fill an explicity null with default when coerceTypes is false', async () => + request(app) + .post(`${basePath}/pets`) + .send({ + name: null, + }) + .expect(400)); + + it('should fill unspecified field with default when coerceTypes is false', async () => + request(app) + .post(`${basePath}/pets`) + .send({ + name: 'name', + }) + .expect(200) + .then(r => { + expect(r.body.tag).to.equal('my default value'); + })); + + it('should fail if required and not provided (nullable true)', async () => + request(app) + .post(`${basePath}/pets/nullable`) + .send({}) + .expect(400) + .then(r => { + expect(r.body.errors[0].path).to.equal('.body.name'); + })); + + it('should fail if required and not provided (nullable false', async () => + request(app) + .post(`${basePath}/pets`) + .send({}) + .expect(400) + .then(r => { + expect(r.body.errors[0].path).to.equal('.body.name'); + })); + + it('should fail if required and provided as null when nullable is false', async () => + request(app) + .post(`${basePath}/pets`) + .send({ + name: null, + }) + .expect(400) + .then(r => { + expect(r.body.errors[0].path).to.equal('.body.name'); + })); }); diff --git a/test/resources/nullable.yaml b/test/resources/nullable.yaml index 8d6139c0..11eceb51 100644 --- a/test/resources/nullable.yaml +++ b/test/resources/nullable.yaml @@ -100,6 +100,7 @@ components: type: string tag: type: string + default: my default value Pet: