diff --git a/docs/assets/css/style.scss b/docs/assets/css/style.scss index 3526b88..03e965e 100644 --- a/docs/assets/css/style.scss +++ b/docs/assets/css/style.scss @@ -7,7 +7,7 @@ $header-bg-color-secondary: #5f5278 !default; $body-link-color: #3b95ef !default; $section-headings-color: #ff6b37 !default; -@import "{{ site.theme }}"; +@import "jekyll-theme-cayman"; strong { color: #788286; diff --git a/lib/index.js b/lib/index.js index 6185e9a..13d4e12 100644 --- a/lib/index.js +++ b/lib/index.js @@ -171,15 +171,16 @@ function parseBody (body = {}, method) { 'multipart/form-data': { schema: { type: 'object', - properties: body.formdata.reduce((obj, { key, type, description, value }) => { - obj[key] = { - type: 'string', - ...(description ? { description } : {}), - ...(value ? { example: value } : {}), - ...(type === 'file' ? { format: 'binary' } : {}) - } - return obj - }, {}) + properties: body.formdata.reduce(mapFormData(), {}) + } + } + } + break + case 'urlencoded': + content = { + 'application/x-www-form-urlencoded': { + schema: { + properties: body.urlencoded.reduce(mapFormData(), {}) } } } @@ -188,6 +189,19 @@ function parseBody (body = {}, method) { return { requestBody: { content } } } +/* Accumulator function for form data values */ +function mapFormData () { + return (obj, { key, type, description, value }) => { + obj[key] = { + type: inferType(value), + ...(description ? { description: description.replace(/ ?\[required\] ?/gi, '') } : {}), + ...(value ? { example: value } : {}), + ...(type === 'file' ? { format: 'binary' } : {}) + } + return obj + } +} + /* Parse the Postman query and header and transform into OpenApi parameters */ function parseParameters (query = [], header, paths, paramsMeta = {}) { // parse Headers diff --git a/test/index.spec.js b/test/index.spec.js index e14fc31..d1d40b0 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -49,6 +49,7 @@ const EXPECTED_RESPONSES_MULTI_LANG = readFileSync('./test/resources/output/Resp const EXPECTED_AUTH_REQUEST = readFileSync('./test/resources/output/AuthRequest.yml', 'utf8') const EXPECTED_RESPONSES_NO_HEADERS = readFileSync('./test/resources/output/ResponsesNoHeaders.yml', 'utf8') const EXPECTED_FORM_DATA = readFileSync('./test/resources/output/FormData.yml', 'utf8') +const EXPECTED_WWW_FORM_URLENCODED = readFileSync('./test/resources/output/WwwFormUrlencoded.yml', 'utf8') const AUTH_DEFINITIONS = { myCustomAuth: { @@ -104,6 +105,7 @@ describe('Library specs', function () { const COLLECTION_RESPONSES_MULTI_LANG = `./test/resources/input/${version}/ResponsesMultiLang.json` const COLLECTION_AUTH_REQUEST = `./test/resources/input/${version}/AuthRequest.json` const COLLECTION_FORM_DATA = `./test/resources/input/${version}/FormData.json` + const COLLECTION_WWW_FORM_URLENCODED = `./test/resources/input/${version}/WwwFormUrlencoded.json` it('should work with a basic transform', async function () { const result = await postmanToOpenApi(COLLECTION_BASIC, OUTPUT_PATH, {}) @@ -402,6 +404,11 @@ describe('Library specs', function () { const result = await postmanToOpenApi(COLLECTION_FORM_DATA, OUTPUT_PATH, {}) equal(result, EXPECTED_FORM_DATA) }) + + it('should parse POST methods with www form urlencoded', async function () { + const result = await postmanToOpenApi(COLLECTION_WWW_FORM_URLENCODED, OUTPUT_PATH, {}) + equal(result, EXPECTED_WWW_FORM_URLENCODED) + }) }) }) diff --git a/test/resources/input/v2/FormData.json b/test/resources/input/v2/FormData.json index 586a94a..8c74f1f 100644 --- a/test/resources/input/v2/FormData.json +++ b/test/resources/input/v2/FormData.json @@ -17,13 +17,13 @@ { "key": "name", "value": "New User", - "description": "full name of the user (accepts spaces)", + "description": "full name of the user (accepts spaces) [required]", "type": "text" }, { "key": "email", "value": "newuser@example.com", - "description": "email of the user (for notifications and login)", + "description": "email of the user (for notifications and login) [required]", "type": "text" }, { @@ -34,6 +34,7 @@ { "key": "profileImage", "description": "User avatar", + "contentType": "application/octet-stream", "type": "file", "src": [] } @@ -44,4 +45,4 @@ "response": [] } ] -} \ No newline at end of file +} diff --git a/test/resources/input/v2/WwwFormUrlencoded.json b/test/resources/input/v2/WwwFormUrlencoded.json new file mode 100644 index 0000000..53ee6da --- /dev/null +++ b/test/resources/input/v2/WwwFormUrlencoded.json @@ -0,0 +1,41 @@ +{ + "info": { + "_postman_id": "1eaa74c4-2d76-45f0-bd34-bff5d96f0ba8", + "name": "Form Data", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "Register New User", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "name", + "value": "New User", + "description": "full name of the user (accepts spaces) [required]", + "type": "text" + }, + { + "key": "email", + "value": "newuser@example.com", + "description": "email of the user (for notifications and login) [required]", + "type": "text" + }, + { + "key": "password", + "value": "pasword123", + "description": "password (to be used for logging in) [required]", + "type": "text" + } + ] + }, + "url": "https://api.io/register" + }, + "response": [] + } + ] +} diff --git a/test/resources/input/v21/FormData.json b/test/resources/input/v21/FormData.json index 247c2a6..759c664 100644 --- a/test/resources/input/v21/FormData.json +++ b/test/resources/input/v21/FormData.json @@ -17,13 +17,13 @@ { "key": "name", "value": "New User", - "description": "full name of the user (accepts spaces)", + "description": "full name of the user (accepts spaces) [required]", "type": "text" }, { "key": "email", "value": "newuser@example.com", - "description": "email of the user (for notifications and login)", + "description": "email of the user (for notifications and login) [required]", "type": "text" }, { @@ -34,6 +34,7 @@ { "key": "profileImage", "description": "User avatar", + "contentType": "application/octet-stream", "type": "file", "src": [] } @@ -54,4 +55,4 @@ "response": [] } ] -} \ No newline at end of file +} diff --git a/test/resources/input/v21/WwwFormUrlencoded.json b/test/resources/input/v21/WwwFormUrlencoded.json new file mode 100644 index 0000000..faff9dc --- /dev/null +++ b/test/resources/input/v21/WwwFormUrlencoded.json @@ -0,0 +1,51 @@ +{ + "info": { + "_postman_id": "1eaa74c4-2d76-45f0-bd34-bff5d96f0ba8", + "name": "Form Data", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Register New User", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "name", + "value": "New User", + "description": "full name of the user (accepts spaces) [required]", + "type": "text" + }, + { + "key": "email", + "value": "newuser@example.com", + "description": "email of the user (for notifications and login) [required]", + "type": "text" + }, + { + "key": "password", + "value": "pasword123", + "description": "password (to be used for logging in) [required]", + "type": "text" + } + ] + }, + "url": { + "raw": "https://api.io/register", + "protocol": "https", + "host": [ + "api", + "io" + ], + "path": [ + "register" + ] + } + }, + "response": [] + } + ] +} diff --git a/test/resources/output/WwwFormUrlencoded.yml b/test/resources/output/WwwFormUrlencoded.yml new file mode 100644 index 0000000..e2d5656 --- /dev/null +++ b/test/resources/output/WwwFormUrlencoded.yml @@ -0,0 +1,34 @@ +openapi: 3.0.0 +info: + title: Form Data + version: 1.0.0 +servers: + - url: https://api.io +paths: + /register: + post: + tags: + - default + summary: Register New User + requestBody: + content: + application/x-www-form-urlencoded: + schema: + properties: + name: + type: string + description: full name of the user (accepts spaces) + example: New User + email: + type: string + description: email of the user (for notifications and login) + example: newuser@example.com + password: + type: string + description: password (to be used for logging in) + example: pasword123 + responses: + '200': + description: Successful response + content: + application/json: {}