diff options
Diffstat (limited to 'api/guestbook')
| -rw-r--r-- | api/guestbook/guestbook.go | 85 | ||||
| -rw-r--r-- | api/guestbook/guestbook_test.go | 136 |
2 files changed, 221 insertions, 0 deletions
diff --git a/api/guestbook/guestbook.go b/api/guestbook/guestbook.go new file mode 100644 index 0000000..60a7b4b --- /dev/null +++ b/api/guestbook/guestbook.go @@ -0,0 +1,85 @@ +package guestbook + +import ( + "log" + "net/http" + "strings" + + "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/types" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/database" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/utils" +) + +func validateGuestbookEntry(entry *database.GuestbookEntry) []string { + errors := []string{} + + if entry.Name == "" { + errors = append(errors, "name is required") + } + + if entry.Message == "" { + errors = append(errors, "message is required") + } + + messageLength := len(entry.Message) + if messageLength > 500 { + errors = append(errors, "message cannot be longer than 500 characters") + } + + newLines := strings.Count(entry.Message, "\n") + if newLines > 10 { + errors = append(errors, "message cannot contain more than 10 new lines") + } + + return errors +} + +func SignGuestbookContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { + return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { + name := req.FormValue("name") + message := req.FormValue("message") + + formErrors := types.FormError{ + Errors: []string{}, + } + + entry := &database.GuestbookEntry{ + ID: utils.RandomId(), + Name: name, + Message: message, + } + formErrors.Errors = append(formErrors.Errors, validateGuestbookEntry(entry)...) + + if len(formErrors.Errors) == 0 { + _, err := database.SaveGuestbookEntry(context.DBConn, entry) + if err != nil { + log.Println(err) + formErrors.Errors = append(formErrors.Errors, "failed to save entry") + } + } + + if len(formErrors.Errors) > 0 { + (*context.TemplateData)["FormError"] = formErrors + (*context.TemplateData)["EntryForm"] = entry + resp.WriteHeader(http.StatusBadRequest) + + return failure(context, req, resp) + } + + return success(context, req, resp) + } +} + +func ListGuestbookContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { + return func(success types.Continuation, failure types.Continuation) types.ContinuationChain { + entries, err := database.GetGuestbookEntries(context.DBConn) + if err != nil { + log.Println(err) + resp.WriteHeader(http.StatusInternalServerError) + return failure(context, req, resp) + } + + (*context.TemplateData)["GuestbookEntries"] = entries + return success(context, req, resp) + } +} diff --git a/api/guestbook/guestbook_test.go b/api/guestbook/guestbook_test.go new file mode 100644 index 0000000..9fd6c62 --- /dev/null +++ b/api/guestbook/guestbook_test.go @@ -0,0 +1,136 @@ +package guestbook_test + +import ( + "database/sql" + "net/http" + "net/http/httptest" + "os" + "testing" + + "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/guestbook" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/api/types" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/args" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/database" + "git.hatecomputers.club/hatecomputers/hatecomputers.club/utils" +) + +func IdContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain { + return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain { + return success(context, req, resp) + } +} + +func setup() (*sql.DB, *types.RequestContext, func()) { + randomDb := utils.RandomId() + + testDb := database.MakeConn(&randomDb) + database.Migrate(testDb) + + context := &types.RequestContext{ + DBConn: testDb, + Args: &args.Arguments{}, + TemplateData: &(map[string]interface{}{}), + } + + return testDb, context, func() { + testDb.Close() + os.Remove(randomDb) + } +} + +func TestValidGuestbookPutsInDatabase(t *testing.T) { + db, context, cleanup := setup() + defer cleanup() + + entries, err := database.GetGuestbookEntries(db) + if err != nil { + t.Fatal(err) + } + if len(entries) > 0 { + t.Errorf("expected no entries, got entries") + } + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + guestbook.SignGuestbookContinuation(context, r, w)(IdContinuation, IdContinuation) + })) + defer ts.Close() + + req := httptest.NewRequest("POST", ts.URL, nil) + req.Form = map[string][]string{ + "name": {"test"}, + "message": {"test"}, + } + + w := httptest.NewRecorder() + ts.Config.Handler.ServeHTTP(w, req) + + if w.Code != http.StatusOK { + t.Errorf("expected status code 200, got %d", w.Code) + } + + entries, err = database.GetGuestbookEntries(db) + if err != nil { + t.Fatal(err) + } + + if len(entries) != 1 { + t.Errorf("expected 1 entry, got %d", len(entries)) + } + + if entries[0].Name != req.FormValue("name") { + t.Errorf("expected name %s, got %s", req.FormValue("name"), entries[0].Name) + } +} + +func TestInvalidGuestbookNotFoundInDatabase(t *testing.T) { + db, context, cleanup := setup() + defer cleanup() + + entries, err := database.GetGuestbookEntries(db) + if err != nil { + t.Fatal(err) + } + if len(entries) > 0 { + t.Errorf("expected no entries, got entries") + } + + testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + guestbook.SignGuestbookContinuation(context, r, w)(IdContinuation, IdContinuation) + })) + defer testServer.Close() + + reallyLongStringThatWouldTakeTooMuchSpace := "a\na\na\na\na\na\na\na\na\na\na\n" + invalidRequests := []struct { + name string + message string + }{ + {"", "test"}, + {"test", ""}, + {"", ""}, + {"test", reallyLongStringThatWouldTakeTooMuchSpace}, + } + + for _, form := range invalidRequests { + req := httptest.NewRequest("POST", testServer.URL, nil) + req.Form = map[string][]string{ + "name": {form.name}, + "message": {form.message}, + } + + responseRecorder := httptest.NewRecorder() + testServer.Config.Handler.ServeHTTP(responseRecorder, req) + + if responseRecorder.Code != http.StatusBadRequest { + t.Errorf("expected status code 400, got %d", responseRecorder.Code) + } + } + + entries, err = database.GetGuestbookEntries(db) + if err != nil { + t.Fatal(err) + } + + if len(entries) != 0 { + t.Errorf("expected 0 entries, got %d", len(entries)) + } +} |
