mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-04 23:16:57 +08:00
add unittest; add --patch options
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
## hrp postman2case
|
||||||
|
|
||||||
|
convert postman collection to json/yaml testcase files
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
convert postman collection to json/yaml testcase files
|
||||||
|
|
||||||
|
```
|
||||||
|
hrp postman2case $postman_path... [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for postman2case
|
||||||
|
-d, --output-dir string specify output directory, default to the same dir with postman collection file
|
||||||
|
-j, --to-json convert to JSON format (default true)
|
||||||
|
-y, --to-yaml convert to YAML format
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 12-May-2022
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
{
|
|
||||||
"config": {
|
|
||||||
"name": "testcase description"
|
|
||||||
},
|
|
||||||
"teststeps": [
|
|
||||||
{
|
|
||||||
"name": "",
|
|
||||||
"request": {
|
|
||||||
"method": "GET",
|
|
||||||
"url": "https://postman-echo.com/get",
|
|
||||||
"params": {
|
|
||||||
"foo1": "HDnY8",
|
|
||||||
"foo2": "34.5"
|
|
||||||
},
|
|
||||||
"headers": {
|
|
||||||
"Accept-Encoding": "gzip",
|
|
||||||
"Host": "postman-echo.com",
|
|
||||||
"User-Agent": "HttpRunnerPlus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"validate": [
|
|
||||||
{
|
|
||||||
"check": "status_code",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": 200,
|
|
||||||
"msg": "assert response status code"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"check": "headers.\"Content-Type\"",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": "application/json; charset=utf-8",
|
|
||||||
"msg": "assert response header Content-Type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"check": "body.url",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": "https://postman-echo.com/get?foo1=HDnY8\u0026foo2=34.5",
|
|
||||||
"msg": "assert response body url"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "",
|
|
||||||
"request": {
|
|
||||||
"method": "POST",
|
|
||||||
"url": "https://postman-echo.com/post",
|
|
||||||
"headers": {
|
|
||||||
"Accept-Encoding": "gzip",
|
|
||||||
"Content-Length": "28",
|
|
||||||
"Content-Type": "application/json; charset=UTF-8",
|
|
||||||
"Host": "postman-echo.com",
|
|
||||||
"User-Agent": "Go-http-client/1.1"
|
|
||||||
},
|
|
||||||
"cookies": {
|
|
||||||
"sails.sid": "s%3Az_LpglkKxTvJ_eHVUH6V67drKp0AGWW-.PidabaXOnatLRP47hVyqqepl6BdrpEQzRlJQXtbIiwk"
|
|
||||||
},
|
|
||||||
"body": {
|
|
||||||
"foo1": "HDnY8",
|
|
||||||
"foo2": 12.3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"validate": [
|
|
||||||
{
|
|
||||||
"check": "status_code",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": 200,
|
|
||||||
"msg": "assert response status code"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"check": "headers.\"Content-Type\"",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": "application/json; charset=utf-8",
|
|
||||||
"msg": "assert response header Content-Type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"check": "body.url",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": "https://postman-echo.com/post",
|
|
||||||
"msg": "assert response body url"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "",
|
|
||||||
"request": {
|
|
||||||
"method": "POST",
|
|
||||||
"url": "https://postman-echo.com/post",
|
|
||||||
"headers": {
|
|
||||||
"Accept-Encoding": "gzip",
|
|
||||||
"Content-Length": "20",
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
|
||||||
"Host": "postman-echo.com",
|
|
||||||
"User-Agent": "Go-http-client/1.1"
|
|
||||||
},
|
|
||||||
"cookies": {
|
|
||||||
"sails.sid": "s%3AS5e7w0zQ0xAsCwh9L8T6R7QLYCO7_gtD.r8%2B2w9IWqEIfuVkrZjnxzm2xADIk34zKAWXRPapr%2FAw"
|
|
||||||
},
|
|
||||||
"body": "foo1=HDnY8\u0026foo2=12.3"
|
|
||||||
},
|
|
||||||
"validate": [
|
|
||||||
{
|
|
||||||
"check": "status_code",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": 200,
|
|
||||||
"msg": "assert response status code"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"check": "headers.\"Content-Type\"",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": "application/json; charset=utf-8",
|
|
||||||
"msg": "assert response header Content-Type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"check": "body.data",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": "",
|
|
||||||
"msg": "assert response body data"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"check": "body.url",
|
|
||||||
"assert": "equals",
|
|
||||||
"expect": "https://postman-echo.com/post",
|
|
||||||
"msg": "assert response body url"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
+148
-6
@@ -51,7 +51,7 @@
|
|||||||
},
|
},
|
||||||
"response": [
|
"response": [
|
||||||
{
|
{
|
||||||
"name": "Get with params",
|
"name": "Get with params case1",
|
||||||
"originalRequest": {
|
"originalRequest": {
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"header": [],
|
"header": [],
|
||||||
@@ -88,10 +88,115 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
"_postman_previewlanguage": "json",
|
"_postman_previewlanguage": "json",
|
||||||
"header": null,
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Date",
|
||||||
|
"value": "Mon, 16 May 2022 12:12:28 GMT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json; charset=utf-8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Length",
|
||||||
|
"value": "508"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Connection",
|
||||||
|
"value": "keep-alive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "ETag",
|
||||||
|
"value": "W/\"1fc-x4EIPFQzoLX0HenCFPx6HNfG0lc\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Vary",
|
||||||
|
"value": "Accept-Encoding"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "set-cookie",
|
||||||
|
"value": "sails.sid=s%3AX2aa_Z7gbcUqIWAjlBkytBRmQ4WCvc3D.pX9Qxh8aO9Ict0BL4CrRhdDJmz81UVmwFsV5Nx30Ils; Path=/; HttpOnly"
|
||||||
|
}
|
||||||
|
],
|
||||||
"cookie": [],
|
"cookie": [],
|
||||||
"body": "{\n \"args\": {\n \"k1\": \"v1\",\n \"k2\": \"v2\"\n },\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"user-agent\": \"PostmanRuntime/7.29.0\",\n \"accept\": \"*/*\",\n \"accept-encoding\": \"gzip, deflate, br\"\n },\n \"url\": \"https://postman-echo.com/get?k1=v1&k2=v2\"\n}"
|
"body": "{\n \"args\": {\n \"k1\": \"v1\",\n \"k2\": \"v2\"\n },\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"user-agent\": \"PostmanRuntime/7.29.0\",\n \"accept\": \"*/*\",\n \"accept-encoding\": \"gzip, deflate, br\",\n \"cookie\": \"Cookie_1=c1; Cookie_2=c2; sails.sid=s%3AGX6aS9b_phvUSUk66w7ZBgWuOPI7IIKT.ayEGTaW4U35eAWyPz%2Fh6Q74DonNcbqw3H5Q5Zv%2BfKMY\"\n },\n \"url\": \"https://postman-echo.com/get?k1=v1&k2=v2\"\n}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get with params case2",
|
||||||
|
"originalRequest": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "https://postman-echo.com/:path?k1=v1&k3=v3",
|
||||||
|
"protocol": "https",
|
||||||
|
"host": [
|
||||||
|
"postman-echo",
|
||||||
|
"com"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
":path"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "k1",
|
||||||
|
"value": "v1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "k2",
|
||||||
|
"value": "v2",
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "k3",
|
||||||
|
"value": "v3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"key": "path",
|
||||||
|
"value": "get"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
|
"_postman_previewlanguage": "json",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Date",
|
||||||
|
"value": "Mon, 16 May 2022 12:14:04 GMT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json; charset=utf-8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Length",
|
||||||
|
"value": "504"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Connection",
|
||||||
|
"value": "keep-alive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "ETag",
|
||||||
|
"value": "W/\"1f8-tMaKs4xmwr+3su3I8mcgR0p+ucw\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Vary",
|
||||||
|
"value": "Accept-Encoding"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "set-cookie",
|
||||||
|
"value": "sails.sid=s%3AMNuX_i0KgaP_KuuMpYB8RtCNipCGJWVw.4ETfPHxE81Omqb6Yli%2FezUU8CXyYBcN3%2Bxkx5htwh8Y; Path=/; HttpOnly"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cookie": [],
|
||||||
|
"body": "{\n \"args\": {\n \"k1\": \"v1\",\n \"k3\": \"v3\"\n },\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"user-agent\": \"PostmanRuntime/7.29.0\",\n \"accept\": \"*/*\",\n \"accept-encoding\": \"gzip, deflate, br\",\n \"cookie\": \"Cookie_1=c1; Cookie_2=c2; sails.sid=s%3AX2aa_Z7gbcUqIWAjlBkytBRmQ4WCvc3D.pX9Qxh8aO9Ict0BL4CrRhdDJmz81UVmwFsV5Nx30Ils\"\n },\n \"url\": \"https://postman-echo.com/get?k1=v1&k3=v3\"\n}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -279,6 +384,11 @@
|
|||||||
"value": "bbx",
|
"value": "bbx",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"disabled": true
|
"disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Connection",
|
||||||
|
"value": "close",
|
||||||
|
"type": "text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"url": {
|
"url": {
|
||||||
@@ -301,7 +411,7 @@
|
|||||||
},
|
},
|
||||||
"response": [
|
"response": [
|
||||||
{
|
{
|
||||||
"name": "Get request headers",
|
"name": "Get request headers case1",
|
||||||
"originalRequest": {
|
"originalRequest": {
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"header": [
|
"header": [
|
||||||
@@ -315,6 +425,11 @@
|
|||||||
"value": "bbx",
|
"value": "bbx",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"disabled": true
|
"disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Cookie",
|
||||||
|
"value": "Cookie_1=c1; Cookie_2=c2; sails.sid=s%3AGX6aS9b_phvUSUk66w7ZBgWuOPI7IIKT.ayEGTaW4U35eAWyPz%2Fh6Q74DonNcbqw3H5Q5Zv%2BfKMY",
|
||||||
|
"type": "text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"url": {
|
"url": {
|
||||||
@@ -335,10 +450,37 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
"_postman_previewlanguage": "json",
|
"_postman_previewlanguage": "json",
|
||||||
"header": null,
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Date",
|
||||||
|
"value": "Mon, 16 May 2022 12:14:25 GMT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json; charset=utf-8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Length",
|
||||||
|
"value": "541"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Connection",
|
||||||
|
"value": "keep-alive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "ETag",
|
||||||
|
"value": "W/\"21d-ld5UvFTaRM6lihVnvCj6mZm5Of0\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Vary",
|
||||||
|
"value": "Accept-Encoding"
|
||||||
|
}
|
||||||
|
],
|
||||||
"cookie": [],
|
"cookie": [],
|
||||||
"body": "{\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"user-agent\": \"HttpRunner\",\n \"accept\": \"*/*\",\n \"accept-encoding\": \"gzip, deflate, br\"\n }\n}"
|
"body": "{\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"user-agent\": \"HttpRunner\",\n \"cookie\": \"Cookie_1=c1; Cookie_2=c2; sails.sid=s%3AGX6aS9b_phvUSUk66w7ZBgWuOPI7IIKT.ayEGTaW4U35eAWyPz%2Fh6Q74DonNcbqw3H5Q5Zv%2BfKMY\",\n \"accept\": \"*/*\",\n \"accept-encoding\": \"gzip, deflate, br\"\n }\n}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
headers:
|
||||||
|
User-Agent: "this header will be created or updated"
|
||||||
|
cookies:
|
||||||
|
Cookie1: "this cookie will be created or updated"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
headers:
|
||||||
|
Header1: "all original headers will be overridden"
|
||||||
|
cookies:
|
||||||
|
Cookie1: "all original cookies will be overridden"
|
||||||
+4
-3
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/convert"
|
"github.com/httprunner/httprunner/v4/hrp/internal/convert/case2script"
|
||||||
)
|
)
|
||||||
|
|
||||||
var convertCmd = &cobra.Command{
|
var convertCmd = &cobra.Command{
|
||||||
@@ -18,15 +18,16 @@ var convertCmd = &cobra.Command{
|
|||||||
setLogLevel(logLevel)
|
setLogLevel(logLevel)
|
||||||
},
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
// TODO: integrate har2case, postman2case, etc. in convert command (forward compatibility)
|
||||||
if !pytestFlag && !gotestFlag {
|
if !pytestFlag && !gotestFlag {
|
||||||
return errors.New("please specify convertion type")
|
return errors.New("please specify convertion type")
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if gotestFlag {
|
if gotestFlag {
|
||||||
err = convert.Convert2TestScripts("gotest", args...)
|
err = case2script.Convert2TestScripts("gotest", args...)
|
||||||
} else {
|
} else {
|
||||||
err = convert.Convert2TestScripts("pytest", args...)
|
err = case2script.Convert2TestScripts("pytest", args...)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("convert test scripts failed")
|
log.Error().Err(err).Msg("convert test scripts failed")
|
||||||
|
|||||||
+22
-15
@@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/har2case"
|
"github.com/httprunner/httprunner/v4/hrp/internal/convert/har2case"
|
||||||
)
|
)
|
||||||
|
|
||||||
// har2caseCmd represents the har2case command
|
// har2caseCmd represents the har2case command
|
||||||
@@ -22,7 +22,7 @@ var har2caseCmd = &cobra.Command{
|
|||||||
var outputFiles []string
|
var outputFiles []string
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
// must choose one
|
// must choose one
|
||||||
if !genYAMLFlag && !genJSONFlag {
|
if !har2caseGenYAMLFlag && !har2caseGenJSONFlag {
|
||||||
return errors.New("please select convert format type")
|
return errors.New("please select convert format type")
|
||||||
}
|
}
|
||||||
var outputPath string
|
var outputPath string
|
||||||
@@ -31,17 +31,22 @@ var har2caseCmd = &cobra.Command{
|
|||||||
har := har2case.NewHAR(arg)
|
har := har2case.NewHAR(arg)
|
||||||
|
|
||||||
// specify output dir
|
// specify output dir
|
||||||
if outputDir != "" {
|
if har2caseOutputDir != "" {
|
||||||
har.SetOutputDir(outputDir)
|
har.SetOutputDir(har2caseOutputDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// specify profile
|
// specify profile
|
||||||
if profilePath != "" {
|
if har2caseProfilePath != "" {
|
||||||
har.SetProfile(profilePath)
|
har.SetProfile(har2caseProfilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify profile
|
||||||
|
if har2casePatchPath != "" {
|
||||||
|
har.SetPatch(har2casePatchPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate json/yaml files
|
// generate json/yaml files
|
||||||
if genYAMLFlag {
|
if har2caseGenYAMLFlag {
|
||||||
outputPath, err = har.GenYAML()
|
outputPath, err = har.GenYAML()
|
||||||
} else {
|
} else {
|
||||||
outputPath, err = har.GenJSON() // default
|
outputPath, err = har.GenJSON() // default
|
||||||
@@ -57,16 +62,18 @@ var har2caseCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
genJSONFlag bool
|
har2caseGenJSONFlag bool
|
||||||
genYAMLFlag bool
|
har2caseGenYAMLFlag bool
|
||||||
outputDir string
|
har2caseOutputDir string
|
||||||
profilePath string
|
har2caseProfilePath string
|
||||||
|
har2casePatchPath string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(har2caseCmd)
|
rootCmd.AddCommand(har2caseCmd)
|
||||||
har2caseCmd.Flags().BoolVarP(&genJSONFlag, "to-json", "j", true, "convert to JSON format")
|
har2caseCmd.Flags().BoolVarP(&har2caseGenJSONFlag, "to-json", "j", true, "convert to JSON format")
|
||||||
har2caseCmd.Flags().BoolVarP(&genYAMLFlag, "to-yaml", "y", false, "convert to YAML format")
|
har2caseCmd.Flags().BoolVarP(&har2caseGenYAMLFlag, "to-yaml", "y", false, "convert to YAML format")
|
||||||
har2caseCmd.Flags().StringVarP(&outputDir, "output-dir", "d", "", "specify output directory, default to the same dir with har file")
|
har2caseCmd.Flags().StringVarP(&har2caseOutputDir, "output-dir", "d", "", "specify output directory, default to the same dir with har file")
|
||||||
har2caseCmd.Flags().StringVarP(&profilePath, "profile", "p", "", "specify profile path to override headers and cookies")
|
har2caseCmd.Flags().StringVarP(&har2caseProfilePath, "profile", "p", "", "specify profile path to override headers and cookies")
|
||||||
|
har2caseCmd.Flags().StringVarP(&har2casePatchPath, "patch", "r", "", "specify the path of the file used to replace headers and cookies")
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-14
@@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/postman2case"
|
"github.com/httprunner/httprunner/v4/hrp/internal/convert/postman2case"
|
||||||
)
|
)
|
||||||
|
|
||||||
// postman2caseCmd represents the postman2case command
|
// postman2caseCmd represents the postman2case command
|
||||||
@@ -22,24 +22,34 @@ var postman2caseCmd = &cobra.Command{
|
|||||||
var outputFiles []string
|
var outputFiles []string
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
// must choose one
|
// must choose one
|
||||||
if !postman2JSONFlag && !postman2YAMLFlag {
|
if !postman2caseGenJSONFlag && !postman2caseGenYAMLFlag {
|
||||||
return errors.New("please select convert format type")
|
return errors.New("please select convert format type")
|
||||||
}
|
}
|
||||||
var outputPath string
|
var outputPath string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
postman := postman2case.NewCollection(arg)
|
collection := postman2case.NewCollection(arg)
|
||||||
|
|
||||||
// specify output dir
|
// specify output dir
|
||||||
if postman2Dir != "" {
|
if postman2caseOutputDir != "" {
|
||||||
postman.SetOutputDir(postman2Dir)
|
collection.SetOutputDir(postman2caseOutputDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify profile path
|
||||||
|
if postman2caseProfilePath != "" {
|
||||||
|
collection.SetProfile(postman2caseProfilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify patch path
|
||||||
|
if postman2casePatchPath != "" {
|
||||||
|
collection.SetPatch(postman2casePatchPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate json/yaml files
|
// generate json/yaml files
|
||||||
if genYAMLFlag {
|
if postman2caseGenYAMLFlag {
|
||||||
outputPath, err = postman.GenYAML()
|
outputPath, err = collection.GenYAML()
|
||||||
} else {
|
} else {
|
||||||
outputPath, err = postman.GenJSON() // default
|
outputPath, err = collection.GenJSON() // default
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -52,14 +62,18 @@ var postman2caseCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
postman2JSONFlag bool
|
postman2caseGenJSONFlag bool
|
||||||
postman2YAMLFlag bool
|
postman2caseGenYAMLFlag bool
|
||||||
postman2Dir string
|
postman2caseOutputDir string
|
||||||
|
postman2caseProfilePath string
|
||||||
|
postman2casePatchPath string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(postman2caseCmd)
|
rootCmd.AddCommand(postman2caseCmd)
|
||||||
postman2caseCmd.Flags().BoolVarP(&postman2JSONFlag, "to-json", "j", true, "convert to JSON format")
|
postman2caseCmd.Flags().BoolVarP(&postman2caseGenJSONFlag, "to-json", "j", true, "convert to JSON format")
|
||||||
postman2caseCmd.Flags().BoolVarP(&postman2YAMLFlag, "to-yaml", "y", false, "convert to YAML format")
|
postman2caseCmd.Flags().BoolVarP(&postman2caseGenYAMLFlag, "to-yaml", "y", false, "convert to YAML format")
|
||||||
postman2caseCmd.Flags().StringVarP(&postman2Dir, "output-dir", "d", "", "specify output directory, default to the same dir with postman collection file")
|
postman2caseCmd.Flags().StringVarP(&postman2caseOutputDir, "output-dir", "d", "", "specify output directory, default to the same dir with postman collection file")
|
||||||
|
postman2caseCmd.Flags().StringVarP(&postman2caseProfilePath, "profile", "p", "", "specify profile path to override original headers (except for Content-Type) and cookies")
|
||||||
|
postman2caseCmd.Flags().StringVarP(&postman2casePatchPath, "patch", "r", "", "specify patch path to create or update headers and cookies")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package convert
|
package case2script
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
@@ -22,6 +22,13 @@ const (
|
|||||||
suffixYAML = ".yaml"
|
suffixYAML = ".yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
configProfile = "profile"
|
||||||
|
configPatch = "patch"
|
||||||
|
keyHeaders = "headers"
|
||||||
|
keyCookies = "cookies"
|
||||||
|
)
|
||||||
|
|
||||||
func NewHAR(path string) *har {
|
func NewHAR(path string) *har {
|
||||||
return &har{
|
return &har{
|
||||||
path: path,
|
path: path,
|
||||||
@@ -33,6 +40,7 @@ type har struct {
|
|||||||
filterStr string
|
filterStr string
|
||||||
excludeStr string
|
excludeStr string
|
||||||
profile map[string]interface{}
|
profile map[string]interface{}
|
||||||
|
patch map[string]interface{}
|
||||||
outputDir string
|
outputDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +54,16 @@ func (h *har) SetProfile(path string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *har) SetPatch(path string) {
|
||||||
|
log.Info().Str("path", path).Msg("set patch")
|
||||||
|
h.patch = make(map[string]interface{})
|
||||||
|
err := builtin.LoadFile(path, h.patch)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Str("path", path).
|
||||||
|
Msg("invalid patch format, ignore!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (h *har) SetOutputDir(dir string) {
|
func (h *har) SetOutputDir(dir string) {
|
||||||
log.Info().Str("dir", dir).Msg("set output directory")
|
log.Info().Str("dir", dir).Msg("set output directory")
|
||||||
h.outputDir = dir
|
h.outputDir = dir
|
||||||
@@ -146,6 +164,7 @@ func (h *har) prepareTestStep(entry *Entry) (*hrp.TStep, error) {
|
|||||||
Validators: make([]interface{}, 0),
|
Validators: make([]interface{}, 0),
|
||||||
},
|
},
|
||||||
profile: h.profile,
|
profile: h.profile,
|
||||||
|
patch: h.patch,
|
||||||
}
|
}
|
||||||
if err := step.makeRequestMethod(entry); err != nil {
|
if err := step.makeRequestMethod(entry); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -174,6 +193,7 @@ func (h *har) prepareTestStep(entry *Entry) (*hrp.TStep, error) {
|
|||||||
type tStep struct {
|
type tStep struct {
|
||||||
hrp.TStep
|
hrp.TStep
|
||||||
profile map[string]interface{}
|
profile map[string]interface{}
|
||||||
|
patch map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *tStep) makeRequestMethod(entry *Entry) error {
|
func (s *tStep) makeRequestMethod(entry *Entry) error {
|
||||||
@@ -199,43 +219,59 @@ func (s *tStep) makeRequestParams(entry *Entry) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *tStep) updateRequestInfo(config string, key string) bool {
|
||||||
|
var m map[string]interface{}
|
||||||
|
switch config {
|
||||||
|
case configProfile:
|
||||||
|
m = s.profile
|
||||||
|
case configPatch:
|
||||||
|
m = s.patch
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
iRequestMap, existed := m[key]
|
||||||
|
if existed {
|
||||||
|
requestMap, ok := iRequestMap.(map[string]interface{})
|
||||||
|
if ok {
|
||||||
|
for k, v := range requestMap {
|
||||||
|
switch key {
|
||||||
|
case keyHeaders:
|
||||||
|
s.Request.Headers[k] = fmt.Sprintf("%v", v)
|
||||||
|
case keyCookies:
|
||||||
|
s.Request.Cookies[k] = fmt.Sprintf("%v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
log.Warn().Interface(key, iRequestMap).Msgf("%v from %v is not a map, ignore!", key, config)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (s *tStep) makeRequestCookies(entry *Entry) error {
|
func (s *tStep) makeRequestCookies(entry *Entry) error {
|
||||||
s.Request.Cookies = make(map[string]string)
|
s.Request.Cookies = make(map[string]string)
|
||||||
cookies, ok := s.profile["cookies"]
|
|
||||||
if ok {
|
// override all cookies according to the profile
|
||||||
// use cookies from profile
|
if s.updateRequestInfo(configProfile, keyCookies) {
|
||||||
cookies, ok := cookies.(map[string]interface{})
|
return nil
|
||||||
if ok {
|
|
||||||
for k, v := range cookies {
|
|
||||||
s.Request.Cookies[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
log.Warn().Interface("cookies", cookies).
|
|
||||||
Msg("cookies from profile is not a map, ignore!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// use cookies from har
|
// use cookies from har
|
||||||
for _, cookie := range entry.Request.Cookies {
|
for _, cookie := range entry.Request.Cookies {
|
||||||
s.Request.Cookies[cookie.Name] = cookie.Value
|
s.Request.Cookies[cookie.Name] = cookie.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create or update the cookies indicated in the patch
|
||||||
|
s.updateRequestInfo(configPatch, keyCookies)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *tStep) makeRequestHeaders(entry *Entry) error {
|
func (s *tStep) makeRequestHeaders(entry *Entry) error {
|
||||||
s.Request.Headers = make(map[string]string)
|
s.Request.Headers = make(map[string]string)
|
||||||
headers, ok := s.profile["headers"]
|
|
||||||
if ok {
|
// override all headers according to the profile
|
||||||
// use headers from profile
|
if s.updateRequestInfo(configProfile, keyHeaders) {
|
||||||
cookies, ok := headers.(map[string]interface{})
|
return nil
|
||||||
if ok {
|
|
||||||
for k, v := range cookies {
|
|
||||||
s.Request.Headers[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
log.Warn().Interface("headers", headers).
|
|
||||||
Msg("headers from profile is not a map, ignore!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// use headers from har
|
// use headers from har
|
||||||
@@ -245,6 +281,9 @@ func (s *tStep) makeRequestHeaders(entry *Entry) error {
|
|||||||
}
|
}
|
||||||
s.Request.Headers[header.Name] = header.Value
|
s.Request.Headers[header.Name] = header.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create or update the headers indicated in the patch
|
||||||
|
s.updateRequestInfo(configPatch, keyHeaders)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package har2case
|
package har2case
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -9,9 +10,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
harPath = "../../../examples/data/har/demo.har"
|
harPath = "../../../../examples/data/har/demo.har"
|
||||||
harPath2 = "../../../examples/data/har/postman-echo.har"
|
harPath2 = "../../../../examples/data/har/postman-echo.har"
|
||||||
profilePath = "../../../examples/data/har/profile.yml"
|
profilePath = "../../../../examples/data/har/profile.yml"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGenJSON(t *testing.T) {
|
func TestGenJSON(t *testing.T) {
|
||||||
@@ -381,3 +382,32 @@ func TestMakeValidate(t *testing.T) {
|
|||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_tStep_makeRequestCookies(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
TStep hrp.TStep
|
||||||
|
profile map[string]interface{}
|
||||||
|
patch map[string]interface{}
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
entry *Entry
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
wantErr assert.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
s := &tStep{
|
||||||
|
TStep: tt.fields.TStep,
|
||||||
|
profile: tt.fields.profile,
|
||||||
|
patch: tt.fields.patch,
|
||||||
|
}
|
||||||
|
tt.wantErr(t, s.makeRequestCookies(tt.args.entry), fmt.Sprintf("makeRequestCookies(%v)", tt.args.entry))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package postman2case
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/json"
|
|
||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -17,6 +16,7 @@ import (
|
|||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp"
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -33,11 +33,18 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
suffixName = ".converted"
|
suffixName = ".converted" // distinguish the converted json(testcase) from the origin json(collection)
|
||||||
extensionJSON = ".json"
|
extensionJSON = ".json"
|
||||||
extensionYAML = ".yaml"
|
extensionYAML = ".yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
configProfile = "profile"
|
||||||
|
configPatch = "patch"
|
||||||
|
keyHeaders = "headers"
|
||||||
|
keyCookies = "cookies"
|
||||||
|
)
|
||||||
|
|
||||||
var contentTypeMap = map[string]string{
|
var contentTypeMap = map[string]string{
|
||||||
"text": "text/plain",
|
"text": "text/plain",
|
||||||
"javascript": "application/javascript",
|
"javascript": "application/javascript",
|
||||||
@@ -54,9 +61,31 @@ func NewCollection(path string) *collection {
|
|||||||
|
|
||||||
type collection struct {
|
type collection struct {
|
||||||
path string
|
path string
|
||||||
|
profile map[string]interface{}
|
||||||
|
patch map[string]interface{}
|
||||||
outputDir string
|
outputDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *collection) SetProfile(path string) {
|
||||||
|
log.Info().Str("path", path).Msg("set profile")
|
||||||
|
c.profile = make(map[string]interface{})
|
||||||
|
err := builtin.LoadFile(path, c.profile)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Str("path", path).
|
||||||
|
Msg("invalid profile format, ignore!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *collection) SetPatch(path string) {
|
||||||
|
log.Info().Str("path", path).Msg("set patch")
|
||||||
|
c.patch = make(map[string]interface{})
|
||||||
|
err := builtin.LoadFile(path, c.patch)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Str("path", path).
|
||||||
|
Msg("invalid patch format, ignore!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *collection) SetOutputDir(dir string) {
|
func (c *collection) SetOutputDir(dir string) {
|
||||||
log.Info().Str("dir", dir).Msg("set output directory")
|
log.Info().Str("dir", dir).Msg("set output directory")
|
||||||
c.outputDir = dir
|
c.outputDir = dir
|
||||||
@@ -169,10 +198,12 @@ func (c *collection) prepareTestStep(item *TItem) (*hrp.TStep, error) {
|
|||||||
Msg("convert teststep")
|
Msg("convert teststep")
|
||||||
|
|
||||||
step := &tStep{
|
step := &tStep{
|
||||||
hrp.TStep{
|
TStep: hrp.TStep{
|
||||||
Request: &hrp.Request{},
|
Request: &hrp.Request{},
|
||||||
Validators: make([]interface{}, 0),
|
Validators: make([]interface{}, 0),
|
||||||
},
|
},
|
||||||
|
profile: c.profile,
|
||||||
|
patch: c.patch,
|
||||||
}
|
}
|
||||||
if err := step.makeRequestName(item); err != nil {
|
if err := step.makeRequestName(item); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -186,20 +217,22 @@ func (c *collection) prepareTestStep(item *TItem) (*hrp.TStep, error) {
|
|||||||
if err := step.makeRequestParams(item); err != nil {
|
if err := step.makeRequestParams(item); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := step.makeRequestHeadersAndCookies(item); err != nil {
|
if err := step.makeRequestHeaders(item); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := step.makeRequestCookies(item); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := step.makeRequestBody(item); err != nil {
|
if err := step.makeRequestBody(item); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := step.makeValidate(item); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &step.TStep, nil
|
return &step.TStep, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type tStep struct {
|
type tStep struct {
|
||||||
hrp.TStep
|
hrp.TStep
|
||||||
|
profile map[string]interface{}
|
||||||
|
patch map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeRequestName indicates the step name the same as item name
|
// makeRequestName indicates the step name the same as item name
|
||||||
@@ -239,21 +272,89 @@ func (s *tStep) makeRequestParams(item *TItem) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *tStep) makeRequestHeadersAndCookies(item *TItem) error {
|
func (s *tStep) updateRequestInfo(config string, key string) bool {
|
||||||
s.Request.Headers = make(map[string]string)
|
var m map[string]interface{}
|
||||||
for _, field := range item.Request.Headers {
|
switch config {
|
||||||
if field.Disabled {
|
case configProfile:
|
||||||
continue
|
m = s.profile
|
||||||
|
case configPatch:
|
||||||
|
m = s.patch
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
iRequestMap, existed := m[key]
|
||||||
|
if existed {
|
||||||
|
requestMap, ok := iRequestMap.(map[string]interface{})
|
||||||
|
if ok {
|
||||||
|
for k, v := range requestMap {
|
||||||
|
switch key {
|
||||||
|
case keyHeaders:
|
||||||
|
s.Request.Headers[k] = fmt.Sprintf("%v", v)
|
||||||
|
case keyCookies:
|
||||||
|
s.Request.Cookies[k] = fmt.Sprintf("%v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
if strings.EqualFold(field.Key, "cookie") {
|
log.Warn().Interface(key, iRequestMap).Msgf("%v from %v is not a map, ignore!", key, config)
|
||||||
s.Request.Cookies[field.Key] = field.Value
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *tStep) makeRequestHeaders(item *TItem) error {
|
||||||
|
s.Request.Headers = make(map[string]string)
|
||||||
|
|
||||||
|
// override all headers according to the profile
|
||||||
|
if s.updateRequestInfo(configProfile, keyHeaders) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// headers defined in postman collection
|
||||||
|
for _, field := range item.Request.Headers {
|
||||||
|
if field.Disabled || strings.EqualFold(field.Key, "cookie") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s.Request.Headers[field.Key] = field.Value
|
s.Request.Headers[field.Key] = field.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create or update the headers indicated in the patch
|
||||||
|
s.updateRequestInfo(configPatch, keyHeaders)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *tStep) makeRequestCookies(item *TItem) error {
|
||||||
|
s.Request.Cookies = make(map[string]string)
|
||||||
|
|
||||||
|
// override all cookies according to the profile
|
||||||
|
if s.updateRequestInfo(configProfile, keyCookies) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// cookies defined in postman collection
|
||||||
|
for _, field := range item.Request.Headers {
|
||||||
|
if field.Disabled || !strings.EqualFold(field.Key, "cookie") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.parseRequestCookiesMap(field.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create or update the cookies indicated in the patch
|
||||||
|
s.updateRequestInfo(configPatch, keyCookies)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *tStep) parseRequestCookiesMap(cookies string) {
|
||||||
|
for _, cookie := range strings.Split(cookies, ";") {
|
||||||
|
cookie = strings.TrimSpace(cookie)
|
||||||
|
index := strings.Index(cookie, "=")
|
||||||
|
if index == -1 {
|
||||||
|
log.Warn().Str("cookie", cookie).Msg("cookie format invalid")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.Request.Cookies[cookie[0:index]] = cookie[index+1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *tStep) makeRequestBody(item *TItem) error {
|
func (s *tStep) makeRequestBody(item *TItem) error {
|
||||||
mode := item.Request.Body.Mode
|
mode := item.Request.Body.Mode
|
||||||
if mode == "" {
|
if mode == "" {
|
||||||
@@ -267,7 +368,7 @@ func (s *tStep) makeRequestBody(item *TItem) error {
|
|||||||
case enumBodyUrlEncoded:
|
case enumBodyUrlEncoded:
|
||||||
return s.makeRequestBodyUrlEncoded(item)
|
return s.makeRequestBodyUrlEncoded(item)
|
||||||
case enumBodyFile, enumBodyGraphQL:
|
case enumBodyFile, enumBodyGraphQL:
|
||||||
return errors.New("not supported body type")
|
return errors.Errorf("unsupported body type: %v", mode)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
package postman2case
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
collectionPath = "../../../../examples/data/postman2case/demo.json"
|
||||||
|
profilePath = "../../../../examples/data/postman2case/profile.yml"
|
||||||
|
patchPath = "../../../../examples/data/postman2case/patch.yml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGenJSON(t *testing.T) {
|
||||||
|
jsonPath, err := NewCollection(collectionPath).GenJSON()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.NotEmpty(t, jsonPath) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenYAML(t *testing.T) {
|
||||||
|
yamlPath, err := NewCollection(collectionPath).GenYAML()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.NotEmpty(t, yamlPath) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadCollection(t *testing.T) {
|
||||||
|
tCollection, err := NewCollection(collectionPath).load()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, "postman collection demo", tCollection.Info.Name) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMakeTestCase(t *testing.T) {
|
||||||
|
tCase, err := NewCollection(collectionPath).makeTestCase()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
// check name
|
||||||
|
if !assert.Equal(t, "postman collection demo", tCase.Config.Name) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
// check method
|
||||||
|
if !assert.EqualValues(t, "GET", tCase.TestSteps[0].Request.Method) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.EqualValues(t, "POST", tCase.TestSteps[1].Request.Method) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
// check url
|
||||||
|
if !assert.Equal(t, "https://postman-echo.com/get", tCase.TestSteps[0].Request.URL) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, "https://postman-echo.com/post", tCase.TestSteps[1].Request.URL) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
// check params
|
||||||
|
if !assert.Equal(t, "v1", tCase.TestSteps[0].Request.Params["k1"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
// check cookies (pass, postman collection doesn't contains cookies)
|
||||||
|
// check headers
|
||||||
|
if !assert.Contains(t, tCase.TestSteps[1].Request.Headers["Content-Type"], "multipart/form-data") {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, "application/x-www-form-urlencoded", tCase.TestSteps[2].Request.Headers["Content-Type"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, "application/json", tCase.TestSteps[3].Request.Headers["Content-Type"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, "text/plain", tCase.TestSteps[4].Request.Headers["Content-Type"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, "HttpRunner", tCase.TestSteps[5].Request.Headers["User-Agent"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
// check body
|
||||||
|
if !assert.Equal(t, nil, tCase.TestSteps[0].Request.Body) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.NotEmpty(t, tCase.TestSteps[1].Request.Body) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, map[string]string{"k1": "v1", "k2": "v2"}, tCase.TestSteps[2].Request.Body) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, map[string]interface{}{"k1": "v1", "k2": "v2"}, tCase.TestSteps[3].Request.Body) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, "have a nice day", tCase.TestSteps[4].Request.Body) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, nil, tCase.TestSteps[5].Request.Body) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMakeTestCaseWithProfile(t *testing.T) {
|
||||||
|
c := NewCollection(collectionPath)
|
||||||
|
c.SetProfile(profilePath)
|
||||||
|
tCase, err := c.makeTestCase()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
for _, step := range tCase.TestSteps {
|
||||||
|
if step.Request.Method == "GET" && !assert.Len(t, step.Request.Headers, 1) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if step.Request.Method == "POST" && !assert.Len(t, step.Request.Headers, 2) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, "all original headers will be overridden", step.Request.Headers["Header1"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Len(t, step.Request.Cookies, 1) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, "all original cookies will be overridden", step.Request.Cookies["Cookie1"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMakeTestCaseWithPatch(t *testing.T) {
|
||||||
|
c := NewCollection(collectionPath)
|
||||||
|
c.SetPatch(patchPath)
|
||||||
|
tCase, err := c.makeTestCase()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
// create cookies Cookie1 indicated in patch
|
||||||
|
if !assert.Equal(t, "this cookie will be created or updated", tCase.TestSteps[0].Request.Cookies["Cookie1"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
// update header User-Agent indicated in patch
|
||||||
|
if !assert.Equal(t, "this header will be created or updated", tCase.TestSteps[5].Request.Headers["User-Agent"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
// pass header Connection which is not indicated in patch
|
||||||
|
if !assert.Equal(t, "close", tCase.TestSteps[5].Request.Headers["Connection"]) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package postman2case
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
var collectionPath = "../../../examples/data/postman2case/postman_collection.json"
|
|
||||||
|
|
||||||
func TestLoadPostmanCollection(t *testing.T) {
|
|
||||||
c, err := NewCollection(collectionPath).load()
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !assert.Equal(t, "postman collection demo", c.Info.Name) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGenJSON(t *testing.T) {
|
|
||||||
jsonPath, err := NewCollection(collectionPath).GenJSON()
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
if !assert.NotEmpty(t, jsonPath) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGenYAML(t *testing.T) {
|
|
||||||
yamlPath, err := NewCollection(collectionPath).GenYAML()
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
if !assert.NotEmpty(t, yamlPath) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user