From 904ee95d63bd87c9b0f1b26723fe60a93a8032d8 Mon Sep 17 00:00:00 2001 From: vinchent Date: Sun, 14 Jul 2024 14:51:12 +0200 Subject: [PATCH] add tests for availabilityJson --- internal/handlers/handlers.go | 49 ++++++++--- internal/handlers/handlers_test.go | 110 ++++++++++++++++++++---- internal/repository/dbrepo/test-repo.go | 5 +- 3 files changed, 133 insertions(+), 31 deletions(-) diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 821afcc..4990fc4 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -277,8 +277,14 @@ type jsonResponse struct { // AvailabilityJSON is the search for availability page handler func (m *Repository) AvailabilityJSON(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { - m.App.Session.Put(r.Context(), "error", "can't parse form") - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + // can't parse form, so return appropriate json + resp := jsonResponse{ + OK: false, + Message: "Internal server error", + } + out, _ := json.MarshalIndent(resp, "", " ") + w.Header().Set("Content-Type", "application/json") + w.Write(out) return } sd := r.Form.Get("start") @@ -287,24 +293,48 @@ func (m *Repository) AvailabilityJSON(w http.ResponseWriter, r *http.Request) { layout := "2006-01-02" startDate, err := time.Parse(layout, sd) if err != nil { - helpers.ServerError(w, err) + resp := jsonResponse{ + OK: false, + Message: "Wrong startDate", + } + out, _ := json.MarshalIndent(resp, "", " ") + w.Header().Set("Content-Type", "application/json") + w.Write(out) return } endDate, err := time.Parse(layout, ed) if err != nil { - helpers.ServerError(w, err) + resp := jsonResponse{ + OK: false, + Message: "Wrong endDate", + } + out, _ := json.MarshalIndent(resp, "", " ") + w.Header().Set("Content-Type", "application/json") + w.Write(out) return } roomID, err := strconv.Atoi(r.Form.Get("room_id")) if err != nil { - helpers.ServerError(w, err) + resp := jsonResponse{ + OK: false, + Message: "Wrong roomID", + } + out, _ := json.MarshalIndent(resp, "", " ") + w.Header().Set("Content-Type", "application/json") + w.Write(out) return } available, err := m.DB.SearchAvailabilityByDatesByRoomID(startDate, endDate, roomID) if err != nil { - helpers.ServerError(w, err) + resp := jsonResponse{ + OK: false, + Message: "Error connecting to database", + } + out, _ := json.MarshalIndent(resp, "", " ") + w.Header().Set("Content-Type", "application/json") + w.Write(out) return } @@ -316,11 +346,8 @@ func (m *Repository) AvailabilityJSON(w http.ResponseWriter, r *http.Request) { RoomID: strconv.Itoa(roomID), } - out, err := json.MarshalIndent(resp, "", " ") - if err != nil { - helpers.ServerError(w, err) - return - } + // No error check because all aspects of the json are handled + out, _ := json.MarshalIndent(resp, "", " ") w.Header().Set("Content-Type", "application/json") diff --git a/internal/handlers/handlers_test.go b/internal/handlers/handlers_test.go index da666cb..50c3e6b 100644 --- a/internal/handlers/handlers_test.go +++ b/internal/handlers/handlers_test.go @@ -2,11 +2,13 @@ package handlers import ( "context" + "encoding/json" "fmt" "go-udemy-web-1/internal/models" "log" "net/http" "net/http/httptest" + "strconv" "strings" "testing" "time" @@ -110,7 +112,6 @@ func TestRepository_MakeReservation(t *testing.T) { var postMakeReservationTests = []struct { name string reservationInfo []postData - roomID int expectedStatusCode int }{ @@ -125,7 +126,7 @@ var postMakeReservationTests = []struct { {key: "start_date", value: "2050-01-01"}, {key: "end_date", value: "2050-01-02"}, }, - 1, http.StatusSeeOther, + http.StatusSeeOther, }, { "no_session", @@ -138,24 +139,20 @@ var postMakeReservationTests = []struct { {key: "start_date", value: "2050-01-01"}, {key: "end_date", value: "2050-01-02"}, }, - 0, http.StatusTemporaryRedirect, - }, - { - "no_post_data", - []postData{}, - 0, http.StatusTemporaryRedirect, + http.StatusTemporaryRedirect, }, + {"no_post_data", []postData{}, http.StatusOK}, { "missing first name", []postData{ {key: "last_name", value: "Smith"}, {key: "email", value: "john@smith.com"}, {key: "phone", value: "1234"}, - {key: "room_id", value: "0"}, + {key: "room_id", value: "1"}, {key: "start_date", value: "2050-01-01"}, {key: "end_date", value: "2050-01-02"}, }, - 1, http.StatusOK, + http.StatusOK, }, { "wrong first name", @@ -164,11 +161,11 @@ var postMakeReservationTests = []struct { {key: "last_name", value: "Smith"}, {key: "email", value: "john@smith.com"}, {key: "phone", value: "1234"}, - {key: "room_id", value: "0"}, + {key: "room_id", value: "1"}, {key: "start_date", value: "2050-01-01"}, {key: "end_date", value: "2050-01-02"}, }, - 1, http.StatusOK, + http.StatusOK, }, { "wrong email", @@ -177,11 +174,11 @@ var postMakeReservationTests = []struct { {key: "last_name", value: "Smith"}, {key: "email", value: "john@smith"}, {key: "phone", value: "1234"}, - {key: "room_id", value: "0"}, + {key: "room_id", value: "1"}, {key: "start_date", value: "2050-01-01"}, {key: "end_date", value: "2050-01-02"}, }, - 1, http.StatusOK, + http.StatusOK, }, { "insert reservation error", @@ -194,7 +191,7 @@ var postMakeReservationTests = []struct { {key: "start_date", value: "2050-01-01"}, {key: "end_date", value: "2050-01-02"}, }, - 2, http.StatusTemporaryRedirect, + http.StatusTemporaryRedirect, }, { "insert room restriction error", @@ -207,26 +204,33 @@ var postMakeReservationTests = []struct { {key: "start_date", value: "2050-01-01"}, {key: "end_date", value: "2050-01-02"}, }, - 100, http.StatusTemporaryRedirect, + http.StatusTemporaryRedirect, }, } func TestRepository_PostMakeReservation(t *testing.T) { for _, test := range postMakeReservationTests { + roomID := 1 var reqBody string if len(test.reservationInfo) > 0 { + if test.reservationInfo[0].key == "room_id" { + roomID, _ = strconv.Atoi(test.reservationInfo[0].value) + } reqBody = fmt.Sprintf("%s=%s", test.reservationInfo[0].key, test.reservationInfo[0].value) for _, element := range test.reservationInfo[1:] { reqBody = fmt.Sprintf("%s&%s=%s", reqBody, element.key, element.value) + if element.key == "room_id" { + roomID, _ = strconv.Atoi(element.value) + } } } layout := "2006-01-02" sd, _ := time.Parse(layout, "2050-01-01") ed, _ := time.Parse(layout, "2050-01-02") reservation := models.Reservation{ - RoomID: test.roomID, + RoomID: roomID, StartDate: sd, EndDate: ed, } @@ -237,7 +241,7 @@ func TestRepository_PostMakeReservation(t *testing.T) { req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := httptest.NewRecorder() - if test.roomID == 0 { + if roomID == 0 { session.Put(ctx, "reservation", nil) } else { session.Put(ctx, "reservation", reservation) @@ -247,12 +251,80 @@ func TestRepository_PostMakeReservation(t *testing.T) { handler.ServeHTTP(rr, req) if rr.Code != test.expectedStatusCode { - fmt.Printf("for %s, reservation handler returned response code: got %d, wanted %d\n", + t.Errorf("for %s, reservation handler returned response code: got %d, wanted %d\n", test.name, rr.Code, test.expectedStatusCode) } } } +// }}} +// {{{ Test AvailabilityJSON + +var availabilityJSONTests = []struct { + name string + queryInfo []postData + expectedStatusJSON jsonResponse +}{ + {"ok", []postData{ + {key: "start", value: "2050-01-01"}, + {key: "end", value: "2050-01-02"}, + {key: "room_id", value: "1"}, + }, jsonResponse{ + OK: true, + Message: "", + StartDate: "2050-01-01", + EndDate: "2050-01-02", + RoomID: "1", + }}, + {"wrong date", []postData{ + {key: "start", value: "2050-01"}, + {key: "end", value: "2050-01-02"}, + {key: "room_id", value: "1"}, + }, jsonResponse{ + OK: false, + Message: "Wrong startDate", + }}, +} + +func Test_AvailabilityJSON(t *testing.T) { + for _, test := range availabilityJSONTests { + var reqBody string + reqBody = fmt.Sprintf("%s=%s", test.queryInfo[0].key, + test.queryInfo[0].value) + for _, element := range test.queryInfo[1:] { + reqBody = fmt.Sprintf("%s&%s=%s", reqBody, element.key, + element.value) + } + + req, _ := http.NewRequest("POST", "/make-reservation", strings.NewReader(reqBody)) + ctx := getCtx(req) + req = req.WithContext(ctx) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + rr := httptest.NewRecorder() + + handler := http.HandlerFunc(Repo.AvailabilityJSON) + handler.ServeHTTP(rr, req) + + if rr.Code != http.StatusOK { + t.Errorf("for %s, reservation handler returned response code: got %d, wanted %d\n", + test.name, rr.Code, http.StatusOK) + } + + var j jsonResponse + err := json.Unmarshal(rr.Body.Bytes(), &j) + if err != nil { + t.Errorf("for %s, failed to parse json", test.name) + } + if j != test.expectedStatusJSON { + expected, _ := json.MarshalIndent(test.expectedStatusJSON, "", " ") + t.Errorf("for %s, returned json is wrong, expected: %s, returned: %s", + test.name, expected, rr.Body.String()) + } + + } +} + // }}} // {{{ Test Helpers diff --git a/internal/repository/dbrepo/test-repo.go b/internal/repository/dbrepo/test-repo.go index 6a1a3ad..5f495b1 100644 --- a/internal/repository/dbrepo/test-repo.go +++ b/internal/repository/dbrepo/test-repo.go @@ -29,7 +29,10 @@ func (m *testDBRepo) InsertRoomRestriction(r models.RoomRestriction) error { // SearchAvailabilityByDatesByRoomID returns true if availability exists for roomID, and false if no availability func (m *testDBRepo) SearchAvailabilityByDatesByRoomID(start, end time.Time, roomID int) (bool, error) { - return false, nil + if roomID == 2 { + return false, errors.New("deliberate error") + } + return true, nil } // SearchAvailabilityForAllRooms returns a slice of rooms, if any, for given date range