github.com/apex/up@v1.7.1/http/errorpages/errorpages_test.go (about) 1 package errorpages 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "net/http/httptest" 8 "os" 9 "testing" 10 11 "github.com/tj/assert" 12 13 "github.com/apex/up" 14 "github.com/apex/up/config" 15 ) 16 17 var server = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 18 if r.URL.Path == "/404" { 19 w.Header().Set("ETag", "something") 20 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 21 return 22 } 23 24 if r.URL.Path == "/400" { 25 http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) 26 return 27 } 28 29 if r.URL.Path == "/400/json" { 30 w.WriteHeader(400) 31 w.Header().Set("Content-Type", "application/json") 32 io.WriteString(w, `{ "error": "bad_request" }`) 33 return 34 } 35 36 if r.URL.Path == "/500" { 37 http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) 38 return 39 } 40 41 w.Header().Set("ETag", "something") 42 w.Header().Set("Content-Type", "text/plain") 43 fmt.Fprintf(w, "Hello") 44 fmt.Fprintf(w, " ") 45 fmt.Fprintf(w, "World") 46 }) 47 48 func TestErrors_templates(t *testing.T) { 49 os.Chdir("testdata/templates") 50 defer os.Chdir("../..") 51 52 c := &up.Config{ 53 Name: "app", 54 ErrorPages: config.ErrorPages{ 55 Enable: true, 56 }, 57 } 58 assert.NoError(t, c.Default(), "default") 59 assert.NoError(t, c.Validate(), "validate") 60 61 test(t, c) 62 } 63 64 func TestErrors_dir(t *testing.T) { 65 c := &up.Config{ 66 Name: "app", 67 ErrorPages: config.ErrorPages{ 68 Dir: "testdata/templates", 69 Enable: true, 70 }, 71 } 72 73 assert.NoError(t, c.Default(), "default") 74 assert.NoError(t, c.Validate(), "validate") 75 76 test(t, c) 77 } 78 79 func TestErrors_defaults(t *testing.T) { 80 os.Chdir("testdata/defaults") 81 defer os.Chdir("../..") 82 83 c := &up.Config{ 84 Name: "app", 85 ErrorPages: config.ErrorPages{ 86 Enable: true, 87 }, 88 } 89 assert.NoError(t, c.Default(), "default") 90 assert.NoError(t, c.Validate(), "validate") 91 92 h, err := New(c, server) 93 assert.NoError(t, err, "init") 94 95 t.Run("200", nonError(h)) 96 t.Run("accepts text/html", acceptsHTML(h)) 97 t.Run("accepts text/*", acceptsText(h)) 98 t.Run("does not accept html", doesNotAcceptHTML(h)) 99 } 100 101 func TestErrors_disabled(t *testing.T) { 102 c := &up.Config{ 103 Name: "app", 104 } 105 106 assert.NoError(t, c.Default(), "default") 107 assert.NoError(t, c.Validate(), "validate") 108 109 h, err := New(c, server) 110 assert.NoError(t, err, "init") 111 112 t.Run("200", nonError(h)) 113 114 t.Run("error", func(t *testing.T) { 115 res := httptest.NewRecorder() 116 req := httptest.NewRequest("GET", "/404", nil) 117 118 h.ServeHTTP(res, req) 119 120 assert.Equal(t, 404, res.Code) 121 assert.Equal(t, "text/plain; charset=utf-8", res.Header().Get("Content-Type")) 122 assert.Equal(t, "Not Found\n", res.Body.String()) 123 }) 124 125 t.Run("json error", func(t *testing.T) { 126 res := httptest.NewRecorder() 127 req := httptest.NewRequest("GET", "/400/json", nil) 128 req.Header.Set("Accept", "application/json") 129 130 h.ServeHTTP(res, req) 131 132 assert.Equal(t, 400, res.Code) 133 assert.Equal(t, "application/json", res.Header().Get("Content-Type")) 134 assert.Equal(t, `{ "error": "bad_request" }`, res.Body.String()) 135 }) 136 } 137 138 func test(t *testing.T, c *up.Config) { 139 h, err := New(c, server) 140 assert.NoError(t, err, "init") 141 142 t.Run("200", nonError(h)) 143 t.Run("accepts text/html", acceptsHTML(h)) 144 t.Run("accepts text/*", acceptsText(h)) 145 t.Run("does not accept html", doesNotAcceptHTML(h)) 146 147 t.Run("exact", func(t *testing.T) { 148 res := httptest.NewRecorder() 149 req := httptest.NewRequest("GET", "/404", nil) 150 151 h.ServeHTTP(res, req) 152 153 assert.Equal(t, 404, res.Code) 154 assert.Equal(t, "", res.Header().Get("ETag")) 155 assert.Equal(t, "text/html; charset=utf-8", res.Header().Get("Content-Type")) 156 assert.Equal(t, "Sorry! Can't find that.\n", res.Body.String()) 157 }) 158 159 t.Run("range", func(t *testing.T) { 160 res := httptest.NewRecorder() 161 req := httptest.NewRequest("GET", "/500", nil) 162 163 h.ServeHTTP(res, req) 164 165 assert.Equal(t, 500, res.Code) 166 assert.Equal(t, "Accept", res.Header().Get("Vary")) 167 assert.Equal(t, "", res.Header().Get("ETag")) 168 assert.Equal(t, "text/html; charset=utf-8", res.Header().Get("Content-Type")) 169 assert.Equal(t, "500 – Internal Server Error\n", res.Body.String()) 170 }) 171 } 172 173 func nonError(h http.Handler) func(t *testing.T) { 174 return func(t *testing.T) { 175 res := httptest.NewRecorder() 176 req := httptest.NewRequest("GET", "/", nil) 177 178 h.ServeHTTP(res, req) 179 180 assert.Equal(t, 200, res.Code) 181 assert.Equal(t, "something", res.Header().Get("ETag")) 182 assert.Equal(t, "text/plain", res.Header().Get("Content-Type")) 183 assert.Equal(t, "Hello World", res.Body.String()) 184 } 185 } 186 187 func acceptsHTML(h http.Handler) func(t *testing.T) { 188 return func(t *testing.T) { 189 res := httptest.NewRecorder() 190 req := httptest.NewRequest("GET", "/400", nil) 191 req.Header.Set("Accept", "text/html") 192 193 h.ServeHTTP(res, req) 194 195 assert.Equal(t, 400, res.Code) 196 assert.Equal(t, "Accept", res.Header().Get("Vary")) 197 assert.Equal(t, "", res.Header().Get("ETag")) 198 assert.Equal(t, "text/html; charset=utf-8", res.Header().Get("Content-Type")) 199 assert.Contains(t, res.Body.String(), "<title>Bad Request – 400</title>", "title") 200 assert.Contains(t, res.Body.String(), `<span class="status">Bad Request</span>`, "status text") 201 assert.Contains(t, res.Body.String(), `<span class="code">400</span>`, "status code") 202 } 203 } 204 205 func acceptsText(h http.Handler) func(t *testing.T) { 206 return func(t *testing.T) { 207 res := httptest.NewRecorder() 208 req := httptest.NewRequest("GET", "/400", nil) 209 req.Header.Set("Accept", "text/*") 210 211 h.ServeHTTP(res, req) 212 213 assert.Equal(t, 400, res.Code) 214 assert.Equal(t, "Accept", res.Header().Get("Vary")) 215 assert.Equal(t, "", res.Header().Get("ETag")) 216 assert.Equal(t, "text/html; charset=utf-8", res.Header().Get("Content-Type")) 217 assert.Contains(t, res.Body.String(), "<title>Bad Request – 400</title>", "title") 218 assert.Contains(t, res.Body.String(), `<span class="status">Bad Request</span>`, "status text") 219 assert.Contains(t, res.Body.String(), `<span class="code">400</span>`, "status code") 220 } 221 } 222 223 func doesNotAcceptHTML(h http.Handler) func(t *testing.T) { 224 return func(t *testing.T) { 225 res := httptest.NewRecorder() 226 req := httptest.NewRequest("GET", "/400/json", nil) 227 req.Header.Set("Accept", "application/json") 228 229 h.ServeHTTP(res, req) 230 231 assert.Equal(t, 400, res.Code) 232 assert.Equal(t, "application/json", res.Header().Get("Content-Type")) 233 assert.Equal(t, `{ "error": "bad_request" }`, res.Body.String()) 234 } 235 }