package handlers import ( "context" "fmt" "go-udemy-web-1/internal/models" "log" "net/http" "net/http/httptest" "strings" "testing" "time" ) type postData struct { key string value string } var theTests = []struct { name string url string method string expectedStatusCode int }{ {"home", "/", "GET", http.StatusOK}, {"about", "/about", "GET", http.StatusOK}, {"gq", "/generals-quarters", "GET", http.StatusOK}, {"ms", "/majors-suite", "GET", http.StatusOK}, {"sa", "/availability", "GET", http.StatusOK}, {"contact", "/contact", "GET", http.StatusOK}, // {"post-search-avail", "/availability", "POST", []postData{ // {key: "start", value: "2020-01-01"}, // {key: "end", value: "2020-01-02"}, // }, http.StatusOK}, // {"post-search-avail-json", "/availability-json", "POST", []postData{ // {key: "start", value: "2020-01-01"}, // {key: "end", value: "2020-01-02"}, // }, http.StatusOK}, // {"make-reservation", "/make-reservation", "POST", []postData{ // {key: "first_name", value: "John"}, // {key: "last_name", value: "Smith"}, // {key: "email", value: "me@here.com"}, // {key: "phone", value: "12345"}, // }, http.StatusOK}, } func TestHandlers(t *testing.T) { routes := getRoutes() ts := httptest.NewTLSServer(routes) defer ts.Close() for _, e := range theTests { resp, err := ts.Client().Get(ts.URL + e.url) if err != nil { t.Log(err) t.Fatal(err) } if resp.StatusCode != e.expectedStatusCode { t.Errorf("for %s, expected %d but got %d", e.name, e.expectedStatusCode, resp.StatusCode) } } } // {{{ Make Reservation Tests var makeReservationTests = []struct { name string roomID int expectedStatusCode int }{ {"ok", 1, http.StatusOK}, {"no session", 0, http.StatusTemporaryRedirect}, {"non-existant room", 100, http.StatusTemporaryRedirect}, } func TestRepository_MakeReservation(t *testing.T) { for _, test := range makeReservationTests { reservation := models.Reservation{ RoomID: test.roomID, Room: models.Room{ ID: test.roomID, RoomName: "Room name", }, } req, _ := http.NewRequest("GET", "/make-reservation", nil) ctx := getCtx(req) req = req.WithContext(ctx) rr := httptest.NewRecorder() if test.roomID == 0 { session.Put(ctx, "reservation", nil) } else { session.Put(ctx, "reservation", reservation) } handler := http.HandlerFunc(Repo.MakeReservation) handler.ServeHTTP(rr, req) if rr.Code != test.expectedStatusCode { t.Errorf("for %s, reservation handler returned response code: got %d, wanted %d", test.name, rr.Code, http.StatusOK) } } } // }}} // {{{ PostMakeReservation tests var postMakeReservationTests = []struct { name string reservationInfo []string roomID int expectedStatusCode int }{ { "ok", []string{ "first_name=John", "last_name=Smith", "email=john@smith.com", "phone=1234", "room_id=1", "start_date=2050-01-01", "end_date=2050-01-02", }, 1, http.StatusSeeOther, }, { "no_session", []string{ "first_name=John", "last_name=Smith", "email=john@smith.com", "phone=1234", "room_id=0", "start_date=2050-01-01", "end_date=2050-01-02", }, 0, http.StatusTemporaryRedirect, }, { "no_post_data", []string{}, 0, http.StatusTemporaryRedirect, }, { "missing first name", []string{ "last_name=Smith", "email=john@smith.com", "phone=1234", "room_id=1", "start_date=2050-01-01", "end_date=2050-01-02", }, 1, http.StatusOK, }, { "wrong first name", []string{ "first_name=J", "last_name=Smith", "email=john@smith.com", "phone=1234", "room_id=1", "start_date=2050-01-01", "end_date=2050-01-02", }, 1, http.StatusOK, }, { "wrong email", []string{ "first_name=John", "last_name=Smith", "email=john@smith", "phone=1234", "room_id=1", "start_date=2050-01-01", "end_date=2050-01-02", }, 1, http.StatusOK, }, { "insert reservation error", []string{ "first_name=John", "last_name=Smith", "email=john@smith.com", "phone=1234", "room_id=2", "start_date=2050-01-01", "end_date=2050-01-02", }, 2, http.StatusTemporaryRedirect, }, { "insert room restriction error", []string{ "first_name=John", "last_name=Smith", "email=john@smith.com", "phone=1234", "room_id=100", "start_date=2050-01-01", "end_date=2050-01-02", }, 100, http.StatusTemporaryRedirect, }, } func TestRepository_PostMakeReservation(t *testing.T) { for _, test := range postMakeReservationTests { var reqBody string if len(test.reservationInfo) > 0 { reqBody = test.reservationInfo[0] for _, element := range test.reservationInfo[1:] { reqBody = fmt.Sprintf("%s&%s", reqBody, element) } } layout := "2006-01-02" sd, _ := time.Parse(layout, "2050-01-01") ed, _ := time.Parse(layout, "2050-01-02") reservation := models.Reservation{ RoomID: test.roomID, StartDate: sd, EndDate: ed, } 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() if test.roomID == 0 { session.Put(ctx, "reservation", nil) } else { session.Put(ctx, "reservation", reservation) } handler := http.HandlerFunc(Repo.PostMakeReservation) handler.ServeHTTP(rr, req) if rr.Code != test.expectedStatusCode { fmt.Printf("for %s, reservation handler returned response code: got %d, wanted %d", test.name, rr.Code, test.expectedStatusCode) } } } // }}} // {{{ Test Helpers func getCtx(req *http.Request) context.Context { ctx, err := session.Load(req.Context(), req.Header.Get("X-Session")) if err != nil { log.Println(err) } return ctx } // }}}