[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
This commit is contained in:
Matthias Ramsauer 2019-11-22 18:36:33 +01:00 committed by Gregory Schier
parent 0933337c1e
commit ab990d7a40
9 changed files with 358 additions and 60 deletions

View File

@ -21,6 +21,7 @@ describe('Fixtures', () => {
}
it(`Import ${name} ${input}`, async () => {
expect.assertions(5);
expect(typeof input).toBe('string');
expect(typeof output).toBe('string');

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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
type: string

View File

@ -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"
}
]
}

View File

@ -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": [],

View File

@ -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,