From 3a7892ac0f8c352acae2a5f862a188c00ff9c4b2 Mon Sep 17 00:00:00 2001 From: Carmine DiMascio Date: Sun, 29 Dec 2019 11:38:32 -0500 Subject: [PATCH] add deepObject test --- .../parsers/req.parameter.mutator.ts | 13 +++++-- test/resources/serialized.objects.yaml | 36 ++++++++++++++++--- test/serialized.objects.spec.ts | 16 ++++++++- tsconfig.json | 5 +-- 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/middlewares/parsers/req.parameter.mutator.ts b/src/middlewares/parsers/req.parameter.mutator.ts index b4cac883..c5e17dfb 100644 --- a/src/middlewares/parsers/req.parameter.mutator.ts +++ b/src/middlewares/parsers/req.parameter.mutator.ts @@ -31,8 +31,8 @@ type Schema = ReferenceObject | SchemaObject; type Parameter = ReferenceObject | ParameterObject; /** - * A class top parse incoing parameters and populate a list of request fields e.g. id and field types e.g. query - * whose value must later be parsed as a JSON object, JSON Exploded Object, JSON Array, or JSON Exploded Array + * A class top parse and mutate the incoming request parameters according to the openapi spec. + * the request is mutated to accomodate various styles and types e.g. form, explode, deepObject, etc */ export class RequestParameterMutator { private _apiDocs: OpenAPIV3.Document; @@ -61,6 +61,8 @@ export class RequestParameterMutator { const { name, schema } = normalizeParameter(parameter); const { type } = schema; const { style, explode } = parameter; + const i = req.originalUrl.indexOf('?'); + const queryString = req.originalUrl.substr(i + 1); if (parameter.content) { this.handleContent(req, name, parameter); @@ -68,6 +70,8 @@ export class RequestParameterMutator { this.parseJsonAndMutateRequest(req, parameter.in, name); if (style === 'form' && explode) { this.handleFormExplode(req, name, schema, parameter); + } else if (parameter.in === 'query' && style === 'deepObject') { + this.handleDeepObject(req, queryString, name); } } else if (type === 'array' && !explode) { const delimiter = ARRAY_DELIMITER[parameter.style]; @@ -81,6 +85,11 @@ export class RequestParameterMutator { }); } + private handleDeepObject(req: Request, qs: string, name: string) { + // nothing to do + // TODO handle url encoded? + } + private handleContent( req: Request, name: string, diff --git a/test/resources/serialized.objects.yaml b/test/resources/serialized.objects.yaml index 2ddc8547..3e3cbd1f 100644 --- a/test/resources/serialized.objects.yaml +++ b/test/resources/serialized.objects.yaml @@ -1,5 +1,4 @@ - -openapi: '3.0.2' +openapi: "3.0.2" info: version: 1.0.0 title: Request Query Serialization @@ -9,6 +8,33 @@ servers: - url: /v1/ paths: + /deep_object: + get: + summary: "retrieve a deep object" + operationId: getDeepObject + parameters: + - in: query + style: deepObject + explode: true + name: settings + schema: + type: object + properties: + tag_ids: + type: array + items: + type: integer + minimum: 0 + minItems: 1 + state: + type: string + enum: ["default", "validated", "pending"] + default: "default" + description: "Filter the tags by their validity. The default value ('default') stands for no filtering." + responses: + "200": + description: the object + /tags: get: summary: "Retrieve all tags" @@ -33,7 +59,7 @@ paths: default: "default" description: "Filter the tags by their validity. The default value ('default') stands for no filtering." responses: - '200': + "200": description: "An array of tag" /serialisable: get: @@ -64,7 +90,7 @@ paths: description: Should not be serialized schema: description: Value passed to Javascript's `new Date()`. - example: '2019-06-24T12:34:56.789Z' + example: "2019-06-24T12:34:56.789Z" anyOf: - type: integer description: Unix milliseconds @@ -89,7 +115,7 @@ paths: required: - foo responses: - '200': + "200": description: parsed & validated query params content: application/json: diff --git a/test/serialized.objects.spec.ts b/test/serialized.objects.spec.ts index d36e14aa..70bdfd23 100644 --- a/test/serialized.objects.spec.ts +++ b/test/serialized.objects.spec.ts @@ -17,7 +17,8 @@ describe(packageJson.name, () => { express .Router() .get(`/serialisable`, (req, res) => res.json(req.query)) - .get(`/tags`, (req, res) => res.json(req.query)), + .get(`/tags`, (req, res) => res.json(req.query)) + .get(`/deep_object`, (req, res) => res.json(req.query)), ), ); }); @@ -104,4 +105,17 @@ describe(packageJson.name, () => { .to.have.property('tag_ids') .that.deep.equals([1]); })); + + it('should explode deepObject query params', async () => + request(app) + .get(`${app.basePath}/deep_object?settings[state]=validated`) + .expect(200) + .then(r => { + const expected = { + settings: { + state: 'validated', + }, + }; + expect(r.body).to.deep.equals(expected); + })); }); diff --git a/tsconfig.json b/tsconfig.json index 0c529e7a..7b9278ab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,10 +9,11 @@ "resolveJsonModule": true, "typeRoots": ["./node_modules/@types", "./typings"] }, - "exclude": ["node_modules"], + "exclude": ["node_modules", "a_reference"], "include": [ "typings/**/*.d.ts", "src/**/*.ts", - "src/framework/modded.express.mung.ts" + "src/framework/modded.express.mung.ts", + "a_reference/query.parser.ts" ] }