From ab990d7a4056cb9a880d829fcea34b7ef1ecffab Mon Sep 17 00:00:00 2001 From: Matthias Ramsauer Date: Fri, 22 Nov 2019 18:36:33 +0100 Subject: [PATCH] [Feature] [SwaggerV2] Body Parameter affect content-type header and implement formData type (#1722) * Body Parameter affect content-type header and implement formData type * Enable Tests and update swagger2 fixtures --- .../src/__tests__/fixtures.test.js | 1 + .../swagger2/dereferenced-output.json | 60 +++++++++++++-- .../dereferenced-with-tags-output.json | 60 +++++++++++++-- .../fixtures/swagger2/petstore-output.json | 60 +++++++++++++-- .../swagger2/petstore-with-tags-output.json | 60 +++++++++++++-- .../fixtures/swagger2/petstore-yml-input.yml | 42 ++++++++-- .../swagger2/petstore-yml-output.json | 46 +++++++++-- .../petstore-yml-with-tags-output.json | 12 +-- .../src/importers/swagger2.js | 77 +++++++++++++++---- 9 files changed, 358 insertions(+), 60 deletions(-) diff --git a/packages/insomnia-importers/src/__tests__/fixtures.test.js b/packages/insomnia-importers/src/__tests__/fixtures.test.js index e22b527ed..1899c8fd4 100755 --- a/packages/insomnia-importers/src/__tests__/fixtures.test.js +++ b/packages/insomnia-importers/src/__tests__/fixtures.test.js @@ -21,6 +21,7 @@ describe('Fixtures', () => { } it(`Import ${name} ${input}`, async () => { + expect.assertions(5); expect(typeof input).toBe('string'); expect(typeof output).toBe('string'); diff --git a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/dereferenced-output.json b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/dereferenced-output.json index 9f8b52504..012d13792 100644 --- a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/dereferenced-output.json +++ b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/dereferenced-output.json @@ -41,7 +41,13 @@ }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/json" + } + ], "authentication": {}, "_type": "request", "_id": "addPet" @@ -56,7 +62,13 @@ }, "method": "PUT", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/json" + } + ], "authentication": {}, "_type": "request", "_id": "updatePet" @@ -114,11 +126,29 @@ "name": "Updates a pet in the store with form data", "url": "{{ base_url }}/pet/{{ petId }}", "body": { - "mimeType": "application/x-www-form-urlencoded" + "mimeType": "application/x-www-form-urlencoded", + "params": [ + { + "disabled": true, + "name": "name", + "value": "string" + }, + { + "disabled": true, + "name": "status", + "value": "string" + } + ] }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/x-www-form-urlencoded" + } + ], "authentication": {}, "_type": "request", "_id": "updatePetWithForm" @@ -146,11 +176,29 @@ "name": "uploads an image", "url": "{{ base_url }}/pet/{{ petId }}/uploadImage", "body": { - "mimeType": "multipart/form-data" + "mimeType": "multipart/form-data", + "params": [ + { + "disabled": true, + "name": "additionalMetadata", + "value": "string" + }, + { + "disabled": true, + "name": "file", + "type": "file" + } + ] }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "multipart/form-data" + } + ], "authentication": {}, "_type": "request", "_id": "uploadFile" diff --git a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/dereferenced-with-tags-output.json b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/dereferenced-with-tags-output.json index 6ca90ca29..72d46b4f7 100644 --- a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/dereferenced-with-tags-output.json +++ b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/dereferenced-with-tags-output.json @@ -65,7 +65,13 @@ }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/json" + } + ], "authentication": {}, "_type": "request", "_id": "addPet" @@ -80,7 +86,13 @@ }, "method": "PUT", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/json" + } + ], "authentication": {}, "_type": "request", "_id": "updatePet" @@ -138,11 +150,29 @@ "name": "Updates a pet in the store with form data", "url": "{{ base_url }}/pet/{{ petId }}", "body": { - "mimeType": "application/x-www-form-urlencoded" + "mimeType": "application/x-www-form-urlencoded", + "params": [ + { + "disabled": true, + "name": "name", + "value": "string" + }, + { + "disabled": true, + "name": "status", + "value": "string" + } + ] }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/x-www-form-urlencoded" + } + ], "authentication": {}, "_type": "request", "_id": "updatePetWithForm" @@ -170,11 +200,29 @@ "name": "uploads an image", "url": "{{ base_url }}/pet/{{ petId }}/uploadImage", "body": { - "mimeType": "multipart/form-data" + "mimeType": "multipart/form-data", + "params": [ + { + "disabled": true, + "name": "additionalMetadata", + "value": "string" + }, + { + "disabled": true, + "name": "file", + "type": "file" + } + ] }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "multipart/form-data" + } + ], "authentication": {}, "_type": "request", "_id": "uploadFile" diff --git a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-output.json b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-output.json index 78bda2597..98c357bde 100644 --- a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-output.json +++ b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-output.json @@ -41,7 +41,13 @@ }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/json" + } + ], "authentication": {}, "_type": "request", "_id": "addPet" @@ -56,7 +62,13 @@ }, "method": "PUT", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/json" + } + ], "authentication": {}, "_type": "request", "_id": "updatePet" @@ -114,11 +126,29 @@ "name": "Updates a pet in the store with form data", "url": "{{ base_url }}/pet/{{ petId }}", "body": { - "mimeType": "application/x-www-form-urlencoded" + "mimeType": "application/x-www-form-urlencoded", + "params": [ + { + "disabled": true, + "name": "name", + "value": "string" + }, + { + "disabled": true, + "name": "status", + "value": "string" + } + ] }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/x-www-form-urlencoded" + } + ], "authentication": {}, "_type": "request", "_id": "updatePetWithForm" @@ -146,11 +176,29 @@ "name": "uploads an image", "url": "{{ base_url }}/pet/{{ petId }}/uploadImage", "body": { - "mimeType": "multipart/form-data" + "mimeType": "multipart/form-data", + "params": [ + { + "disabled": true, + "name": "additionalMetadata", + "value": "string" + }, + { + "disabled": true, + "name": "file", + "type": "file" + } + ] }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "multipart/form-data" + } + ], "authentication": {}, "_type": "request", "_id": "uploadFile" diff --git a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-with-tags-output.json b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-with-tags-output.json index c74e598e8..d916b2513 100644 --- a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-with-tags-output.json +++ b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-with-tags-output.json @@ -65,7 +65,13 @@ }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/json" + } + ], "authentication": {}, "_type": "request", "_id": "addPet" @@ -80,7 +86,13 @@ }, "method": "PUT", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/json" + } + ], "authentication": {}, "_type": "request", "_id": "updatePet" @@ -138,11 +150,29 @@ "name": "Updates a pet in the store with form data", "url": "{{ base_url }}/pet/{{ petId }}", "body": { - "mimeType": "application/x-www-form-urlencoded" + "mimeType": "application/x-www-form-urlencoded", + "params": [ + { + "disabled": true, + "name": "name", + "value": "string" + }, + { + "disabled": true, + "name": "status", + "value": "string" + } + ] }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "application/x-www-form-urlencoded" + } + ], "authentication": {}, "_type": "request", "_id": "updatePetWithForm" @@ -170,11 +200,29 @@ "name": "uploads an image", "url": "{{ base_url }}/pet/{{ petId }}/uploadImage", "body": { - "mimeType": "multipart/form-data" + "mimeType": "multipart/form-data", + "params": [ + { + "disabled": true, + "name": "additionalMetadata", + "value": "string" + }, + { + "disabled": true, + "name": "file", + "type": "file" + } + ] }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "name": "Content-Type", + "disabled": false, + "value": "multipart/form-data" + } + ], "authentication": {}, "_type": "request", "_id": "uploadFile" diff --git a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-input.yml b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-input.yml index ecd195aa6..11ca45235 100644 --- a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-input.yml +++ b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-input.yml @@ -1,4 +1,4 @@ -swagger: "2.0" +swagger: '2.0' info: version: 1.0.0 title: Swagger Petstore @@ -27,7 +27,7 @@ paths: type: integer format: int32 responses: - "200": + '200': description: A paged array of pets headers: x-next: @@ -44,8 +44,14 @@ paths: operationId: createPets tags: - pets + parameters: + - name: pet + in: body + required: true + schema: + $ref: '#/definitions/Pet' responses: - "201": + '201': description: Null response default: description: unexpected error @@ -64,7 +70,33 @@ paths: description: The id of the pet to retrieve type: string responses: - "200": + '200': + description: Expected response to a valid request + schema: + $ref: '#/definitions/Pets' + default: + description: unexpected error + schema: + $ref: '#/definitions/Error' + post: + summary: Update specific pet + operationId: updatePet + tags: + - pets + consumes: + - application/x-www-form-urlencoded + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + type: string + - name: name + in: formData + type: string + required: true + responses: + '200': description: Expected response to a valid request schema: $ref: '#/definitions/Pets' @@ -98,4 +130,4 @@ definitions: type: integer format: int32 message: - type: string \ No newline at end of file + type: string diff --git a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-output.json b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-output.json index a88e75585..22722ed15 100644 --- a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-output.json +++ b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-output.json @@ -35,9 +35,7 @@ "parentId": "__WORKSPACE_ID__", "name": "List all pets", "url": "{{ base_url }}/pets", - "body": { - "mimeType": "application/json" - }, + "body": {}, "method": "GET", "parameters": [ { @@ -56,11 +54,18 @@ "name": "Create a pet", "url": "{{ base_url }}/pets", "body": { - "mimeType": "application/json" + "mimeType": "application/json", + "text": "{\n \"id\": 0,\n \"name\": \"string\",\n \"tag\": \"string\"\n}" }, "method": "POST", "parameters": [], - "headers": [], + "headers": [ + { + "disabled": false, + "name": "Content-Type", + "value": "application/json" + } + ], "authentication": {}, "_type": "request", "_id": "createPets" @@ -69,15 +74,40 @@ "parentId": "__WORKSPACE_ID__", "name": "Info for a specific pet", "url": "{{ base_url }}/pets/{{ petId }}", - "body": { - "mimeType": "application/json" - }, + "body": {}, "method": "GET", "parameters": [], "headers": [], "authentication": {}, "_type": "request", "_id": "showPetById" + }, + { + "parentId": "__WORKSPACE_ID__", + "name": "Update specific pet", + "url": "{{ base_url }}/pets/{{ petId }}", + "body": { + "mimeType": "application/x-www-form-urlencoded", + "params": [ + { + "disabled": false, + "name": "name", + "value": "string" + } + ] + }, + "method": "POST", + "parameters": [], + "headers": [ + { + "disabled": false, + "name": "Content-Type", + "value": "application/x-www-form-urlencoded" + } + ], + "authentication": {}, + "_type": "request", + "_id": "updatePet" } ] } diff --git a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-with-tags-output.json b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-with-tags-output.json index c8c10f465..0df8ad80d 100644 --- a/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-with-tags-output.json +++ b/packages/insomnia-importers/src/__tests__/fixtures/swagger2/petstore-yml-with-tags-output.json @@ -43,9 +43,7 @@ "parentId": "__GRP_1__", "name": "List all pets", "url": "{{ base_url }}/pets", - "body": { - "mimeType": "application/json" - }, + "body": {}, "method": "GET", "parameters": [ { @@ -63,9 +61,7 @@ "parentId": "__GRP_1__", "name": "Create a pet", "url": "{{ base_url }}/pets", - "body": { - "mimeType": "application/json" - }, + "body": {}, "method": "POST", "parameters": [], "headers": [], @@ -77,9 +73,7 @@ "parentId": "__GRP_1__", "name": "Info for a specific pet", "url": "{{ base_url }}/pets/{{ petId }}", - "body": { - "mimeType": "application/json" - }, + "body": {}, "method": "GET", "parameters": [], "headers": [], diff --git a/packages/insomnia-importers/src/importers/swagger2.js b/packages/insomnia-importers/src/importers/swagger2.js index 21663d8cc..c9ae6b7c1 100644 --- a/packages/insomnia-importers/src/importers/swagger2.js +++ b/packages/insomnia-importers/src/importers/swagger2.js @@ -3,7 +3,9 @@ const utils = require('../utils'); const SUPPORTED_SWAGGER_VERSION = '2.0'; const MIMETYPE_JSON = 'application/json'; -const SUPPORTED_MIME_TYPES = [MIMETYPE_JSON]; +const MIMETYPE_URLENCODED = 'application/x-www-form-urlencoded'; +const MIMETYPE_MULTIPART = 'multipart/form-data'; +const SUPPORTED_MIME_TYPES = [MIMETYPE_JSON, MIMETYPE_URLENCODED, MIMETYPE_MULTIPART]; const WORKSPACE_ID = '__WORKSPACE_ID__'; let requestCount = 1; @@ -122,7 +124,7 @@ function parseEndpoints(document) { ? `${endpointSchema.operationId}${index > 0 ? index : ''}` : `__REQUEST_${requestCount++}__`; let parentId = folderLookup[tag] || defaultParent; - requests.push(importRequest(endpointSchema, globalMimeTypes, id, parentId)); + requests.push(importRequest(document, endpointSchema, globalMimeTypes, id, parentId)); }); }); @@ -150,26 +152,36 @@ function importFolderItem(item, parentId) { /** * Return Insomnia request * - * + * @param {Object} schema - swagger 2.0 schema * @param {Object} endpointSchema - swagger 2.0 endpoint schema * @param {string[]} globalMimeTypes - list of mimeTypes available in document globally (i.e. document.consumes) * @param {string} id - id to be given to current request * @param {string} parentId - id of parent category * @returns {Object} */ -function importRequest(endpointSchema, globalMimeTypes, id, parentId) { +function importRequest(schema, endpointSchema, globalMimeTypes, id, parentId) { const name = endpointSchema.summary || `${endpointSchema.method} ${endpointSchema.path}`; - return { + const request = { _type: 'request', _id: id, parentId: parentId, name, method: endpointSchema.method.toUpperCase(), url: '{{ base_url }}' + pathWithParamsAsVariables(endpointSchema.path), - body: prepareBody(endpointSchema, globalMimeTypes), + body: prepareBody(schema, endpointSchema, globalMimeTypes), headers: prepareHeaders(endpointSchema), parameters: prepareQueryParams(endpointSchema), }; + if (request.body.mimeType && !request.headers.find(header => header.name === 'Content-Type')) { + request.headers = [ + { + name: 'Content-Type', + disabled: false, + value: request.body.mimeType, + }, + ].concat(request.headers); + } + return request; } /** @@ -210,39 +222,69 @@ function prepareHeaders(endpointSchema) { return convertParameters(headerParameters); } +function resolve$ref(schema, $ref) { + const parts = $ref.split('/'); + parts.shift(); // remove # + return parts.reduce((doc, path) => doc[path], schema); +} + /** * Imports insomnia request body definitions, including data mock (if available) * * If multiple types are available, the one for which an example can be generated will be selected first (i.e. application/json) * + * @param {Object} schema - swagger 2.0 schema * @param {Object} endpointSchema - swagger 2.0 endpoint schema * @param {string[]} globalMimeTypes - list of mimeTypes available in document globally (i.e. document.consumes) * * @return {Object} insomnia request's body definition */ -function prepareBody(endpointSchema, globalMimeTypes) { +function prepareBody(schema, endpointSchema, globalMimeTypes) { const mimeTypes = endpointSchema.consumes || globalMimeTypes || []; const isAvailable = m => mimeTypes.includes(m); const supportedMimeType = SUPPORTED_MIME_TYPES.find(isAvailable); - if (supportedMimeType === MIMETYPE_JSON) { const isSendInBody = p => p.in === 'body'; const parameters = endpointSchema.parameters || []; const bodyParameter = parameters.find(isSendInBody); if (!bodyParameter) { - return { - mimeType: supportedMimeType, - }; + return {}; + } + + const type = bodyParameter.type || 'object'; + const example = generateParameterExample(type); + let text; + if (type === 'object') { + if (bodyParameter.schema.$ref) { + const definition = resolve$ref(schema, bodyParameter.schema.$ref); + text = JSON.stringify(example(definition), null, 2); + } else { + text = JSON.stringify(example(bodyParameter.schema), null, 2); + } + } else { + text = JSON.stringify(example, null, 2); } - const example = bodyParameter ? generateParameterExample(bodyParameter.schema) : undefined; - const text = JSON.stringify(example, null, 2); return { mimeType: supportedMimeType, text, }; } + if (supportedMimeType === MIMETYPE_URLENCODED || supportedMimeType === MIMETYPE_MULTIPART) { + const isSendInFormData = p => p.in === 'formData'; + const parameters = endpointSchema.parameters || []; + const formDataParameters = parameters.filter(isSendInFormData); + + if (formDataParameters.length === 0) { + return {}; + } + return { + mimeType: supportedMimeType, + params: convertParameters(formDataParameters), + }; + } + if (mimeTypes && mimeTypes.length) { return { mimeType: mimeTypes[0] || undefined, @@ -260,7 +302,14 @@ function prepareBody(endpointSchema, globalMimeTypes) { */ function convertParameters(parameters) { return parameters.map(parameter => { - const { required, name } = parameter; + const { required, name, type } = parameter; + if (type === 'file') { + return { + name, + disabled: required !== true, + type: 'file', + }; + } return { name, disabled: required !== true,