1package matchers_test
2
3import (
4	"io"
5	"net/http"
6	"net/http/httptest"
7	"strings"
8
9	. "github.com/onsi/ginkgo"
10	. "github.com/onsi/gomega"
11)
12
13var _ = Describe("HaveHTTPStatus", func() {
14	When("EXPECTED is single integer", func() {
15		It("matches the StatusCode", func() {
16			resp := &http.Response{StatusCode: http.StatusOK}
17			Expect(resp).To(HaveHTTPStatus(http.StatusOK))
18			Expect(resp).NotTo(HaveHTTPStatus(http.StatusNotFound))
19		})
20	})
21
22	When("EXPECTED is single string", func() {
23		It("matches the Status", func() {
24			resp := &http.Response{Status: "200 OK"}
25			Expect(resp).To(HaveHTTPStatus("200 OK"))
26			Expect(resp).NotTo(HaveHTTPStatus("404 Not Found"))
27		})
28	})
29
30	When("EXPECTED is empty", func() {
31		It("errors", func() {
32			failures := InterceptGomegaFailures(func() {
33				resp := &http.Response{StatusCode: http.StatusOK}
34				Expect(resp).To(HaveHTTPStatus())
35			})
36			Expect(failures).To(HaveLen(1))
37			Expect(failures[0]).To(Equal("HaveHTTPStatus matcher must be passed an int or a string. Got nothing"))
38		})
39	})
40
41	When("EXPECTED is not a string or integer", func() {
42		It("errors", func() {
43			failures := InterceptGomegaFailures(func() {
44				resp := &http.Response{StatusCode: http.StatusOK}
45				Expect(resp).To(HaveHTTPStatus(true))
46			})
47			Expect(failures).To(HaveLen(1))
48			Expect(failures[0]).To(Equal("HaveHTTPStatus matcher must be passed int or string types. Got:\n    <bool>: true"))
49		})
50	})
51
52	When("EXPECTED is a list of strings and integers", func() {
53		It("matches the StatusCode and Status", func() {
54			resp := &http.Response{
55				Status:     "200 OK",
56				StatusCode: http.StatusOK,
57			}
58			Expect(resp).To(HaveHTTPStatus(http.StatusOK, http.StatusNoContent, http.StatusNotFound))
59			Expect(resp).To(HaveHTTPStatus("204 Feeling Fine", "200 OK", "404 Not Found"))
60			Expect(resp).To(HaveHTTPStatus("204 Feeling Fine", http.StatusOK, "404 Not Found"))
61			Expect(resp).To(HaveHTTPStatus(http.StatusNoContent, "200 OK", http.StatusNotFound))
62			Expect(resp).NotTo(HaveHTTPStatus(http.StatusNotFound, http.StatusNoContent, http.StatusGone))
63			Expect(resp).NotTo(HaveHTTPStatus("204 Feeling Fine", "201 Sleeping", "404 Not Found"))
64			Expect(resp).NotTo(HaveHTTPStatus(http.StatusNotFound, "404 Not Found", http.StatusGone))
65		})
66	})
67
68	When("EXPECTED is a list containing non-string or integer types", func() {
69		It("errors", func() {
70			failures := InterceptGomegaFailures(func() {
71				resp := &http.Response{StatusCode: http.StatusOK}
72				Expect(resp).To(HaveHTTPStatus(http.StatusGone, "204 No Content", true, http.StatusNotFound))
73			})
74			Expect(failures).To(HaveLen(1))
75			Expect(failures[0]).To(Equal("HaveHTTPStatus matcher must be passed int or string types. Got:\n    <bool>: true"))
76		})
77	})
78
79	When("ACTUAL is *httptest.ResponseRecorder", func() {
80		When("EXPECTED is integer", func() {
81			It("matches the StatusCode", func() {
82				resp := &httptest.ResponseRecorder{Code: http.StatusOK}
83				Expect(resp).To(HaveHTTPStatus(http.StatusOK))
84				Expect(resp).NotTo(HaveHTTPStatus(http.StatusNotFound))
85			})
86		})
87
88		When("EXPECTED is string", func() {
89			It("matches the Status", func() {
90				resp := &httptest.ResponseRecorder{Code: http.StatusOK}
91				Expect(resp).To(HaveHTTPStatus("200 OK"))
92				Expect(resp).NotTo(HaveHTTPStatus("404 Not Found"))
93			})
94		})
95
96		When("EXPECTED is anything else", func() {
97			It("does not match", func() {
98				failures := InterceptGomegaFailures(func() {
99					resp := &httptest.ResponseRecorder{Code: http.StatusOK}
100					Expect(resp).NotTo(HaveHTTPStatus(nil))
101				})
102				Expect(failures).To(HaveLen(1))
103				Expect(failures[0]).To(Equal("HaveHTTPStatus matcher must be passed int or string types. Got:\n    <nil>: nil"))
104			})
105		})
106	})
107
108	When("ACTUAL is neither *http.Response nor *httptest.ResponseRecorder", func() {
109		It("errors", func() {
110			failures := InterceptGomegaFailures(func() {
111				Expect("foo").To(HaveHTTPStatus(http.StatusOK))
112			})
113			Expect(failures).To(HaveLen(1))
114			Expect(failures[0]).To(Equal("HaveHTTPStatus matcher expects *http.Response or *httptest.ResponseRecorder. Got:\n    <string>: foo"))
115		})
116	})
117
118	Describe("FailureMessage", func() {
119		It("returns a message for a single expected value", func() {
120			failures := InterceptGomegaFailures(func() {
121				resp := &http.Response{
122					StatusCode: http.StatusBadGateway,
123					Status:     "502 Bad Gateway",
124					Body:       io.NopCloser(strings.NewReader("did not like it")),
125				}
126				Expect(resp).To(HaveHTTPStatus(http.StatusOK))
127			})
128			Expect(failures).To(HaveLen(1))
129			Expect(failures[0]).To(Equal(`Expected
130    <*http.Response>: {
131        Status:     <string>: "502 Bad Gateway"
132        StatusCode: <int>: 502
133        Body:       <string>: "did not like it"
134    }
135to have HTTP status
136    <int>: 200`), failures[0])
137		})
138
139		It("returns a message for a multiple expected values", func() {
140			failures := InterceptGomegaFailures(func() {
141				resp := &http.Response{
142					StatusCode: http.StatusBadGateway,
143					Status:     "502 Bad Gateway",
144					Body:       io.NopCloser(strings.NewReader("did not like it")),
145				}
146				Expect(resp).To(HaveHTTPStatus(http.StatusOK, http.StatusNotFound, "204 No content"))
147			})
148			Expect(failures).To(HaveLen(1))
149			Expect(failures[0]).To(Equal(`Expected
150    <*http.Response>: {
151        Status:     <string>: "502 Bad Gateway"
152        StatusCode: <int>: 502
153        Body:       <string>: "did not like it"
154    }
155to have HTTP status
156    <int>: 200
157    <int>: 404
158    <string>: 204 No content`), failures[0])
159		})
160	})
161
162	Describe("NegatedFailureMessage", func() {
163		It("returns a message for a single expected value", func() {
164			failures := InterceptGomegaFailures(func() {
165				resp := &http.Response{
166					StatusCode: http.StatusOK,
167					Status:     "200 OK",
168					Body:       io.NopCloser(strings.NewReader("got it!")),
169				}
170				Expect(resp).NotTo(HaveHTTPStatus(http.StatusOK))
171			})
172			Expect(failures).To(HaveLen(1))
173			Expect(failures[0]).To(Equal(`Expected
174    <*http.Response>: {
175        Status:     <string>: "200 OK"
176        StatusCode: <int>: 200
177        Body:       <string>: "got it!"
178    }
179not to have HTTP status
180    <int>: 200`), failures[0])
181		})
182
183		It("returns a message for a multiple expected values", func() {
184			failures := InterceptGomegaFailures(func() {
185				resp := &http.Response{
186					StatusCode: http.StatusOK,
187					Status:     "200 OK",
188					Body:       io.NopCloser(strings.NewReader("got it!")),
189				}
190				Expect(resp).NotTo(HaveHTTPStatus(http.StatusOK, "204 No content", http.StatusGone))
191			})
192			Expect(failures).To(HaveLen(1))
193			Expect(failures[0]).To(Equal(`Expected
194    <*http.Response>: {
195        Status:     <string>: "200 OK"
196        StatusCode: <int>: 200
197        Body:       <string>: "got it!"
198    }
199not to have HTTP status
200    <int>: 200
201    <string>: 204 No content
202    <int>: 410`), failures[0])
203		})
204	})
205})
206