goyave.dev/goyave/v5@v5.0.0-rc9.0.20240517145003-d3f977d0b9f3/status_handler_test.go (about) 1 package goyave 2 3 import ( 4 "bytes" 5 "io" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "goyave.dev/goyave/v5/config" 13 "goyave.dev/goyave/v5/slog" 14 "goyave.dev/goyave/v5/util/errors" 15 "goyave.dev/goyave/v5/validation" 16 ) 17 18 func prepareStatusHandlerTest() (*Request, *Response, *httptest.ResponseRecorder) { 19 server, err := New(Options{Config: config.LoadDefault()}) 20 if err != nil { 21 panic(err) 22 } 23 httpReq := httptest.NewRequest(http.MethodGet, "/test", nil) 24 req := NewRequest(httpReq) 25 recorder := httptest.NewRecorder() 26 resp := NewResponse(server, req, recorder) 27 return req, resp, recorder 28 } 29 30 func TestPanicStatusHandler(t *testing.T) { 31 t.Run("no_debug", func(t *testing.T) { 32 req, resp, recorder := prepareStatusHandlerTest() 33 resp.server.config.Set("app.debug", false) 34 handler := &PanicStatusHandler{} 35 handler.Init(resp.server) 36 37 resp.err = errors.New("test error").(*errors.Error) 38 handler.Handle(resp, req) 39 res := recorder.Result() 40 body, err := io.ReadAll(res.Body) 41 assert.NoError(t, res.Body.Close()) 42 require.NoError(t, err) 43 44 assert.Equal(t, "{\"error\":\"Internal Server Error\"}\n", string(body)) 45 }) 46 47 t.Run("debug", func(t *testing.T) { 48 req, resp, recorder := prepareStatusHandlerTest() 49 resp.server.config.Set("app.debug", true) 50 logBuffer := &bytes.Buffer{} 51 resp.server.Logger = slog.New(slog.NewHandler(false, logBuffer)) 52 handler := &PanicStatusHandler{} 53 handler.Init(resp.server) 54 55 resp.err = errors.New("test error").(*errors.Error) 56 handler.Handle(resp, req) 57 res := recorder.Result() 58 body, err := io.ReadAll(res.Body) 59 assert.NoError(t, res.Body.Close()) 60 require.NoError(t, err) 61 62 assert.Equal(t, "{\"error\":\"test error\"}\n", string(body)) 63 64 // Error and stacktrace already printed by the recovery middleware or `response.Error` 65 // (those are not executed in this test, thus leaving the log buffer empty) 66 assert.Empty(t, logBuffer.String()) 67 }) 68 69 t.Run("nil_error", func(t *testing.T) { 70 req, resp, recorder := prepareStatusHandlerTest() 71 resp.server.config.Set("app.debug", true) 72 logBuffer := &bytes.Buffer{} 73 resp.server.Logger = slog.New(slog.NewHandler(false, logBuffer)) 74 handler := &PanicStatusHandler{} 75 handler.Init(resp.server) 76 77 handler.Handle(resp, req) 78 res := recorder.Result() 79 body, err := io.ReadAll(res.Body) 80 assert.NoError(t, res.Body.Close()) 81 require.NoError(t, err) 82 83 assert.Equal(t, "{\"error\":null}\n", string(body)) 84 85 // Error and stacktrace are not printed to console because recovery middleware 86 // is not executed (no error raised, we just set the response status to 500 for example) 87 assert.Empty(t, logBuffer.String()) 88 }) 89 } 90 91 func TestErrorStatusHandler(t *testing.T) { 92 req, resp, recorder := prepareStatusHandlerTest() 93 handler := &ErrorStatusHandler{} 94 handler.Init(resp.server) 95 96 resp.Status(http.StatusNotFound) 97 98 handler.Handle(resp, req) 99 100 res := recorder.Result() 101 body, err := io.ReadAll(res.Body) 102 assert.NoError(t, res.Body.Close()) 103 require.NoError(t, err) 104 105 assert.Equal(t, "{\"error\":\"Not Found\"}\n", string(body)) 106 } 107 108 func TestValidationStatusHandler(t *testing.T) { 109 req, resp, recorder := prepareStatusHandlerTest() 110 handler := &ValidationStatusHandler{} 111 handler.Init(resp.server) 112 113 req.Extra[ExtraValidationError{}] = &validation.Errors{ 114 Errors: []string{"The body is required"}, 115 Fields: validation.FieldsErrors{ 116 "field": &validation.Errors{Errors: []string{"The field is required"}}, 117 }, 118 } 119 req.Extra[ExtraQueryValidationError{}] = &validation.Errors{ 120 Fields: validation.FieldsErrors{ 121 "query": &validation.Errors{Errors: []string{"The query is required"}}, 122 }, 123 } 124 125 handler.Handle(resp, req) 126 127 res := recorder.Result() 128 body, err := io.ReadAll(res.Body) 129 assert.NoError(t, res.Body.Close()) 130 require.NoError(t, err) 131 132 assert.Equal(t, "{\"error\":{\"body\":{\"fields\":{\"field\":{\"errors\":[\"The field is required\"]}},\"errors\":[\"The body is required\"]},\"query\":{\"fields\":{\"query\":{\"errors\":[\"The query is required\"]}}}}}\n", string(body)) 133 }