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  }