diff --git a/assert.go b/assert.go index 6800dd4..3b3999a 100644 --- a/assert.go +++ b/assert.go @@ -1,6 +1,7 @@ package abide import ( + "encoding/hex" "encoding/json" "fmt" "io" @@ -14,6 +15,28 @@ import ( "github.com/sergi/go-diff/diffmatchpatch" ) +// ContentType expected response body type. +type ContentType string + +// ContentType possible values. +const ( + ContentTypeJSON ContentType = "json" + ContentTypeText ContentType = "text" + ContentTypeBinary ContentType = "binary" +) + +// SetContentType define the response type in the options. +func SetContentType(typ ContentType) func(*AssertOptions) { + return func(options *AssertOptions) { + options.ContentType = typ + } +} + +// AssertOptions possible options for the assert. +type AssertOptions struct { + ContentType ContentType +} + // Assertable represents an object that can be asserted. type Assertable interface { String() string @@ -26,46 +49,82 @@ func Assert(t *testing.T, id string, a Assertable) { } // AssertHTTPResponse asserts the value of an http.Response. -func AssertHTTPResponse(t *testing.T, id string, w *http.Response) { +func AssertHTTPResponse(t *testing.T, id string, w *http.Response, opts ...func(*AssertOptions)) { + options := &AssertOptions{} + for _, opt := range opts { + opt(options) + } + body, err := httputil.DumpResponse(w, true) if err != nil { t.Fatal(err) } - assertHTTP(t, id, body, contentTypeIsJSON(w.Header.Get("Content-Type"))) + // keep backward compatibility checking for JSON type when the response type + // wasn't provided + if options.ContentType == ContentType("") && contentTypeIsJSON(w.Header.Get("Content-Type")) { + options.ContentType = ContentTypeJSON + } + assertHTTP(t, id, body, options.ContentType) } // AssertHTTPRequestOut asserts the value of an http.Request. // Intended for use when testing outgoing client requests // See https://golang.org/pkg/net/http/httputil/#DumpRequestOut for more -func AssertHTTPRequestOut(t *testing.T, id string, r *http.Request) { +func AssertHTTPRequestOut(t *testing.T, id string, r *http.Request, opts ...func(*AssertOptions)) { + options := &AssertOptions{} + for _, opt := range opts { + opt(options) + } + body, err := httputil.DumpRequestOut(r, true) if err != nil { t.Fatal(err) } - assertHTTP(t, id, body, contentTypeIsJSON(r.Header.Get("Content-Type"))) + // keep backward compatibility checking for JSON type when the content type + // wasn't provided + if options.ContentType == ContentType("") && contentTypeIsJSON(r.Header.Get("Content-Type")) { + options.ContentType = ContentTypeJSON + } + assertHTTP(t, id, body, options.ContentType) } // AssertHTTPRequest asserts the value of an http.Request. // Intended for use when testing incoming client requests // See https://golang.org/pkg/net/http/httputil/#DumpRequest for more -func AssertHTTPRequest(t *testing.T, id string, r *http.Request) { +func AssertHTTPRequest(t *testing.T, id string, r *http.Request, opts ...func(*AssertOptions)) { + options := &AssertOptions{} + for _, opt := range opts { + opt(options) + } + body, err := httputil.DumpRequest(r, true) if err != nil { t.Fatal(err) } - assertHTTP(t, id, body, contentTypeIsJSON(r.Header.Get("Content-Type"))) + // keep backward compatibility checking for JSON type when the content type + // wasn't provided + if options.ContentType == ContentType("") && contentTypeIsJSON(r.Header.Get("Content-Type")) { + options.ContentType = ContentTypeJSON + } + assertHTTP(t, id, body, options.ContentType) } -func assertHTTP(t *testing.T, id string, body []byte, isJSON bool) { +func assertHTTP(t *testing.T, id string, body []byte, contentType ContentType) { config, err := getConfig() if err != nil { t.Fatal(err) } - data := string(body) + var data string + if contentType == ContentTypeBinary { + data = hex.EncodeToString(body) + } else { + data = string(body) + } + lines := strings.Split(strings.TrimSpace(data), "\n") if config != nil { @@ -83,7 +142,7 @@ func assertHTTP(t *testing.T, id string, body []byte, isJSON bool) { } // If the response body is JSON, indent. - if isJSON { + if contentType == ContentTypeJSON { jsonStr := lines[len(lines)-1] var jsonIface map[string]interface{} diff --git a/example/__snapshots__/example.snapshot b/example/__snapshots__/example.snapshot index cd96eaa..496ba4c 100755 --- a/example/__snapshots__/example.snapshot +++ b/example/__snapshots__/example.snapshot @@ -4,6 +4,9 @@ main.MyStruct {Field1:String1 Field2:1234567 Field3:true field4:string4} /* snapshot: assertable string */ string to be asserted +/* snapshot: fifth route */ +485454502f312e3120323030204f4b0d0a436f6e6e656374696f6e3a20636c6f73650d0a436f6e74656e742d547970653a206170706c69636174696f6e2f7064660d0a0d0a0102030405060708090a + /* snapshot: first route */ HTTP/1.1 200 OK Connection: close diff --git a/example/main.go b/example/main.go index c3f76eb..10d2eb0 100644 --- a/example/main.go +++ b/example/main.go @@ -61,10 +61,16 @@ func fourthHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`Hello World.`)) } +func fifthHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/pdf") + w.Write([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) +} + func main() { http.HandleFunc("/first", firstHandler) http.HandleFunc("/second", secondHandler) http.HandleFunc("/third", thirdHandler) http.HandleFunc("/fourth", fourthHandler) + http.HandleFunc("/fifth", fifthHandler) http.ListenAndServe(":8080", nil) } diff --git a/example/main_test.go b/example/main_test.go index 7d1a24d..0a4b791 100644 --- a/example/main_test.go +++ b/example/main_test.go @@ -34,6 +34,12 @@ func TestRequests(t *testing.T) { thirdHandler(w, req) res = w.Result() abide.AssertHTTPResponse(t, "third route", res) + + req = httptest.NewRequest("GET", "http://example.com/", nil) + w = httptest.NewRecorder() + fifthHandler(w, req) + res = w.Result() + abide.AssertHTTPResponse(t, "fifth route", res, abide.SetContentType(abide.ContentTypeBinary)) } func TestReader(t *testing.T) {