diff --git a/go.mod b/go.mod index c7cfc1b5..f275a22e 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/maja42/goval v1.2.1 github.com/myzhan/boomer v1.6.0 github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/shirou/gopsutil v3.21.8+incompatible // indirect github.com/spf13/cobra v1.2.1 github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 990fc21b..05e632a4 100644 --- a/go.sum +++ b/go.sum @@ -214,6 +214,8 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= diff --git a/har2case/core.go b/har2case/core.go index d16f1342..ad0465e6 100644 --- a/har2case/core.go +++ b/har2case/core.go @@ -1,6 +1,7 @@ package har2case import ( + "encoding/base64" "encoding/json" "fmt" "io/ioutil" @@ -11,6 +12,7 @@ import ( "strings" "github.com/httprunner/httpboomer" + "github.com/pkg/errors" ) func NewHAR(path string) *HAR { @@ -132,7 +134,7 @@ func (h *HAR) prepareTestStep(entry *Entry) (*httpboomer.TStep, error) { if err := tStep.makeRequestBody(entry); err != nil { return nil, err } - if err := tStep.makeValidate(); err != nil { + if err := tStep.makeValidate(entry); err != nil { return nil, err } return &tStep.TStep, nil @@ -187,6 +189,12 @@ func (s *TStep) makeRequestHeaders(entry *Entry) error { func (s *TStep) makeRequestBody(entry *Entry) error { mimeType := entry.Request.PostData.MimeType + if mimeType == "" { + // GET/HEAD/DELETE without body + return nil + } + + // POST/PUT with body if strings.HasPrefix(mimeType, "application/json") { // post json var body interface{} @@ -203,12 +211,78 @@ func (s *TStep) makeRequestBody(entry *Entry) error { paramsList = append(paramsList, fmt.Sprintf("%s=%s", param.Name, param.Value)) } s.Request.Body = strings.Join(paramsList, "&") + } else { + // TODO + log.Fatalf("makeRequestBody: NotImplemented for mimeType %s", mimeType) } return nil } -func (s *TStep) makeValidate() error { - s.Validators = nil +func (s *TStep) makeValidate(entry *Entry) error { + // make validator for response status code + s.Validators = append(s.Validators, httpboomer.TValidator{ + Check: "status_code", + Assert: "equals", + Expect: entry.Response.Status, + Message: "assert response status code", + }) + + // make validators for response headers + for _, header := range entry.Response.Headers { + // assert Content-Type + if strings.EqualFold(header.Name, "Content-Type") { + s.Validators = append(s.Validators, httpboomer.TValidator{ + Check: "headers.Content-Type", + Assert: "equals", + Expect: header.Value, + Message: "assert response header Content-Type", + }) + } + } + + // make validators for response body + respBody := entry.Response.Content + if respBody.Text == "" { + // response body is empty + return nil + } + if strings.HasPrefix(respBody.MimeType, "application/json") { + // response body is json + if respBody.Encoding == "base64" { + // decode base64 text + data, err := base64.StdEncoding.DecodeString(respBody.Text) + if err != nil { + return errors.Wrap(err, "decode base64 error") + } + + // convert to json + var body interface{} + if err = json.Unmarshal(data, &body); err != nil { + return errors.Wrap(err, "json.Unmarshal body error") + } + if _, ok := body.(map[string]interface{}); !ok { + return fmt.Errorf("response body is not json, not matched with MimeType") + } + + // response body is json + for key, value := range body.(map[string]interface{}) { + switch v := value.(type) { + case map[string]interface{}: + continue + case []interface{}: + continue + default: + s.Validators = append(s.Validators, httpboomer.TValidator{ + Check: fmt.Sprintf("body.%s", key), + Assert: "equals", + Expect: v, + Message: fmt.Sprintf("assert response body %s", key), + }) + } + } + } + } + return nil }