syncthing/vendor/github.com/onsi/gomega/ghttp/test_server_test.go
Jakob Borg 65aaa607ab Use Go 1.5 vendoring instead of Godeps
Change made by:

- running "gvt fetch" on each of the packages mentioned in
  Godeps/Godeps.json
- `rm -rf Godeps`
- tweaking the build scripts to not mention Godeps
- tweaking the build scripts to test `./lib/...`, `./cmd/...` explicitly
  (to avoid testing vendor)
- tweaking the build scripts to not juggle GOPATH for Godeps and instead
  set GO15VENDOREXPERIMENT.

This also results in some updated packages at the same time I bet.

Building with Go 1.3 and 1.4 still *works* but won't use our vendored
dependencies - the user needs to have the actual packages in their
GOPATH then, which they'll get with a normal "go get". Building with Go
1.6+ will get our vendored dependencies by default even when not using
our build script, which is nice.

By doing this we gain some freedom in that we can pick and choose
manually what to include in vendor, as it's not based on just dependency
analysis of our own code. This is also a risk as we might pick up
dependencies we are unaware of, as the build may work locally with those
packages present in GOPATH. On the other hand the build server will
detect this as it has no packages in it's GOPATH beyond what is included
in the repo.

Recommended tool to manage dependencies is github.com/FiloSottile/gvt.
2016-03-05 21:21:24 +01:00

1083 lines
31 KiB
Go

package ghttp_test
import (
"bytes"
"io"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"github.com/golang/protobuf/proto"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/ghttp/protobuf"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/ghttp"
)
var _ = Describe("TestServer", func() {
var (
resp *http.Response
err error
s *Server
)
BeforeEach(func() {
s = NewServer()
})
AfterEach(func() {
s.Close()
})
Describe("Resetting the server", func() {
BeforeEach(func() {
s.RouteToHandler("GET", "/", func(w http.ResponseWriter, req *http.Request) {})
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {})
http.Get(s.URL() + "/")
Ω(s.ReceivedRequests()).Should(HaveLen(1))
})
It("clears all handlers and call counts", func() {
s.Reset()
Ω(s.ReceivedRequests()).Should(HaveLen(0))
Ω(func() { s.GetHandler(0) }).Should(Panic())
})
})
Describe("closing client connections", func() {
It("closes", func() {
s.RouteToHandler("GET", "/",
func(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, req.RemoteAddr)
},
)
resp, err := http.Get(s.URL())
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(200))
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
Ω(err).ShouldNot(HaveOccurred())
s.CloseClientConnections()
resp, err = http.Get(s.URL())
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(200))
body2, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
Ω(err).ShouldNot(HaveOccurred())
Ω(body2).ShouldNot(Equal(body))
})
})
Describe("allowing unhandled requests", func() {
Context("when true", func() {
BeforeEach(func() {
s.AllowUnhandledRequests = true
s.UnhandledRequestStatusCode = http.StatusForbidden
resp, err = http.Get(s.URL() + "/foo")
Ω(err).ShouldNot(HaveOccurred())
})
It("should allow unhandled requests and respond with the passed in status code", func() {
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusForbidden))
data, err := ioutil.ReadAll(resp.Body)
Ω(err).ShouldNot(HaveOccurred())
Ω(data).Should(BeEmpty())
})
It("should record the requests", func() {
Ω(s.ReceivedRequests()).Should(HaveLen(1))
Ω(s.ReceivedRequests()[0].URL.Path).Should(Equal("/foo"))
})
})
Context("when false", func() {
It("should fail when attempting a request", func() {
failures := InterceptGomegaFailures(func() {
http.Get(s.URL() + "/foo")
})
Ω(failures[0]).Should(ContainSubstring("Received Unhandled Request"))
})
})
})
Describe("Managing Handlers", func() {
var called []string
BeforeEach(func() {
called = []string{}
s.RouteToHandler("GET", "/routed", func(w http.ResponseWriter, req *http.Request) {
called = append(called, "r1")
})
s.RouteToHandler("POST", regexp.MustCompile(`/routed\d`), func(w http.ResponseWriter, req *http.Request) {
called = append(called, "r2")
})
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {
called = append(called, "A")
}, func(w http.ResponseWriter, req *http.Request) {
called = append(called, "B")
})
})
It("should prefer routed handlers if there is a match", func() {
http.Get(s.URL() + "/routed")
http.Post(s.URL()+"/routed7", "application/json", nil)
http.Get(s.URL() + "/foo")
http.Get(s.URL() + "/routed")
http.Post(s.URL()+"/routed9", "application/json", nil)
http.Get(s.URL() + "/bar")
failures := InterceptGomegaFailures(func() {
http.Get(s.URL() + "/foo")
http.Get(s.URL() + "/routed/not/a/match")
http.Get(s.URL() + "/routed7")
http.Post(s.URL()+"/routed", "application/json", nil)
})
Ω(failures[0]).Should(ContainSubstring("Received Unhandled Request"))
Ω(failures).Should(HaveLen(4))
http.Post(s.URL()+"/routed3", "application/json", nil)
Ω(called).Should(Equal([]string{"r1", "r2", "A", "r1", "r2", "B", "r2"}))
})
It("should override routed handlers when reregistered", func() {
s.RouteToHandler("GET", "/routed", func(w http.ResponseWriter, req *http.Request) {
called = append(called, "r3")
})
s.RouteToHandler("POST", regexp.MustCompile(`/routed\d`), func(w http.ResponseWriter, req *http.Request) {
called = append(called, "r4")
})
http.Get(s.URL() + "/routed")
http.Post(s.URL()+"/routed7", "application/json", nil)
Ω(called).Should(Equal([]string{"r3", "r4"}))
})
It("should call the appended handlers, in order, as requests come in", func() {
http.Get(s.URL() + "/foo")
Ω(called).Should(Equal([]string{"A"}))
http.Get(s.URL() + "/foo")
Ω(called).Should(Equal([]string{"A", "B"}))
failures := InterceptGomegaFailures(func() {
http.Get(s.URL() + "/foo")
})
Ω(failures[0]).Should(ContainSubstring("Received Unhandled Request"))
})
Describe("Overwriting an existing handler", func() {
BeforeEach(func() {
s.SetHandler(0, func(w http.ResponseWriter, req *http.Request) {
called = append(called, "C")
})
})
It("should override the specified handler", func() {
http.Get(s.URL() + "/foo")
http.Get(s.URL() + "/foo")
Ω(called).Should(Equal([]string{"C", "B"}))
})
})
Describe("Getting an existing handler", func() {
It("should return the handler func", func() {
s.GetHandler(1)(nil, nil)
Ω(called).Should(Equal([]string{"B"}))
})
})
Describe("Wrapping an existing handler", func() {
BeforeEach(func() {
s.WrapHandler(0, func(w http.ResponseWriter, req *http.Request) {
called = append(called, "C")
})
})
It("should wrap the existing handler in a new handler", func() {
http.Get(s.URL() + "/foo")
http.Get(s.URL() + "/foo")
Ω(called).Should(Equal([]string{"A", "C", "B"}))
})
})
})
Describe("When a handler fails", func() {
BeforeEach(func() {
s.UnhandledRequestStatusCode = http.StatusForbidden //just to be clear that 500s aren't coming from unhandled requests
})
Context("because the handler has panicked", func() {
BeforeEach(func() {
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {
panic("bam")
})
})
It("should respond with a 500 and make a failing assertion", func() {
var resp *http.Response
var err error
failures := InterceptGomegaFailures(func() {
resp, err = http.Get(s.URL())
})
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError))
Ω(failures).Should(ConsistOf(ContainSubstring("Handler Panicked")))
})
})
Context("because an assertion has failed", func() {
BeforeEach(func() {
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {
// Ω(true).Should(BeFalse()) <-- would be nice to do it this way, but the test just can't be written this way
By("We're cheating a bit here -- we're throwing a GINKGO_PANIC which simulates a failed assertion")
panic(GINKGO_PANIC)
})
})
It("should respond with a 500 and *not* make a failing assertion, instead relying on Ginkgo to have already been notified of the error", func() {
resp, err := http.Get(s.URL())
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusInternalServerError))
})
})
})
Describe("Logging to the Writer", func() {
var buf *gbytes.Buffer
BeforeEach(func() {
buf = gbytes.NewBuffer()
s.Writer = buf
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {})
s.AppendHandlers(func(w http.ResponseWriter, req *http.Request) {})
})
It("should write to the buffer when a request comes in", func() {
http.Get(s.URL() + "/foo")
Ω(buf).Should(gbytes.Say("GHTTP Received Request: GET - /foo\n"))
http.Post(s.URL()+"/bar", "", nil)
Ω(buf).Should(gbytes.Say("GHTTP Received Request: POST - /bar\n"))
})
})
Describe("Request Handlers", func() {
Describe("VerifyRequest", func() {
BeforeEach(func() {
s.AppendHandlers(VerifyRequest("GET", "/foo"))
})
It("should verify the method, path", func() {
resp, err = http.Get(s.URL() + "/foo?baz=bar")
Ω(err).ShouldNot(HaveOccurred())
})
It("should verify the method, path", func() {
failures := InterceptGomegaFailures(func() {
http.Get(s.URL() + "/foo2")
})
Ω(failures).Should(HaveLen(1))
})
It("should verify the method, path", func() {
failures := InterceptGomegaFailures(func() {
http.Post(s.URL()+"/foo", "application/json", nil)
})
Ω(failures).Should(HaveLen(1))
})
Context("when passed a rawQuery", func() {
It("should also be possible to verify the rawQuery", func() {
s.SetHandler(0, VerifyRequest("GET", "/foo", "baz=bar"))
resp, err = http.Get(s.URL() + "/foo?baz=bar")
Ω(err).ShouldNot(HaveOccurred())
})
It("should match irregardless of query parameter ordering", func() {
s.SetHandler(0, VerifyRequest("GET", "/foo", "type=get&name=money"))
u, _ := url.Parse(s.URL() + "/foo")
u.RawQuery = url.Values{
"type": []string{"get"},
"name": []string{"money"},
}.Encode()
resp, err = http.Get(u.String())
Ω(err).ShouldNot(HaveOccurred())
})
})
Context("when passed a matcher for path", func() {
It("should apply the matcher", func() {
s.SetHandler(0, VerifyRequest("GET", MatchRegexp(`/foo/[a-f]*/3`)))
resp, err = http.Get(s.URL() + "/foo/abcdefa/3")
Ω(err).ShouldNot(HaveOccurred())
})
})
})
Describe("VerifyContentType", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("GET", "/foo"),
VerifyContentType("application/octet-stream"),
))
})
It("should verify the content type", func() {
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
Ω(err).ShouldNot(HaveOccurred())
req.Header.Set("Content-Type", "application/octet-stream")
resp, err = http.DefaultClient.Do(req)
Ω(err).ShouldNot(HaveOccurred())
})
It("should verify the content type", func() {
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
Ω(err).ShouldNot(HaveOccurred())
req.Header.Set("Content-Type", "application/json")
failures := InterceptGomegaFailures(func() {
http.DefaultClient.Do(req)
})
Ω(failures).Should(HaveLen(1))
})
})
Describe("Verify BasicAuth", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("GET", "/foo"),
VerifyBasicAuth("bob", "password"),
))
})
It("should verify basic auth", func() {
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
Ω(err).ShouldNot(HaveOccurred())
req.SetBasicAuth("bob", "password")
resp, err = http.DefaultClient.Do(req)
Ω(err).ShouldNot(HaveOccurred())
})
It("should verify basic auth", func() {
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
Ω(err).ShouldNot(HaveOccurred())
req.SetBasicAuth("bob", "bassword")
failures := InterceptGomegaFailures(func() {
http.DefaultClient.Do(req)
})
Ω(failures).Should(HaveLen(1))
})
It("should require basic auth header", func() {
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
Ω(err).ShouldNot(HaveOccurred())
failures := InterceptGomegaFailures(func() {
http.DefaultClient.Do(req)
})
Ω(failures).Should(ContainElement(ContainSubstring("Authorization header must be specified")))
})
})
Describe("VerifyHeader", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("GET", "/foo"),
VerifyHeader(http.Header{
"accept": []string{"jpeg", "png"},
"cache-control": []string{"omicron"},
"Return-Path": []string{"hobbiton"},
}),
))
})
It("should verify the headers", func() {
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
Ω(err).ShouldNot(HaveOccurred())
req.Header.Add("Accept", "jpeg")
req.Header.Add("Accept", "png")
req.Header.Add("Cache-Control", "omicron")
req.Header.Add("return-path", "hobbiton")
resp, err = http.DefaultClient.Do(req)
Ω(err).ShouldNot(HaveOccurred())
})
It("should verify the headers", func() {
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
Ω(err).ShouldNot(HaveOccurred())
req.Header.Add("Schmaccept", "jpeg")
req.Header.Add("Schmaccept", "png")
req.Header.Add("Cache-Control", "omicron")
req.Header.Add("return-path", "hobbiton")
failures := InterceptGomegaFailures(func() {
http.DefaultClient.Do(req)
})
Ω(failures).Should(HaveLen(1))
})
})
Describe("VerifyHeaderKV", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("GET", "/foo"),
VerifyHeaderKV("accept", "jpeg", "png"),
VerifyHeaderKV("cache-control", "omicron"),
VerifyHeaderKV("Return-Path", "hobbiton"),
))
})
It("should verify the headers", func() {
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
Ω(err).ShouldNot(HaveOccurred())
req.Header.Add("Accept", "jpeg")
req.Header.Add("Accept", "png")
req.Header.Add("Cache-Control", "omicron")
req.Header.Add("return-path", "hobbiton")
resp, err = http.DefaultClient.Do(req)
Ω(err).ShouldNot(HaveOccurred())
})
It("should verify the headers", func() {
req, err := http.NewRequest("GET", s.URL()+"/foo", nil)
Ω(err).ShouldNot(HaveOccurred())
req.Header.Add("Accept", "jpeg")
req.Header.Add("Cache-Control", "omicron")
req.Header.Add("return-path", "hobbiton")
failures := InterceptGomegaFailures(func() {
http.DefaultClient.Do(req)
})
Ω(failures).Should(HaveLen(1))
})
})
Describe("VerifyBody", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
VerifyBody([]byte("some body")),
))
})
It("should verify the body", func() {
resp, err = http.Post(s.URL()+"/foo", "", bytes.NewReader([]byte("some body")))
Ω(err).ShouldNot(HaveOccurred())
})
It("should verify the body", func() {
failures := InterceptGomegaFailures(func() {
http.Post(s.URL()+"/foo", "", bytes.NewReader([]byte("wrong body")))
})
Ω(failures).Should(HaveLen(1))
})
})
Describe("VerifyJSON", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
VerifyJSON(`{"a":3, "b":2}`),
))
})
It("should verify the json body and the content type", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", bytes.NewReader([]byte(`{"b":2, "a":3}`)))
Ω(err).ShouldNot(HaveOccurred())
})
It("should verify the json body and the content type", func() {
failures := InterceptGomegaFailures(func() {
http.Post(s.URL()+"/foo", "application/json", bytes.NewReader([]byte(`{"b":2, "a":4}`)))
})
Ω(failures).Should(HaveLen(1))
})
It("should verify the json body and the content type", func() {
failures := InterceptGomegaFailures(func() {
http.Post(s.URL()+"/foo", "application/not-json", bytes.NewReader([]byte(`{"b":2, "a":3}`)))
})
Ω(failures).Should(HaveLen(1))
})
})
Describe("VerifyJSONRepresenting", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
VerifyJSONRepresenting([]int{1, 3, 5}),
))
})
It("should verify the json body and the content type", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", bytes.NewReader([]byte(`[1,3,5]`)))
Ω(err).ShouldNot(HaveOccurred())
})
It("should verify the json body and the content type", func() {
failures := InterceptGomegaFailures(func() {
http.Post(s.URL()+"/foo", "application/json", bytes.NewReader([]byte(`[1,3]`)))
})
Ω(failures).Should(HaveLen(1))
})
})
Describe("VerifyForm", func() {
var formValues url.Values
BeforeEach(func() {
formValues = make(url.Values)
formValues.Add("users", "user1")
formValues.Add("users", "user2")
formValues.Add("group", "users")
})
Context("when encoded in the URL", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("GET", "/foo"),
VerifyForm(url.Values{
"users": []string{"user1", "user2"},
"group": []string{"users"},
}),
))
})
It("should verify form values", func() {
resp, err = http.Get(s.URL() + "/foo?" + formValues.Encode())
Ω(err).ShouldNot(HaveOccurred())
})
It("should ignore extra values", func() {
formValues.Add("extra", "value")
resp, err = http.Get(s.URL() + "/foo?" + formValues.Encode())
Ω(err).ShouldNot(HaveOccurred())
})
It("fail on missing values", func() {
formValues.Del("group")
failures := InterceptGomegaFailures(func() {
resp, err = http.Get(s.URL() + "/foo?" + formValues.Encode())
})
Ω(failures).Should(HaveLen(1))
})
It("fail on incorrect values", func() {
formValues.Set("group", "wheel")
failures := InterceptGomegaFailures(func() {
resp, err = http.Get(s.URL() + "/foo?" + formValues.Encode())
})
Ω(failures).Should(HaveLen(1))
})
})
Context("when present in the body", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
VerifyForm(url.Values{
"users": []string{"user1", "user2"},
"group": []string{"users"},
}),
))
})
It("should verify form values", func() {
resp, err = http.PostForm(s.URL()+"/foo", formValues)
Ω(err).ShouldNot(HaveOccurred())
})
It("should ignore extra values", func() {
formValues.Add("extra", "value")
resp, err = http.PostForm(s.URL()+"/foo", formValues)
Ω(err).ShouldNot(HaveOccurred())
})
It("fail on missing values", func() {
formValues.Del("group")
failures := InterceptGomegaFailures(func() {
resp, err = http.PostForm(s.URL()+"/foo", formValues)
})
Ω(failures).Should(HaveLen(1))
})
It("fail on incorrect values", func() {
formValues.Set("group", "wheel")
failures := InterceptGomegaFailures(func() {
resp, err = http.PostForm(s.URL()+"/foo", formValues)
})
Ω(failures).Should(HaveLen(1))
})
})
})
Describe("VerifyFormKV", func() {
Context("when encoded in the URL", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("GET", "/foo"),
VerifyFormKV("users", "user1", "user2"),
))
})
It("verifies the form value", func() {
resp, err = http.Get(s.URL() + "/foo?users=user1&users=user2")
Ω(err).ShouldNot(HaveOccurred())
})
It("verifies the form value", func() {
failures := InterceptGomegaFailures(func() {
resp, err = http.Get(s.URL() + "/foo?users=user1")
})
Ω(failures).Should(HaveLen(1))
})
})
Context("when present in the body", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
VerifyFormKV("users", "user1", "user2"),
))
})
It("verifies the form value", func() {
resp, err = http.PostForm(s.URL()+"/foo", url.Values{"users": []string{"user1", "user2"}})
Ω(err).ShouldNot(HaveOccurred())
})
It("verifies the form value", func() {
failures := InterceptGomegaFailures(func() {
resp, err = http.PostForm(s.URL()+"/foo", url.Values{"users": []string{"user1"}})
})
Ω(failures).Should(HaveLen(1))
})
})
})
Describe("VerifyProtoRepresenting", func() {
var message *protobuf.SimpleMessage
BeforeEach(func() {
message = new(protobuf.SimpleMessage)
message.Description = proto.String("A description")
message.Id = proto.Int32(0)
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/proto"),
VerifyProtoRepresenting(message),
))
})
It("verifies the proto body and the content type", func() {
serialized, err := proto.Marshal(message)
Ω(err).ShouldNot(HaveOccurred())
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", bytes.NewReader(serialized))
Ω(err).ShouldNot(HaveOccurred())
})
It("should verify the proto body and the content type", func() {
serialized, err := proto.Marshal(&protobuf.SimpleMessage{
Description: proto.String("A description"),
Id: proto.Int32(0),
Metadata: proto.String("some metadata"),
})
Ω(err).ShouldNot(HaveOccurred())
failures := InterceptGomegaFailures(func() {
http.Post(s.URL()+"/proto", "application/x-protobuf", bytes.NewReader(serialized))
})
Ω(failures).Should(HaveLen(1))
})
It("should verify the proto body and the content type", func() {
serialized, err := proto.Marshal(message)
Ω(err).ShouldNot(HaveOccurred())
failures := InterceptGomegaFailures(func() {
http.Post(s.URL()+"/proto", "application/not-x-protobuf", bytes.NewReader(serialized))
})
Ω(failures).Should(HaveLen(1))
})
})
Describe("RespondWith", func() {
Context("without headers", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWith(http.StatusCreated, "sweet"),
), CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWith(http.StatusOK, []byte("sour")),
))
})
It("should return the response", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
body, err := ioutil.ReadAll(resp.Body)
Ω(err).ShouldNot(HaveOccurred())
Ω(body).Should(Equal([]byte("sweet")))
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusOK))
body, err = ioutil.ReadAll(resp.Body)
Ω(err).ShouldNot(HaveOccurred())
Ω(body).Should(Equal([]byte("sour")))
})
})
Context("with headers", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWith(http.StatusCreated, "sweet", http.Header{"X-Custom-Header": []string{"my header"}}),
))
})
It("should return the headers too", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
Ω(ioutil.ReadAll(resp.Body)).Should(Equal([]byte("sweet")))
Ω(resp.Header.Get("X-Custom-Header")).Should(Equal("my header"))
})
})
})
Describe("RespondWithPtr", func() {
var code int
var byteBody []byte
var stringBody string
BeforeEach(func() {
code = http.StatusOK
byteBody = []byte("sweet")
stringBody = "sour"
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWithPtr(&code, &byteBody),
), CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWithPtr(&code, &stringBody),
))
})
It("should return the response", func() {
code = http.StatusCreated
byteBody = []byte("tasty")
stringBody = "treat"
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
body, err := ioutil.ReadAll(resp.Body)
Ω(err).ShouldNot(HaveOccurred())
Ω(body).Should(Equal([]byte("tasty")))
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
body, err = ioutil.ReadAll(resp.Body)
Ω(err).ShouldNot(HaveOccurred())
Ω(body).Should(Equal([]byte("treat")))
})
Context("when passed a nil body", func() {
BeforeEach(func() {
s.SetHandler(0, CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWithPtr(&code, nil),
))
})
It("should return an empty body and not explode", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusOK))
body, err := ioutil.ReadAll(resp.Body)
Ω(err).ShouldNot(HaveOccurred())
Ω(body).Should(BeEmpty())
Ω(s.ReceivedRequests()).Should(HaveLen(1))
})
})
})
Describe("RespondWithJSON", func() {
Context("when no optional headers are set", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWithJSONEncoded(http.StatusCreated, []int{1, 2, 3}),
))
})
It("should return the response", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
body, err := ioutil.ReadAll(resp.Body)
Ω(err).ShouldNot(HaveOccurred())
Ω(body).Should(MatchJSON("[1,2,3]"))
})
It("should set the Content-Type header to application/json", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/json"}))
})
})
Context("when optional headers are set", func() {
var headers http.Header
BeforeEach(func() {
headers = http.Header{"Stuff": []string{"things"}}
})
JustBeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWithJSONEncoded(http.StatusCreated, []int{1, 2, 3}, headers),
))
})
It("should preserve those headers", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Stuff"]).Should(Equal([]string{"things"}))
})
It("should set the Content-Type header to application/json", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/json"}))
})
Context("when setting the Content-Type explicitly", func() {
BeforeEach(func() {
headers["Content-Type"] = []string{"not-json"}
})
It("should use the Content-Type header that was explicitly set", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"not-json"}))
})
})
})
})
Describe("RespondWithJSONPtr", func() {
type testObject struct {
Key string
Value string
}
var code int
var object testObject
Context("when no optional headers are set", func() {
BeforeEach(func() {
code = http.StatusOK
object = testObject{}
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWithJSONEncodedPtr(&code, &object),
))
})
It("should return the response", func() {
code = http.StatusCreated
object = testObject{
Key: "Jim",
Value: "Codes",
}
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
body, err := ioutil.ReadAll(resp.Body)
Ω(err).ShouldNot(HaveOccurred())
Ω(body).Should(MatchJSON(`{"Key": "Jim", "Value": "Codes"}`))
})
It("should set the Content-Type header to application/json", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/json"}))
})
})
Context("when optional headers are set", func() {
var headers http.Header
BeforeEach(func() {
headers = http.Header{"Stuff": []string{"things"}}
})
JustBeforeEach(func() {
code = http.StatusOK
object = testObject{}
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/foo"),
RespondWithJSONEncodedPtr(&code, &object, headers),
))
})
It("should preserve those headers", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Stuff"]).Should(Equal([]string{"things"}))
})
It("should set the Content-Type header to application/json", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/json"}))
})
Context("when setting the Content-Type explicitly", func() {
BeforeEach(func() {
headers["Content-Type"] = []string{"not-json"}
})
It("should use the Content-Type header that was explicitly set", func() {
resp, err = http.Post(s.URL()+"/foo", "application/json", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"not-json"}))
})
})
})
})
Describe("RespondWithProto", func() {
var message *protobuf.SimpleMessage
BeforeEach(func() {
message = new(protobuf.SimpleMessage)
message.Description = proto.String("A description")
message.Id = proto.Int32(99)
})
Context("when no optional headers are set", func() {
BeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/proto"),
RespondWithProto(http.StatusCreated, message),
))
})
It("should return the response", func() {
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.StatusCode).Should(Equal(http.StatusCreated))
var received protobuf.SimpleMessage
body, err := ioutil.ReadAll(resp.Body)
err = proto.Unmarshal(body, &received)
Ω(err).ShouldNot(HaveOccurred())
})
It("should set the Content-Type header to application/x-protobuf", func() {
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/x-protobuf"}))
})
})
Context("when optional headers are set", func() {
var headers http.Header
BeforeEach(func() {
headers = http.Header{"Stuff": []string{"things"}}
})
JustBeforeEach(func() {
s.AppendHandlers(CombineHandlers(
VerifyRequest("POST", "/proto"),
RespondWithProto(http.StatusCreated, message, headers),
))
})
It("should preserve those headers", func() {
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Stuff"]).Should(Equal([]string{"things"}))
})
It("should set the Content-Type header to application/x-protobuf", func() {
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"application/x-protobuf"}))
})
Context("when setting the Content-Type explicitly", func() {
BeforeEach(func() {
headers["Content-Type"] = []string{"not-x-protobuf"}
})
It("should use the Content-Type header that was explicitly set", func() {
resp, err = http.Post(s.URL()+"/proto", "application/x-protobuf", nil)
Ω(err).ShouldNot(HaveOccurred())
Ω(resp.Header["Content-Type"]).Should(Equal([]string{"not-x-protobuf"}))
})
})
})
})
})
})