1package assert
2
3import (
4	"fmt"
5	"net/http"
6	"net/http/httptest"
7	"net/url"
8	"strings"
9)
10
11// httpCode is a helper that returns HTTP code of the response. It returns -1
12// if building a new request fails.
13func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int {
14	w := httptest.NewRecorder()
15	req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
16	if err != nil {
17		return -1
18	}
19	handler(w, req)
20	return w.Code
21}
22
23// HTTPSuccess asserts that a specified handler returns a success status code.
24//
25//  assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
26//
27// Returns whether the assertion was successful (true) or not (false).
28func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
29	code := httpCode(handler, method, url, values)
30	if code == -1 {
31		return false
32	}
33	return code >= http.StatusOK && code <= http.StatusPartialContent
34}
35
36// HTTPRedirect asserts that a specified handler returns a redirect status code.
37//
38//  assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
39//
40// Returns whether the assertion was successful (true) or not (false).
41func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
42	code := httpCode(handler, method, url, values)
43	if code == -1 {
44		return false
45	}
46	return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
47}
48
49// HTTPError asserts that a specified handler returns an error status code.
50//
51//  assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
52//
53// Returns whether the assertion was successful (true) or not (false).
54func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
55	code := httpCode(handler, method, url, values)
56	if code == -1 {
57		return false
58	}
59	return code >= http.StatusBadRequest
60}
61
62// HTTPBody is a helper that returns HTTP body of the response. It returns
63// empty string if building a new request fails.
64func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
65	w := httptest.NewRecorder()
66	req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
67	if err != nil {
68		return ""
69	}
70	handler(w, req)
71	return w.Body.String()
72}
73
74// HTTPBodyContains asserts that a specified handler returns a
75// body that contains a string.
76//
77//  assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
78//
79// Returns whether the assertion was successful (true) or not (false).
80func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
81	body := HTTPBody(handler, method, url, values)
82
83	contains := strings.Contains(body, fmt.Sprint(str))
84	if !contains {
85		Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
86	}
87
88	return contains
89}
90
91// HTTPBodyNotContains asserts that a specified handler returns a
92// body that does not contain a string.
93//
94//  assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
95//
96// Returns whether the assertion was successful (true) or not (false).
97func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
98	body := HTTPBody(handler, method, url, values)
99
100	contains := strings.Contains(body, fmt.Sprint(str))
101	if contains {
102		Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)
103	}
104
105	return !contains
106}
107