diff --git a/main.go b/main.go index d35c0f2..e0ffb88 100644 --- a/main.go +++ b/main.go @@ -43,6 +43,8 @@ func main() { os.Exit(2) } + prepareResponseBody(&t) + url := opts.URL if opts.Port != 0 { url = fmt.Sprintf("%s:%d", url, opts.Port) @@ -81,3 +83,14 @@ func unmarshal(filename string, in []byte, out interface{}) error { return unmarshalError } + +// In order to keep retro compatibility with ExpectedResponseBody, and at the same time introducing multiple response check with ExpectedResponse +func prepareResponseBody(t *tester.Test) { + if t != nil && t.Contracts != nil && len(t.Contracts) > 0 { + for _, c := range t.Contracts { + if c.ExpectedResponseBody != "" { + c.ExpectedResponses = append(c.ExpectedResponses, c.ExpectedResponseBody) + } + } + } +} diff --git a/smoke_test.json b/smoke_test.json index ff71c5c..9bc87e8 100644 --- a/smoke_test.json +++ b/smoke_test.json @@ -182,6 +182,22 @@ "method": "GET", "response_headers_is": {"My-Header": "found", "My-Header2": "foundToo"} + }, + { + "name": "httpbin_get_body_multiple", + "path": "/get?foo=hello!", + "method": "GET", + + + "response_contains": ["hello", "foo", "!"] + }, + { + "name": "httpbin_get_response_multiple", + "path": "/get?foo=hello!", + "method": "GET", + + "response_body_contains": "hello", + "response_contains": ["foo", "!"] } ] } \ No newline at end of file diff --git a/smoke_test.yaml b/smoke_test.yaml index 86ece3e..af0be50 100644 --- a/smoke_test.yaml +++ b/smoke_test.yaml @@ -164,3 +164,22 @@ contracts: response_headers_is: My-Header: "found" My-Header2: "foundToo" + +- name: httpbin_get_body_multiple + path: "/get?foo=hello!" + method: GET + + response_body_contains: hello + response_contains: + - foo + - ! + +- name: httpbin_get_response_multiple + path: "/get?foo=hello!" + method: GET + + response_contains: + - hello + - foo + - ! + diff --git a/tester/tester.go b/tester/tester.go index d0a0ba7..fc390c3 100644 --- a/tester/tester.go +++ b/tester/tester.go @@ -39,9 +39,11 @@ type Contract struct { ExpectedHTTPCode int `json:"http_code_is" yaml:"http_code_is"` ExpectedResponseBody string `json:"response_body_contains" yaml:"response_body_contains"` + ExpectedResponses []string `json:"response_contains" yaml:"response_contains"` ExpectedHeaders map[string]string `json:"response_headers_is" yaml:"response_headers_is"` } + // Test represents the data for a full test suite type Test struct { Globals map[string]string `json:"globals" yaml:"globals"` @@ -141,7 +143,7 @@ func (runner *Runner) validateContract(contract Contract) (err error) { } } - if contract.ExpectedResponseBody != "" || (contract.Outputs != nil && len(contract.Outputs) > 0) { + if len(contract.ExpectedResponses) > 0 || (contract.Outputs != nil && len(contract.Outputs) > 0) { body, err := ioutil.ReadAll(resp.Body) if err != nil { return err @@ -201,25 +203,25 @@ func validateHTTPCode(contract Contract, resp *http.Response) error { } func validateResponseBody(contract Contract, body []byte) error { - if contract.ExpectedResponseBody == "" { + if len(contract.ExpectedResponses) == 0 { return nil } - - if strings.HasPrefix(contract.ExpectedResponseBody, "r/") { - expectedRegexp := contract.ExpectedResponseBody[2:] - re, err := regexp.Compile(expectedRegexp) - if err == nil { - if !re.Match(body) { - return fmt.Errorf("regular expression did not find any matches in the response body") + + for _, r := range contract.ExpectedResponses { + // check if it is a regexp + if strings.HasPrefix(r, "r/") { + expectedRegexp := r[2:] + re, err := regexp.Compile(expectedRegexp) + if err == nil { + if !re.Match(body) { + return fmt.Errorf("regular expression did not find any matches in the response body") + } } - return nil + } else if !bytes.Contains(body, []byte(r)) { + return fmt.Errorf("expected response not found in the body") } } - - if !bytes.Contains(body, []byte(contract.ExpectedResponseBody)) { - return fmt.Errorf("expected response not found in the body") - } - + return nil }