package httpexpect import ( "bytes" "encoding/json" "errors" "io/ioutil" "mime" "mime/multipart" "net/http" "os" "strings" "testing" "github.com/stretchr/testify/assert" ) func TestRequestFailed(t *testing.T) { client := &mockClient{} chain := makeChain(newMockReporter(t)) chain.fail("fail") config := Config{ Client: client, } req := &Request{ config: config, chain: chain, http: nil, } req.WithClient(&http.Client{}) req.WithHandler(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) req.WithPath("foo", "bar") req.WithPathObject(map[string]interface{}{"foo": "bar"}) req.WithQuery("foo", "bar") req.WithQueryObject(map[string]interface{}{"foo": "bar"}) req.WithQueryString("foo=bar") req.WithURL("http://example.com") req.WithHeaders(map[string]string{"foo": "bar"}) req.WithHeader("foo", "bar") req.WithCookies(map[string]string{"foo": "bar"}) req.WithCookie("foo", "bar") req.WithBasicAuth("foo", "bar") req.WithProto("HTTP/1.1") req.WithChunked(strings.NewReader("foo")) req.WithBytes([]byte("foo")) req.WithText("foo") req.WithJSON(map[string]string{"foo": "bar"}) req.WithForm(map[string]string{"foo": "bar"}) req.WithFormField("foo", "bar") req.WithFile("foo", "bar", strings.NewReader("baz")) req.WithFileBytes("foo", "bar", []byte("baz")) req.WithMultipart() resp := req.Expect() assert.False(t, resp == nil) req.chain.assertFailed(t) resp.chain.assertFailed(t) } func TestRequestEmpty(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "", "") resp := req.Expect() req.chain.assertOK(t) resp.chain.assertOK(t) } func TestRequestTime(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } for n := 0; n < 10; n++ { req := NewRequest(config, "", "") resp := req.Expect() assert.True(t, resp.time >= 0) } } func TestRequestClient(t *testing.T) { factory := DefaultRequestFactory{} client1 := &mockClient{} client2 := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Reporter: reporter, Client: client1, } req1 := NewRequest(config, "METHOD", "/") req1.Expect().chain.assertOK(t) assert.NotNil(t, client1.req) req2 := NewRequest(config, "METHOD", "/") req2.WithClient(client2) req2.Expect().chain.assertOK(t) assert.NotNil(t, client2.req) req3 := NewRequest(config, "METHOD", "/") req3.WithClient(nil) req3.chain.assertFailed(t) } func TestRequestHandler(t *testing.T) { factory := DefaultRequestFactory{} var hr1 *http.Request handler1 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { hr1 = r }) var hr2 *http.Request handler2 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { hr2 = r }) reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Reporter: reporter, Client: &http.Client{ Transport: NewBinder(handler1), }, } req1 := NewRequest(config, "METHOD", "/") req1.Expect().chain.assertOK(t) assert.NotNil(t, hr1) req2 := NewRequest(config, "METHOD", "/") req2.WithHandler(handler2) req2.Expect().chain.assertOK(t) assert.NotNil(t, hr2) req3 := NewRequest(config, "METHOD", "/") req3.WithHandler(nil) req3.chain.assertFailed(t) } func TestRequestHandlerResetClient(t *testing.T) { factory := DefaultRequestFactory{} var hr *http.Request handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { hr = r }) client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Reporter: reporter, Client: client, } req := NewRequest(config, "METHOD", "/") req.WithHandler(handler) req.Expect().chain.assertOK(t) assert.NotNil(t, hr) assert.Nil(t, client.req) } func TestRequestHandlerResueClient(t *testing.T) { factory := DefaultRequestFactory{} handler1 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) handler2 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) client := &http.Client{ Transport: NewBinder(handler1), Jar: NewJar(), } reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Reporter: reporter, Client: client, } req := NewRequest(config, "METHOD", "/") req.WithHandler(handler2) assert.True(t, req.config.Client.(*http.Client).Jar == client.Jar) } func TestRequestProto(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "/") assert.Equal(t, 1, req.http.ProtoMajor) assert.Equal(t, 1, req.http.ProtoMinor) req.WithProto("HTTP/2.0") assert.Equal(t, 2, req.http.ProtoMajor) assert.Equal(t, 0, req.http.ProtoMinor) req.WithProto("HTTP/1.0") assert.Equal(t, 1, req.http.ProtoMajor) assert.Equal(t, 0, req.http.ProtoMinor) req.WithProto("bad") req.chain.assertFailed(t) assert.Equal(t, 1, req.http.ProtoMajor) assert.Equal(t, 0, req.http.ProtoMinor) } func TestRequestURLConcatenate(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := NewAssertReporter(t) config1 := Config{ RequestFactory: factory, BaseURL: "", Client: client, Reporter: reporter, } config2 := Config{ RequestFactory: factory, BaseURL: "http://example.com", Client: client, Reporter: reporter, } config3 := Config{ RequestFactory: factory, BaseURL: "http://example.com/", Client: client, Reporter: reporter, } reqs := []*Request{ NewRequest(config2, "METHOD", "path"), NewRequest(config2, "METHOD", "/path"), NewRequest(config3, "METHOD", "path"), NewRequest(config3, "METHOD", "/path"), NewRequest(config3, "METHOD", "{arg}", "/path"), NewRequest(config3, "METHOD", "{arg}").WithPath("arg", "/path"), } for _, req := range reqs { req.Expect().chain.assertOK(t) assert.Equal(t, "http://example.com/path", client.req.URL.String()) } empty1 := NewRequest(config1, "METHOD", "") empty2 := NewRequest(config2, "METHOD", "") empty3 := NewRequest(config3, "METHOD", "") empty1.Expect().chain.assertOK(t) empty2.Expect().chain.assertOK(t) empty3.Expect().chain.assertOK(t) assert.Equal(t, "", empty1.http.URL.String()) assert.Equal(t, "http://example.com", empty2.http.URL.String()) assert.Equal(t, "http://example.com/", empty3.http.URL.String()) } func TestRequestURLOverwrite(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := NewAssertReporter(t) config1 := Config{ RequestFactory: factory, BaseURL: "", Client: client, Reporter: reporter, } config2 := Config{ RequestFactory: factory, BaseURL: "http://foobar.com", Client: client, Reporter: reporter, } reqs := []*Request{ NewRequest(config1, "METHOD", "/path").WithURL("http://example.com"), NewRequest(config1, "METHOD", "path").WithURL("http://example.com"), NewRequest(config1, "METHOD", "/path").WithURL("http://example.com/"), NewRequest(config1, "METHOD", "path").WithURL("http://example.com/"), NewRequest(config2, "METHOD", "/path").WithURL("http://example.com"), NewRequest(config2, "METHOD", "path").WithURL("http://example.com"), NewRequest(config2, "METHOD", "/path").WithURL("http://example.com/"), NewRequest(config2, "METHOD", "path").WithURL("http://example.com/"), } for _, req := range reqs { req.Expect().chain.assertOK(t) assert.Equal(t, "http://example.com/path", client.req.URL.String()) } } func TestRequestURLInterpolate(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) var reqs [3]*Request config := Config{ RequestFactory: factory, BaseURL: "http://example.com/", Client: client, Reporter: reporter, } reqs[0] = NewRequest(config, "METHOD", "/foo/{arg}", "bar") reqs[1] = NewRequest(config, "METHOD", "{arg}foo{arg}", "/", "/bar") reqs[2] = NewRequest(config, "METHOD", "{arg}", "/foo/bar") for _, req := range reqs { req.Expect().chain.assertOK(t) assert.Equal(t, "http://example.com/foo/bar", client.req.URL.String()) } r1 := NewRequest(config, "METHOD", "/{arg1}/{arg2}", "foo") r1.Expect().chain.assertOK(t) assert.Equal(t, "http://example.com/foo/%7Barg2%7D", client.req.URL.String()) r2 := NewRequest(config, "METHOD", "/{arg1}/{arg2}/{arg3}") r2.WithPath("ARG3", "foo") r2.WithPath("arg2", "bar") r2.Expect().chain.assertOK(t) assert.Equal(t, "http://example.com/%7Barg1%7D/bar/foo", client.req.URL.String()) r3 := NewRequest(config, "METHOD", "/{arg1}.{arg2}.{arg3}") r3.WithPath("arg2", "bar") r3.WithPathObject(map[string]string{"ARG1": "foo", "arg3": "baz"}) r3.WithPathObject(nil) r3.Expect().chain.assertOK(t) assert.Equal(t, "http://example.com/foo.bar.baz", client.req.URL.String()) type S struct { Arg1 string A2 int `path:"arg2"` A3 int `path:"-"` } r4 := NewRequest(config, "METHOD", "/{arg1}{arg2}") r4.WithPathObject(S{"foo", 1, 2}) r4.Expect().chain.assertOK(t) assert.Equal(t, "http://example.com/foo1", client.req.URL.String()) r5 := NewRequest(config, "METHOD", "/{arg1}{arg2}") r5.WithPathObject(&S{"foo", 1, 2}) r5.Expect().chain.assertOK(t) assert.Equal(t, "http://example.com/foo1", client.req.URL.String()) r6 := NewRequest(config, "GET", "{arg}", nil) r6.chain.assertFailed(t) r7 := NewRequest(config, "GET", "{arg}") r7.chain.assertOK(t) r7.WithPath("arg", nil) r7.chain.assertFailed(t) r8 := NewRequest(config, "GET", "{arg}") r8.chain.assertOK(t) r8.WithPath("bad", "value") r8.chain.assertFailed(t) r9 := NewRequest(config, "GET", "{arg") r9.chain.assertFailed(t) r9.WithPath("arg", "foo") r9.chain.assertFailed(t) r10 := NewRequest(config, "GET", "{arg}") r10.chain.assertOK(t) r10.WithPathObject(func() {}) r10.chain.assertFailed(t) } func TestRequestURLQuery(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, BaseURL: "http://example.com", } req1 := NewRequest(config, "METHOD", "/path"). WithQuery("aa", "foo").WithQuery("bb", 123).WithQuery("cc", "*&@") q := map[string]interface{}{ "bb": 123, "cc": "*&@", } req2 := NewRequest(config, "METHOD", "/path"). WithQuery("aa", "foo"). WithQueryObject(q) type S struct { Bb int `url:"bb"` Cc string `url:"cc"` Dd string `url:"-"` } req3 := NewRequest(config, "METHOD", "/path"). WithQueryObject(S{123, "*&@", "dummy"}).WithQuery("aa", "foo") req4 := NewRequest(config, "METHOD", "/path"). WithQueryObject(&S{123, "*&@", "dummy"}).WithQuery("aa", "foo") req5 := NewRequest(config, "METHOD", "/path"). WithQuery("bb", 123). WithQueryString("aa=foo&cc=%2A%26%40") req6 := NewRequest(config, "METHOD", "/path"). WithQueryString("aa=foo&cc=%2A%26%40"). WithQuery("bb", 123) for _, req := range []*Request{req1, req2, req3, req4, req5, req6} { client.req = nil req.Expect() req.chain.assertOK(t) assert.Equal(t, "http://example.com/path?aa=foo&bb=123&cc=%2A%26%40", client.req.URL.String()) } req7 := NewRequest(config, "METHOD", "/path"). WithQuery("foo", "bar"). WithQueryObject(nil) req7.Expect() req7.chain.assertOK(t) assert.Equal(t, "http://example.com/path?foo=bar", client.req.URL.String()) NewRequest(config, "METHOD", "/path"). WithQueryObject(func() {}).chain.assertFailed(t) NewRequest(config, "METHOD", "/path"). WithQueryString("%").chain.assertFailed(t) } func TestRequestHeaders(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") req.WithHeader("first-header", "foo") req.WithHeaders(map[string]string{ "Second-Header": "bar", "content-Type": "baz", "HOST": "example.com", }) expectedHeaders := map[string][]string{ "First-Header": {"foo"}, "Second-Header": {"bar"}, "Content-Type": {"baz"}, } resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "example.com", client.req.Host) assert.Equal(t, "url", client.req.URL.String()) assert.Equal(t, http.Header(expectedHeaders), client.req.Header) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestCookies(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") req.WithCookie("foo", "1") req.WithCookie("bar", "2 ") req.WithCookies(map[string]string{ "baz": " 3", }) expectedHeaders := map[string][]string{ "Cookie": {`foo=1; bar="2 "; baz=" 3"`}, } resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) assert.Equal(t, http.Header(expectedHeaders), client.req.Header) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestBasicAuth(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") req.WithBasicAuth("Aladdin", "open sesame") req.chain.assertOK(t) assert.Equal(t, "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", req.http.Header.Get("Authorization")) } func TestRequestBodyChunked(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") req.WithChunked(bytes.NewBufferString("body")) resp := req.Expect() resp.chain.assertOK(t) assert.False(t, client.req.Body == nil) assert.Equal(t, int64(-1), client.req.ContentLength) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) assert.Equal(t, make(http.Header), client.req.Header) assert.Equal(t, "body", string(resp.content)) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestBodyChunkedNil(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") req.WithChunked(nil) resp := req.Expect() resp.chain.assertOK(t) assert.True(t, client.req.Body == nil) assert.Equal(t, int64(0), client.req.ContentLength) } func TestRequestBodyChunkedProto(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req1 := NewRequest(config, "METHOD", "url") req1.WithProto("HTTP/1.0") assert.Equal(t, 1, req1.http.ProtoMajor) assert.Equal(t, 0, req1.http.ProtoMinor) req1.WithChunked(bytes.NewBufferString("body")) req1.chain.assertFailed(t) req2 := NewRequest(config, "METHOD", "url") req2.WithProto("HTTP/2.0") assert.Equal(t, 2, req2.http.ProtoMajor) assert.Equal(t, 0, req2.http.ProtoMinor) req2.WithChunked(bytes.NewBufferString("body")) assert.Equal(t, 2, req2.http.ProtoMajor) assert.Equal(t, 0, req2.http.ProtoMinor) } func TestRequestBodyBytes(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "/path") req.WithBytes([]byte("body")) resp := req.Expect() resp.chain.assertOK(t) assert.False(t, client.req.Body == nil) assert.Equal(t, int64(len("body")), client.req.ContentLength) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "/path", client.req.URL.String()) assert.Equal(t, make(http.Header), client.req.Header) assert.Equal(t, "body", string(resp.content)) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestBodyBytesNil(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") req.WithBytes(nil) resp := req.Expect() resp.chain.assertOK(t) assert.True(t, client.req.Body == nil) assert.Equal(t, int64(0), client.req.ContentLength) } func TestRequestBodyText(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } expectedHeaders := map[string][]string{ "Content-Type": {"text/plain; charset=utf-8"}, "Some-Header": {"foo"}, } req := NewRequest(config, "METHOD", "url") req.WithHeaders(map[string]string{ "Some-Header": "foo", }) req.WithText("some text") resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) assert.Equal(t, http.Header(expectedHeaders), client.req.Header) assert.Equal(t, "some text", string(resp.content)) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestBodyForm(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } expectedHeaders := map[string][]string{ "Content-Type": {"application/x-www-form-urlencoded"}, "Some-Header": {"foo"}, } req := NewRequest(config, "METHOD", "url") req.WithHeaders(map[string]string{ "Some-Header": "foo", }) req.WithForm(map[string]interface{}{ "a": 1, "b": "2", }) resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) assert.Equal(t, http.Header(expectedHeaders), client.req.Header) assert.Equal(t, `a=1&b=2`, string(resp.content)) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestBodyField(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } expectedHeaders := map[string][]string{ "Content-Type": {"application/x-www-form-urlencoded"}, "Some-Header": {"foo"}, } req := NewRequest(config, "METHOD", "url") req.WithHeaders(map[string]string{ "Some-Header": "foo", }) req.WithFormField("a", 1) req.WithFormField("b", "2") resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) assert.Equal(t, http.Header(expectedHeaders), client.req.Header) assert.Equal(t, `a=1&b=2`, string(resp.content)) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestBodyFormStruct(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } expectedHeaders := map[string][]string{ "Content-Type": {"application/x-www-form-urlencoded"}, } req := NewRequest(config, "METHOD", "url") type S struct { A string `form:"a"` B int `form:"b"` C int `form:"-"` } req.WithForm(S{"1", 2, 3}) resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) assert.Equal(t, http.Header(expectedHeaders), client.req.Header) assert.Equal(t, `a=1&b=2`, string(resp.content)) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestBodyFormCombined(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } expectedHeaders := map[string][]string{ "Content-Type": {"application/x-www-form-urlencoded"}, } req := NewRequest(config, "METHOD", "url") type S struct { A int `form:"a"` } req.WithForm(S{A: 1}) req.WithForm(map[string]string{"b": "2"}) req.WithFormField("c", 3) resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) assert.Equal(t, http.Header(expectedHeaders), client.req.Header) assert.Equal(t, `a=1&b=2&c=3`, string(resp.content)) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestBodyMultipart(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "POST", "url") req.WithMultipart() req.WithForm(map[string]string{"b": "1", "c": "2"}) req.WithFormField("a", 3) resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "POST", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) mediatype, params, err := mime.ParseMediaType(client.req.Header.Get("Content-Type")) assert.True(t, err == nil) assert.Equal(t, "multipart/form-data", mediatype) assert.True(t, params["boundary"] != "") reader := multipart.NewReader(bytes.NewReader(resp.content), params["boundary"]) part1, _ := reader.NextPart() assert.Equal(t, "b", part1.FormName()) assert.Equal(t, "", part1.FileName()) b1, _ := ioutil.ReadAll(part1) assert.Equal(t, "1", string(b1)) part2, _ := reader.NextPart() assert.Equal(t, "c", part2.FormName()) assert.Equal(t, "", part2.FileName()) b2, _ := ioutil.ReadAll(part2) assert.Equal(t, "2", string(b2)) part3, _ := reader.NextPart() assert.Equal(t, "a", part3.FormName()) assert.Equal(t, "", part3.FileName()) b3, _ := ioutil.ReadAll(part3) assert.Equal(t, "3", string(b3)) eof, _ := reader.NextPart() assert.True(t, eof == nil) } func TestRequestBodyMultipartFile(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "POST", "url") fh, _ := ioutil.TempFile("", "httpexpect") filename2 := fh.Name() fh.WriteString("2") fh.Close() defer os.Remove(filename2) req.WithMultipart() req.WithForm(map[string]string{"a": "1"}) req.WithFile("b", filename2) req.WithFile("c", "filename3", strings.NewReader("3")) req.WithFileBytes("d", "filename4", []byte("4")) resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "POST", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) mediatype, params, err := mime.ParseMediaType(client.req.Header.Get("Content-Type")) assert.True(t, err == nil) assert.Equal(t, "multipart/form-data", mediatype) assert.True(t, params["boundary"] != "") reader := multipart.NewReader(bytes.NewReader(resp.content), params["boundary"]) part1, _ := reader.NextPart() assert.Equal(t, "a", part1.FormName()) assert.Equal(t, "", part1.FileName()) b1, _ := ioutil.ReadAll(part1) assert.Equal(t, "1", string(b1)) part2, _ := reader.NextPart() assert.Equal(t, "b", part2.FormName()) assert.Equal(t, filename2, part2.FileName()) b2, _ := ioutil.ReadAll(part2) assert.Equal(t, "2", string(b2)) part3, _ := reader.NextPart() assert.Equal(t, "c", part3.FormName()) assert.Equal(t, "filename3", part3.FileName()) b3, _ := ioutil.ReadAll(part3) assert.Equal(t, "3", string(b3)) part4, _ := reader.NextPart() assert.Equal(t, "d", part4.FormName()) assert.Equal(t, "filename4", part4.FileName()) b4, _ := ioutil.ReadAll(part4) assert.Equal(t, "4", string(b4)) eof, _ := reader.NextPart() assert.True(t, eof == nil) } func TestRequestBodyJSON(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } expectedHeaders := map[string][]string{ "Content-Type": {"application/json; charset=utf-8"}, "Some-Header": {"foo"}, } req := NewRequest(config, "METHOD", "url") req.WithHeaders(map[string]string{ "Some-Header": "foo", }) req.WithJSON(map[string]interface{}{"key": "value"}) resp := req.Expect() resp.chain.assertOK(t) assert.Equal(t, "METHOD", client.req.Method) assert.Equal(t, "url", client.req.URL.String()) assert.Equal(t, http.Header(expectedHeaders), client.req.Header) assert.Equal(t, `{"key":"value"}`, string(resp.content)) assert.Equal(t, &client.resp, resp.Raw()) } func TestRequestContentLength(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req1 := NewRequest(config, "METHOD", "url") req1.WithChunked(bytes.NewReader([]byte("12345"))) req1.Expect().chain.assertOK(t) assert.Equal(t, int64(-1), client.req.ContentLength) req2 := NewRequest(config, "METHOD", "url") req2.WithBytes([]byte("12345")) req2.Expect().chain.assertOK(t) assert.Equal(t, int64(5), client.req.ContentLength) req3 := NewRequest(config, "METHOD", "url") req3.WithText("12345") req3.Expect().chain.assertOK(t) assert.Equal(t, int64(5), client.req.ContentLength) j, _ := json.Marshal(map[string]string{"a": "b"}) req4 := NewRequest(config, "METHOD", "url") req4.WithJSON(map[string]string{"a": "b"}) req4.Expect().chain.assertOK(t) assert.Equal(t, int64(len(j)), client.req.ContentLength) f := `a=b` req5 := NewRequest(config, "METHOD", "url") req5.WithForm(map[string]string{"a": "b"}) req5.Expect().chain.assertOK(t) assert.Equal(t, int64(len(f)), client.req.ContentLength) req6 := NewRequest(config, "METHOD", "url") req6.WithFormField("a", "b") req6.Expect().chain.assertOK(t) assert.Equal(t, int64(len(f)), client.req.ContentLength) req7 := NewRequest(config, "METHOD", "url") req7.WithMultipart() req7.WithFileBytes("a", "b", []byte("12345")) req7.Expect().chain.assertOK(t) assert.True(t, client.req.ContentLength > 0) } func TestRequestContentTypeOverwrite(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req1 := NewRequest(config, "METHOD", "url") req1.WithText("hello") req1.WithHeader("Content-Type", "foo") req1.Expect().chain.assertOK(t) assert.Equal(t, http.Header{"Content-Type": {"foo"}}, client.req.Header) req2 := NewRequest(config, "METHOD", "url") req2.WithHeader("Content-Type", "foo") req2.WithText("hello") req2.Expect().chain.assertOK(t) assert.Equal(t, http.Header{"Content-Type": {"foo"}}, client.req.Header) req3 := NewRequest(config, "METHOD", "url") req3.WithJSON(map[string]interface{}{"a": "b"}) req3.WithHeader("Content-Type", "foo") req3.WithHeader("Content-Type", "bar") req3.Expect().chain.assertOK(t) assert.Equal(t, http.Header{"Content-Type": {"foo", "bar"}}, client.req.Header) req4 := NewRequest(config, "METHOD", "url") req4.WithForm(map[string]interface{}{"a": "b"}) req4.WithHeader("Content-Type", "foo") req4.WithHeader("Content-Type", "bar") req4.Expect().chain.assertOK(t) assert.Equal(t, http.Header{"Content-Type": {"foo", "bar"}}, client.req.Header) req5 := NewRequest(config, "METHOD", "url") req5.WithMultipart() req5.WithForm(map[string]interface{}{"a": "b"}) req5.WithHeader("Content-Type", "foo") req5.WithHeader("Content-Type", "bar") req5.Expect().chain.assertOK(t) assert.Equal(t, http.Header{"Content-Type": {"foo", "bar"}}, client.req.Header) } func TestRequestErrorMarshalForm(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") req.WithForm(func() {}) resp := req.Expect() resp.chain.assertFailed(t) assert.True(t, resp.Raw() == nil) } func TestRequestErrorMarshalJSON(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{} reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") req.WithJSON(func() {}) resp := req.Expect() resp.chain.assertFailed(t) assert.True(t, resp.Raw() == nil) } func TestRequestErrorReadFile(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{ err: errors.New("error"), } reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") req.WithMultipart() req.WithFile("", "") resp := req.Expect() resp.chain.assertFailed(t) assert.True(t, resp.Raw() == nil) } func TestRequestErrorSend(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{ err: errors.New("error"), } reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req := NewRequest(config, "METHOD", "url") resp := req.Expect() resp.chain.assertFailed(t) assert.True(t, resp.Raw() == nil) } func TestRequestErrorConflictBody(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{ err: errors.New("error"), } reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req1 := NewRequest(config, "METHOD", "url") req1.WithChunked(nil) req1.chain.assertOK(t) req1.WithChunked(nil) req1.chain.assertFailed(t) req2 := NewRequest(config, "METHOD", "url") req2.WithChunked(nil) req2.chain.assertOK(t) req2.WithBytes(nil) req2.chain.assertFailed(t) req3 := NewRequest(config, "METHOD", "url") req3.WithChunked(nil) req3.chain.assertOK(t) req3.WithText("") req3.chain.assertFailed(t) req4 := NewRequest(config, "METHOD", "url") req4.WithChunked(nil) req4.chain.assertOK(t) req4.WithJSON(map[string]interface{}{"a": "b"}) req4.chain.assertFailed(t) req5 := NewRequest(config, "METHOD", "url") req5.WithChunked(nil) req5.chain.assertOK(t) req5.WithForm(map[string]interface{}{"a": "b"}) req5.Expect() req5.chain.assertFailed(t) req6 := NewRequest(config, "METHOD", "url") req6.WithChunked(nil) req6.chain.assertOK(t) req6.WithFormField("a", "b") req6.Expect() req6.chain.assertFailed(t) req7 := NewRequest(config, "METHOD", "url") req7.WithChunked(nil) req7.chain.assertOK(t) req7.WithMultipart() req7.chain.assertFailed(t) } func TestRequestErrorConflictType(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{ err: errors.New("error"), } reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req1 := NewRequest(config, "METHOD", "url") req1.WithText("") req1.chain.assertOK(t) req1.WithJSON(map[string]interface{}{"a": "b"}) req1.chain.assertFailed(t) req2 := NewRequest(config, "METHOD", "url") req2.WithText("") req2.chain.assertOK(t) req2.WithForm(map[string]interface{}{"a": "b"}) req2.chain.assertFailed(t) req3 := NewRequest(config, "METHOD", "url") req3.WithText("") req3.chain.assertOK(t) req3.WithFormField("a", "b") req3.chain.assertFailed(t) req4 := NewRequest(config, "METHOD", "url") req4.WithText("") req4.chain.assertOK(t) req4.WithMultipart() req4.chain.assertFailed(t) } func TestRequestErrorConflictMultipart(t *testing.T) { factory := DefaultRequestFactory{} client := &mockClient{ err: errors.New("error"), } reporter := newMockReporter(t) config := Config{ RequestFactory: factory, Client: client, Reporter: reporter, } req1 := NewRequest(config, "METHOD", "url") req1.WithForm(map[string]interface{}{"a": "b"}) req1.chain.assertOK(t) req1.WithMultipart() req1.chain.assertFailed(t) req2 := NewRequest(config, "METHOD", "url") req2.WithFormField("a", "b") req2.chain.assertOK(t) req2.WithMultipart() req2.chain.assertFailed(t) req3 := NewRequest(config, "METHOD", "url") req3.WithFileBytes("a", "a", []byte("a")) req3.chain.assertFailed(t) }