From 57d54731f6f0f53dec3abdf63cff8489839b839f Mon Sep 17 00:00:00 2001 From: Shahar Shelly Date: Sun, 31 Mar 2019 00:33:40 +0300 Subject: [PATCH 1/3] added support for form data --- README.md | 17 +++++++++++++++++ package.json | 2 ++ src/configSchema.ts | 11 ++++++++++- src/test.ts | 23 +++++++++++++++++++++++ tests/strest.png | Bin 0 -> 7186 bytes tests/success/formdata/file.strest.yml | 22 ++++++++++++++++++++++ tests/success/formdata/simple.strest.yml | 19 +++++++++++++++++++ 7 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 tests/strest.png create mode 100644 tests/success/formdata/file.strest.yml create mode 100644 tests/success/formdata/simple.strest.yml diff --git a/README.md b/README.md index c312ed3..ca8868a 100644 --- a/README.md +++ b/README.md @@ -378,7 +378,24 @@ requests: expect: "<$ '2019-10-10' | date('YYYY') $>" ``` +## Sending files and form data +Sending files and form data is easy, use form type in the postData prop. +```yaml +version: 2 +requests: + postwithfile: + request: + url: https://postman-echo.com/post + method: POST + postData: + mimeType: application/x-www-form-urlencoded + form: + - name: userId + value: "1" + - name: avatar + value: <$ file("tests/strest.png") $> +``` ## Response Validation The immediate response is stored in [HAR Format](http://www.softwareishard.com/blog/har-12-spec/#response) diff --git a/package.json b/package.json index 26da6bc..b58a56f 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "commander": "^2.17.1", "deep-eql": "4.0.0", "faker": "^4.1.0", + "form-data": "^2.3.3", "get-line-from-pos": "1.0.0", "joi": "^13.6.0", "js-yaml": "^3.12.0", @@ -54,6 +55,7 @@ "devDependencies": { "@types/commander": "^2.12.2", "@types/faker": "^4.1.3", + "@types/form-data": "^2.2.1", "@types/jest": "^23.3.2", "@types/joi": "^13.4.4", "@types/js-yaml": "^3.11.2", diff --git a/src/configSchema.ts b/src/configSchema.ts index 84a96e4..dabacca 100644 --- a/src/configSchema.ts +++ b/src/configSchema.ts @@ -46,9 +46,14 @@ const postDataSchema = Joi.object().keys({ mimeType: Joi.string().required(), params: Joi.array().items(paramsSchema).optional(), text : Joi.alternatives().try(Joi.object(), Joi.string()).optional(), + form : Joi.array().items(paramsSchema).optional(), comment: Joi.string().optional(), }).without('text', 'params') .without('params', 'text') + .without('form', 'params') + .without('form', 'text') + .without('text', 'form') + .without('params', 'form') const requestSchema = Joi.object().keys({ url: Joi.string().required(), @@ -141,11 +146,15 @@ interface paramsObjectSchema { name: string, value: string, } - +interface formObjectSchema { + name: string, + value: any, +} interface postDataObjectSchema { mimeType: string, params: Array, text : string, + form : Array, comment: string, } diff --git a/src/test.ts b/src/test.ts index db3f47e..2081357 100644 --- a/src/test.ts +++ b/src/test.ts @@ -13,6 +13,8 @@ import * as jsonfile from 'jsonfile' import * as path from 'path'; import * as Ajv from 'ajv'; import * as nunjucksDate from 'nunjucks-date'; +import * as fs from 'fs'; +import * as FormData from 'form-data'; var deepEql = require("deep-eql"); var lineNumber = require('line-number'); @@ -44,6 +46,10 @@ nunjucksEnv.addGlobal('Env', function (envi: string) { return environ; }) +nunjucksEnv.addGlobal('file', function (filePath: string) { + const key = `sendFile:${path.resolve(filePath)}`; + return key; +}); /** * All Data that any request returns, will be stored here. After that it can be used in the following methods */ @@ -405,11 +411,28 @@ const performRequest = async (requestObject: requestsObjectSchema, requestName: if (requestObject.request.postData.text) { axiosObject.data = requestObject.request.postData.text; } + if (requestObject.request.postData.params) { const searchParams = new URLSearchParams() requestObject.request.postData.params.forEach(item=>{searchParams.append(item.name,item.value)}) axiosObject.data = searchParams.toString(); } + + if (requestObject.request.postData.form) { + const form: FormData = new FormData(); + requestObject.request.postData.form.forEach(item=>{ + if(item.value.startsWith('sendFile:')){ + const filePath = item.value.replace('sendFile:',''); + const fileStream = fs.createReadStream(filePath); + form.append(item.name, fileStream, { filepath:filePath }); + } + else{ + form.append(item.name, item.value); + } + }); + axiosObject.data = form; + axiosObject.headers = {...axiosObject.headers,...form.getHeaders()}; + } } try { diff --git a/tests/strest.png b/tests/strest.png new file mode 100644 index 0000000000000000000000000000000000000000..d89f48c3bb523f736eff8bd406fc42356797664a GIT binary patch literal 7186 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 literal 0 HcmV?d00001 diff --git a/tests/success/formdata/file.strest.yml b/tests/success/formdata/file.strest.yml new file mode 100644 index 0000000..225f563 --- /dev/null +++ b/tests/success/formdata/file.strest.yml @@ -0,0 +1,22 @@ +version: 2 +requests: + postwithfile: + request: + url: https://postman-echo.com/post + method: POST + postData: + mimeType: application/x-www-form-urlencoded + form: + - name: title + value: foo + - name: body + value: bar + - name: userId + value: "1" + - name: avatar + value: <$ file("tests/strest.png") $> + validate: + - jsonpath: content.form.title + expect: foo + - jsonpath: content.files["strest.png"] + type: [ string] \ No newline at end of file diff --git a/tests/success/formdata/simple.strest.yml b/tests/success/formdata/simple.strest.yml new file mode 100644 index 0000000..1924f2a --- /dev/null +++ b/tests/success/formdata/simple.strest.yml @@ -0,0 +1,19 @@ +version: 2 + +requests: + simpleformdata: + request: + url: https://postman-echo.com/post + method: POST + postData: + mimeType: application/x-www-form-urlencoded + form: + - name: title + value: foo + - name: body + value: bar + - name: userId + value: "1" + validate: + - jsonpath: content.form.title + expect: foo \ No newline at end of file From ed9e7687b1dbfd47036f87e82cdaee417938cb25 Mon Sep 17 00:00:00 2001 From: Shahar Shelly Date: Sat, 6 Apr 2019 16:31:55 +0300 Subject: [PATCH 2/3] added support for form data --- src/configSchema.ts | 10 ------ src/test.ts | 40 +++++++++++++----------- tests/success/formdata/file.strest.yml | 15 ++++++--- tests/success/formdata/simple.strest.yml | 2 +- 4 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/configSchema.ts b/src/configSchema.ts index dabacca..e3d41ba 100644 --- a/src/configSchema.ts +++ b/src/configSchema.ts @@ -46,14 +46,9 @@ const postDataSchema = Joi.object().keys({ mimeType: Joi.string().required(), params: Joi.array().items(paramsSchema).optional(), text : Joi.alternatives().try(Joi.object(), Joi.string()).optional(), - form : Joi.array().items(paramsSchema).optional(), comment: Joi.string().optional(), }).without('text', 'params') .without('params', 'text') - .without('form', 'params') - .without('form', 'text') - .without('text', 'form') - .without('params', 'form') const requestSchema = Joi.object().keys({ url: Joi.string().required(), @@ -146,15 +141,10 @@ interface paramsObjectSchema { name: string, value: string, } -interface formObjectSchema { - name: string, - value: any, -} interface postDataObjectSchema { mimeType: string, params: Array, text : string, - form : Array, comment: string, } diff --git a/src/test.ts b/src/test.ts index 2081357..51b2f4a 100644 --- a/src/test.ts +++ b/src/test.ts @@ -413,25 +413,27 @@ const performRequest = async (requestObject: requestsObjectSchema, requestName: } if (requestObject.request.postData.params) { - const searchParams = new URLSearchParams() - requestObject.request.postData.params.forEach(item=>{searchParams.append(item.name,item.value)}) - axiosObject.data = searchParams.toString(); - } - - if (requestObject.request.postData.form) { - const form: FormData = new FormData(); - requestObject.request.postData.form.forEach(item=>{ - if(item.value.startsWith('sendFile:')){ - const filePath = item.value.replace('sendFile:',''); - const fileStream = fs.createReadStream(filePath); - form.append(item.name, fileStream, { filepath:filePath }); - } - else{ - form.append(item.name, item.value); - } - }); - axiosObject.data = form; - axiosObject.headers = {...axiosObject.headers,...form.getHeaders()}; + if(requestObject.request.postData.mimeType && requestObject.request.postData.mimeType.toLowerCase()=='application/x-www-form-urlencoded') + { + const searchParams = new URLSearchParams() + requestObject.request.postData.params.forEach(item=>{searchParams.append(item.name,item.value)}) + axiosObject.data = searchParams.toString(); + } + else{ + const form: FormData = new FormData(); + requestObject.request.postData.params.forEach(item=>{ + if(item.value.startsWith('sendFile:')){ + const filePath = item.value.replace('sendFile:',''); + const fileStream = fs.createReadStream(filePath); + form.append(item.name, fileStream, { filepath:filePath }); + } + else{ + form.append(item.name, item.value); + } + }); + axiosObject.data = form; + axiosObject.headers = {...axiosObject.headers,...form.getHeaders()}; + } } } diff --git a/tests/success/formdata/file.strest.yml b/tests/success/formdata/file.strest.yml index 225f563..df77af4 100644 --- a/tests/success/formdata/file.strest.yml +++ b/tests/success/formdata/file.strest.yml @@ -2,11 +2,14 @@ version: 2 requests: postwithfile: request: - url: https://postman-echo.com/post + # url: https://postman-echo.com/post + # url: http://localhost:3000/post + # url: http://jkorpela.fi/cgi-bin/echoraw.cgi + url: http://httpbin.org/post method: POST postData: - mimeType: application/x-www-form-urlencoded - form: + mimeType: multipart/form-data + params: - name: title value: foo - name: body @@ -15,8 +18,10 @@ requests: value: "1" - name: avatar value: <$ file("tests/strest.png") $> + - name: avatar1 + value: <$ file("tests/strest.png") $> validate: - jsonpath: content.form.title expect: foo - - jsonpath: content.files["strest.png"] - type: [ string] \ No newline at end of file + - jsonpath: content.files["avatar"] + type: [string] \ No newline at end of file diff --git a/tests/success/formdata/simple.strest.yml b/tests/success/formdata/simple.strest.yml index 1924f2a..27f583e 100644 --- a/tests/success/formdata/simple.strest.yml +++ b/tests/success/formdata/simple.strest.yml @@ -7,7 +7,7 @@ requests: method: POST postData: mimeType: application/x-www-form-urlencoded - form: + params: - name: title value: foo - name: body From bc95e1a11060a8cd78d5262c64b4877795b5758c Mon Sep 17 00:00:00 2001 From: Shahar Shelly Date: Sat, 6 Apr 2019 16:48:20 +0300 Subject: [PATCH 3/3] updated the readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ca8868a..98cc929 100644 --- a/README.md +++ b/README.md @@ -379,7 +379,7 @@ requests: ``` ## Sending files and form data -Sending files and form data is easy, use form type in the postData prop. +Sending files and form data is easy, use params type in the postData prop. ```yaml version: 2 requests: @@ -388,8 +388,8 @@ requests: url: https://postman-echo.com/post method: POST postData: - mimeType: application/x-www-form-urlencoded - form: + mimeType: multipart/form-data + params: - name: userId value: "1" - name: avatar