package hws_test import ( "bytes" "context" "io" "net/http" "net/http/httptest" "testing" "git.haelnorr.com/h/golib/hws" "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) type goodPage struct{} type badPage struct{} func goodRender(error hws.HWSError) (hws.ErrorPage, error) { return goodPage{}, nil } func badRender1(error hws.HWSError) (hws.ErrorPage, error) { return badPage{}, nil } func badRender2(error hws.HWSError) (hws.ErrorPage, error) { return nil, errors.New("I'm an error") } func (g goodPage) Render(ctx context.Context, w io.Writer) error { w.Write([]byte("Test write to ResponseWriter")) return nil } func (b badPage) Render(ctx context.Context, w io.Writer) error { return nil } func Test_AddErrorPage(t *testing.T) { var buf bytes.Buffer server := createTestServer(t, &buf) goodRender := goodRender badRender1 := badRender1 badRender2 := badRender2 tests := []struct { name string renderer hws.ErrorPageFunc valid bool }{ { name: "Valid Renderer", renderer: goodRender, valid: true, }, { name: "Invalid Renderer 1", renderer: badRender1, valid: false, }, { name: "Invalid Renderer 2", renderer: badRender2, valid: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := server.AddErrorPage(tt.renderer) if tt.valid { assert.NoError(t, err) } else { assert.Error(t, err) } }) } } func Test_ThrowError(t *testing.T) { var buf bytes.Buffer server := createTestServer(t, &buf) rr := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) t.Run("Server not started", func(t *testing.T) { err := server.ThrowError(rr, req, hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "Error", Error: errors.New("Error"), }) assert.Error(t, err) }) startTestServer(t, server) defer server.Shutdown(t.Context()) tests := []struct { name string request *http.Request error hws.HWSError valid bool }{ { name: "No HWSError.Status code", request: nil, error: hws.HWSError{}, valid: false, }, { name: "Negative HWSError.Status code", request: nil, error: hws.HWSError{StatusCode: -1}, valid: false, }, { name: "No HWSError.Message", request: nil, error: hws.HWSError{StatusCode: http.StatusInternalServerError}, valid: false, }, { name: "No HWSError.Error", request: nil, error: hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "An error occured", }, valid: false, }, { name: "No request provided", request: nil, error: hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "An error occured", Error: errors.New("Error"), }, valid: false, }, { name: "Valid", request: httptest.NewRequest("GET", "/", nil), error: hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "An error occured", Error: errors.New("Error"), }, valid: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { rr := httptest.NewRecorder() err := server.ThrowError(rr, tt.request, tt.error) if tt.valid { assert.NoError(t, err) } else { t.Log(err) assert.Error(t, err) } }) } t.Run("Log level set correctly", func(t *testing.T) { buf.Reset() rr := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) err := server.ThrowError(rr, req, hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "An error occured", Error: errors.New("Error"), Level: hws.ErrorWARN, }) assert.NoError(t, err) _, err = buf.ReadString([]byte(" ")[0]) loglvl, err := buf.ReadString([]byte(" ")[0]) assert.NoError(t, err) if loglvl != "\x1b[33mWRN\x1b[0m " { err = errors.New("Log level not set correctly") } assert.NoError(t, err) buf.Reset() err = server.ThrowError(rr, req, hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "An error occured", Error: errors.New("Error"), }) assert.NoError(t, err) _, err = buf.ReadString([]byte(" ")[0]) loglvl, err = buf.ReadString([]byte(" ")[0]) assert.NoError(t, err) if loglvl != "\x1b[31mERR\x1b[0m " { err = errors.New("Log level not set correctly") } assert.NoError(t, err) }) t.Run("Error page doesnt render if no error page set", func(t *testing.T) { // Must be run before adding the error page to the test server rr := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) err := server.ThrowError(rr, req, hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "An error occured", Error: errors.New("Error"), RenderErrorPage: true, }) assert.NoError(t, err) body := rr.Body.String() if body != "" { assert.Error(t, nil) } }) t.Run("Error page renders", func(t *testing.T) { rr := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) // Adding the error page will carry over to all future tests and cant be undone server.AddErrorPage(goodRender) err := server.ThrowError(rr, req, hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "An error occured", Error: errors.New("Error"), RenderErrorPage: true, }) assert.NoError(t, err) body := rr.Body.String() if body == "" { assert.Error(t, nil) } }) t.Run("Error page doesnt render if no told to render", func(t *testing.T) { // Error page already added to server rr := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) err := server.ThrowError(rr, req, hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "An error occured", Error: errors.New("Error"), }) assert.NoError(t, err) body := rr.Body.String() if body != "" { assert.Error(t, nil) } }) server.Shutdown(t.Context()) t.Run("Doesn't error if no logger added to server", func(t *testing.T) { server, err := hws.NewServer(&hws.Config{ Host: "127.0.0.1", Port: randomPort(), }) require.NoError(t, err) err = server.AddRoutes(hws.Route{ Path: "/", Method: hws.MethodGET, Handler: testHandler, }) require.NoError(t, err) err = server.Start(t.Context()) require.NoError(t, err) <-server.Ready() rr := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) err = server.ThrowError(rr, req, hws.HWSError{ StatusCode: http.StatusInternalServerError, Message: "An error occured", Error: errors.New("Error"), }) assert.NoError(t, err) }) }