package handlers import ( "context" "encoding/json" "fmt" "github.com/tsawler/bookings/internal/driver" "github.com/tsawler/bookings/internal/models" "log" "net/http" "net/http/httptest" "net/url" "reflect" "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", "/search-availability", "GET", http.StatusOK}, {"contact", "/contact", "GET", http.StatusOK}, {"non-existent", "/green/eggs/and/ham", "GET", http.StatusNotFound}, {"login", "/user/login", "GET", http.StatusOK}, {"logout", "/user/logout", "GET", http.StatusOK}, {"dashboard", "/admin/dashboard", "GET", http.StatusOK}, {"new res", "/admin/reservations-new", "GET", http.StatusOK}, {"all res", "/admin/reservations-all", "GET", http.StatusOK}, {"show res", "/admin/reservations/new/1/show", "GET", http.StatusOK}, {"show res cal", "/admin/reservations-calendar", "GET", http.StatusOK}, {"show res cal with params", "/admin/reservations-calendar?y=2020&m=1", "GET", http.StatusOK}, } // TestHandlers tests all routes that don't require extra tests (gets) 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) } } } // data for the Reservation handler, /make-reservation route var reservationTests = []struct { name string reservation models.Reservation expectedStatusCode int expectedLocation string expectedHTML string }{ { name: "reservation-in-session", reservation: models.Reservation{ RoomID: 1, Room: models.Room{ ID: 1, RoomName: "General's Quarters", }, }, expectedStatusCode: http.StatusOK, expectedHTML: `action="/make-reservation"`, }, { name: "reservation-not-in-session", reservation: models.Reservation{}, expectedStatusCode: http.StatusSeeOther, expectedLocation: "/", expectedHTML: "", }, { name: "non-existent-room", reservation: models.Reservation{ RoomID: 100, Room: models.Room{ ID: 100, RoomName: "General's Quarters", }, }, expectedStatusCode: http.StatusSeeOther, expectedLocation: "/", expectedHTML: "", }, } // TestReservation tests the reservation handler func TestReservation(t *testing.T) { for _, e := range reservationTests { req, _ := http.NewRequest("GET", "/make-reservation", nil) ctx := getCtx(req) req = req.WithContext(ctx) rr := httptest.NewRecorder() if e.reservation.RoomID > 0 { session.Put(ctx, "reservation", e.reservation) } handler := http.HandlerFunc(Repo.Reservation) handler.ServeHTTP(rr, req) if rr.Code != e.expectedStatusCode { t.Errorf("%s returned wrong response code: got %d, wanted %d", e.name, rr.Code, e.expectedStatusCode) } if e.expectedLocation != "" { // get the URL from test actualLoc, _ := rr.Result().Location() if actualLoc.String() != e.expectedLocation { t.Errorf("failed %s: expected location %s, but got location %s", e.name, e.expectedLocation, actualLoc.String()) } } if e.expectedHTML != "" { // read the response body into a string html := rr.Body.String() if !strings.Contains(html, e.expectedHTML) { t.Errorf("failed %s: expected to find %s but did not", e.name, e.expectedHTML) } } } } // postReservationTests is the test data for hte PostReservation handler test var postReservationTests = []struct { name string postedData url.Values expectedResponseCode int expectedLocation string expectedHTML string }{ { name: "valid-data", postedData: url.Values{ "start_date": {"2050-01-01"}, "end_date": {"2050-01-02"}, "first_name": {"John"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, "room_id": {"1"}, }, expectedResponseCode: http.StatusSeeOther, expectedHTML: "", expectedLocation: "/reservation-summary", }, { name: "missing-post-body", postedData: nil, expectedResponseCode: http.StatusSeeOther, expectedHTML: "", expectedLocation: "/", }, { name: "invalid-start-date", postedData: url.Values{ "start_date": {"invalid"}, "end_date": {"2050-01-02"}, "first_name": {"John"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, "room_id": {"1"}, }, expectedResponseCode: http.StatusSeeOther, expectedHTML: "", expectedLocation: "/", }, { name: "invalid-end-date", postedData: url.Values{ "start_date": {"2050-01-01"}, "end_date": {"end"}, "first_name": {"John"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, "room_id": {"1"}, }, expectedResponseCode: http.StatusSeeOther, expectedHTML: "", expectedLocation: "/", }, { name: "invalid-room-id", postedData: url.Values{ "start_date": {"2050-01-01"}, "end_date": {"2050-01-02"}, "first_name": {"John"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, "room_id": {"invalid"}, }, expectedResponseCode: http.StatusSeeOther, expectedHTML: "", expectedLocation: "/", }, { name: "invalid-data", postedData: url.Values{ "start_date": {"2050-01-01"}, "end_date": {"2050-01-02"}, "first_name": {"J"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, "room_id": {"1"}, }, expectedResponseCode: http.StatusOK, expectedHTML: `action="/make-reservation"`, expectedLocation: "", }, { name: "database-insert-fails-reservation", postedData: url.Values{ "start_date": {"2050-01-01"}, "end_date": {"2050-01-02"}, "first_name": {"John"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, "room_id": {"2"}, }, expectedResponseCode: http.StatusSeeOther, expectedHTML: "", expectedLocation: "/", }, { name: "database-insert-fails-restriction", postedData: url.Values{ "start_date": {"2050-01-01"}, "end_date": {"2050-01-02"}, "first_name": {"John"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, "room_id": {"1000"}, }, expectedResponseCode: http.StatusSeeOther, expectedHTML: "", expectedLocation: "/", }, } // TestPostReservation tests the PostReservation handler func TestPostReservation(t *testing.T) { for _, e := range postReservationTests { var req *http.Request if e.postedData != nil { req, _ = http.NewRequest("POST", "/make-reservation", strings.NewReader(e.postedData.Encode())) } else { req, _ = http.NewRequest("POST", "/make-reservation", nil) } ctx := getCtx(req) req = req.WithContext(ctx) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := httptest.NewRecorder() handler := http.HandlerFunc(Repo.PostReservation) handler.ServeHTTP(rr, req) if rr.Code != e.expectedResponseCode { t.Errorf("%s returned wrong response code: got %d, wanted %d", e.name, rr.Code, e.expectedResponseCode) } if e.expectedLocation != "" { // get the URL from test actualLoc, _ := rr.Result().Location() if actualLoc.String() != e.expectedLocation { t.Errorf("failed %s: expected location %s, but got location %s", e.name, e.expectedLocation, actualLoc.String()) } } if e.expectedHTML != "" { // read the response body into a string html := rr.Body.String() if !strings.Contains(html, e.expectedHTML) { t.Errorf("failed %s: expected to find %s but did not", e.name, e.expectedHTML) } } } } func TestNewRepo(t *testing.T) { var db driver.DB testRepo := NewRepo(&app, &db) if reflect.TypeOf(testRepo).String() != "*handlers.Repository" { t.Errorf("Did not get correct type from NewRepo: got %s, wanted *Repository", reflect.TypeOf(testRepo).String()) } } // testAvailabilityJSONData is data for the AvailabilityJSON handler, /search-availability-json route var testAvailabilityJSONData = []struct { name string postedData url.Values expectedOK bool expectedMessage string }{ { name: "rooms not available", postedData: url.Values{ "start": {"2050-01-01"}, "end": {"2050-01-02"}, "room_id": {"1"}, }, expectedOK: false, }, { name: "rooms are available", postedData: url.Values{ "start": {"2040-01-01"}, "end": {"2040-01-02"}, "room_id": {"1"}, }, expectedOK: true, }, { name: "empty post body", postedData: nil, expectedOK: false, expectedMessage: "Internal Server Error", }, { name: "database query fails", postedData: url.Values{ "start": {"2060-01-01"}, "end": {"2060-01-02"}, "room_id": {"1"}, }, expectedOK: false, expectedMessage: "Error querying database", }, } // TestAvailabilityJSON tests the AvailabilityJSON handler func TestAvailabilityJSON(t *testing.T) { for _, e := range testAvailabilityJSONData { // create request, get the context with session, set header, create recorder var req *http.Request if e.postedData != nil { req, _ = http.NewRequest("POST", "/search-availability-json", strings.NewReader(e.postedData.Encode())) } else { req, _ = http.NewRequest("POST", "/search-availability-json", nil) } ctx := getCtx(req) req = req.WithContext(ctx) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := httptest.NewRecorder() // make our handler a http.HandlerFunc and call handler := http.HandlerFunc(Repo.AvailabilityJSON) handler.ServeHTTP(rr, req) var j jsonResponse err := json.Unmarshal([]byte(rr.Body.String()), &j) if err != nil { t.Error("failed to parse json!") } if j.OK != e.expectedOK { t.Errorf("%s: expected %v but got %v", e.name, e.expectedOK, j.OK) } } } // testPostAvailabilityData is data for the PostAvailability handler test, /search-availability var testPostAvailabilityData = []struct { name string postedData url.Values expectedStatusCode int expectedLocation string }{ { name: "rooms not available", postedData: url.Values{ "start": {"2050-01-01"}, "end": {"2050-01-02"}, }, expectedStatusCode: http.StatusSeeOther, }, { name: "rooms are available", postedData: url.Values{ "start": {"2040-01-01"}, "end": {"2040-01-02"}, "room_id": {"1"}, }, expectedStatusCode: http.StatusOK, }, { name: "empty post body", postedData: url.Values{}, expectedStatusCode: http.StatusSeeOther, }, { name: "start date wrong format", postedData: url.Values{ "start": {"invalid"}, "end": {"2040-01-02"}, "room_id": {"1"}, }, expectedStatusCode: http.StatusSeeOther, }, { name: "end date wrong format", postedData: url.Values{ "start": {"2040-01-01"}, "end": {"invalid"}, }, expectedStatusCode: http.StatusSeeOther, }, { name: "database query fails", postedData: url.Values{ "start": {"2060-01-01"}, "end": {"2060-01-02"}, }, expectedStatusCode: http.StatusSeeOther, }, } // TestPostAvailability tests the PostAvailabilityHandler func TestPostAvailability(t *testing.T) { for _, e := range testPostAvailabilityData { req, _ := http.NewRequest("POST", "/search-availability", strings.NewReader(e.postedData.Encode())) // get the context with session ctx := getCtx(req) req = req.WithContext(ctx) // set the request header req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := httptest.NewRecorder() // make our handler a http.HandlerFunc and call handler := http.HandlerFunc(Repo.PostAvailability) handler.ServeHTTP(rr, req) if rr.Code != e.expectedStatusCode { t.Errorf("%s gave wrong status code: got %d, wanted %d", e.name, rr.Code, e.expectedStatusCode) } } } // reservationSummaryTests is the data to test ReservationSummary handler var reservationSummaryTests = []struct { name string reservation models.Reservation url string expectedStatusCode int expectedLocation string }{ { name: "res-in-session", reservation: models.Reservation{ RoomID: 1, Room: models.Room{ ID: 1, RoomName: "General's Quarters", }, }, url: "/reservation-summary", expectedStatusCode: http.StatusOK, expectedLocation: "", }, { name: "res-not-in-session", reservation: models.Reservation{}, url: "/reservation-summary", expectedStatusCode: http.StatusSeeOther, expectedLocation: "/", }, } // TestReservationSummary tests the ReservationSummaryHandler func TestReservationSummary(t *testing.T) { for _, e := range reservationSummaryTests { req, _ := http.NewRequest("GET", e.url, nil) ctx := getCtx(req) req = req.WithContext(ctx) rr := httptest.NewRecorder() if e.reservation.RoomID > 0 { session.Put(ctx, "reservation", e.reservation) } handler := http.HandlerFunc(Repo.ReservationSummary) handler.ServeHTTP(rr, req) if rr.Code != e.expectedStatusCode { t.Errorf("%s returned wrong response code: got %d, wanted %d", e.name, rr.Code, e.expectedStatusCode) } if e.expectedLocation != "" { actualLoc, _ := rr.Result().Location() if actualLoc.String() != e.expectedLocation { t.Errorf("failed %s: expected location %s, but got location %s", e.name, e.expectedLocation, actualLoc.String()) } } } } // chooseRoomTests is the data for ChooseRoom handler tests, /choose-room/{id} var chooseRoomTests = []struct { name string reservation models.Reservation url string expectedStatusCode int expectedLocation string }{ { name: "reservation-in-session", reservation: models.Reservation{ RoomID: 1, Room: models.Room{ ID: 1, RoomName: "General's Quarters", }, }, url: "/choose-room/1", expectedStatusCode: http.StatusSeeOther, expectedLocation: "/make-reservation", }, { name: "reservation-not-in-session", reservation: models.Reservation{}, url: "/choose-room/1", expectedStatusCode: http.StatusSeeOther, expectedLocation: "/", }, { name: "malformed-url", reservation: models.Reservation{}, url: "/choose-room/fish", expectedStatusCode: http.StatusSeeOther, expectedLocation: "/", }, } // TestChooseRoom tests the ChooseRoom handler func TestChooseRoom(t *testing.T) { for _, e := range chooseRoomTests { req, _ := http.NewRequest("GET", e.url, nil) ctx := getCtx(req) req = req.WithContext(ctx) // set the RequestURI on the request so that we can grab the ID from the URL req.RequestURI = e.url rr := httptest.NewRecorder() if e.reservation.RoomID > 0 { session.Put(ctx, "reservation", e.reservation) } handler := http.HandlerFunc(Repo.ChooseRoom) handler.ServeHTTP(rr, req) if rr.Code != e.expectedStatusCode { t.Errorf("%s returned wrong response code: got %d, wanted %d", e.name, rr.Code, e.expectedStatusCode) } if e.expectedLocation != "" { actualLoc, _ := rr.Result().Location() if actualLoc.String() != e.expectedLocation { t.Errorf("failed %s: expected location %s, but got location %s", e.name, e.expectedLocation, actualLoc.String()) } } } } // bookRoomTests is the data for the BookRoom handler tests var bookRoomTests = []struct { name string url string expectedStatusCode int }{ { name: "database-works", url: "/book-room?s=2050-01-01&e=2050-01-02&id=1", expectedStatusCode: http.StatusSeeOther, }, { name: "database-fails", url: "/book-room?s=2040-01-01&e=2040-01-02&id=4", expectedStatusCode: http.StatusSeeOther, }, } // TestBookRoom tests the BookRoom handler func TestBookRoom(t *testing.T) { reservation := models.Reservation{ RoomID: 1, Room: models.Room{ ID: 1, RoomName: "General's Quarters", }, } for _, e := range bookRoomTests { req, _ := http.NewRequest("GET", e.url, nil) ctx := getCtx(req) req = req.WithContext(ctx) rr := httptest.NewRecorder() session.Put(ctx, "reservation", reservation) handler := http.HandlerFunc(Repo.BookRoom) handler.ServeHTTP(rr, req) if rr.Code != http.StatusSeeOther { t.Errorf("%s failed: returned wrong response code: got %d, wanted %d", e.name, rr.Code, e.expectedStatusCode) } } } // loginTests is the data for the Login handler tests var loginTests = []struct { name string email string expectedStatusCode int expectedHTML string expectedLocation string }{ { "valid-credentials", "me@here.ca", http.StatusSeeOther, "", "/", }, { "invalid-credentials", "jack@nimble.com", http.StatusSeeOther, "", "/user/login", }, { "invalid-data", "j", http.StatusOK, `action="/user/login"`, "", }, } func TestLogin(t *testing.T) { // range through all tests for _, e := range loginTests { postedData := url.Values{} postedData.Add("email", e.email) postedData.Add("password", "password") // create request req, _ := http.NewRequest("POST", "/user/login", strings.NewReader(postedData.Encode())) ctx := getCtx(req) req = req.WithContext(ctx) // set the header req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := httptest.NewRecorder() // call the handler handler := http.HandlerFunc(Repo.PostShowLogin) handler.ServeHTTP(rr, req) if rr.Code != e.expectedStatusCode { t.Errorf("failed %s: expected code %d, but got %d", e.name, e.expectedStatusCode, rr.Code) } if e.expectedLocation != "" { // get the URL from test actualLoc, _ := rr.Result().Location() if actualLoc.String() != e.expectedLocation { t.Errorf("failed %s: expected location %s, but got location %s", e.name, e.expectedLocation, actualLoc.String()) } } // checking for expected values in HTML if e.expectedHTML != "" { // read the response body into a string html := rr.Body.String() if !strings.Contains(html, e.expectedHTML) { t.Errorf("failed %s: expected to find %s but did not", e.name, e.expectedHTML) } } } } var adminPostShowReservationTests = []struct { name string url string postedData url.Values expectedResponseCode int expectedLocation string expectedHTML string }{ { name: "valid-data-from-new", url: "/admin/reservations/new/1/show", postedData: url.Values{ "first_name": {"John"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, }, expectedResponseCode: http.StatusSeeOther, expectedLocation: "/admin/reservations-new", expectedHTML: "", }, { name: "valid-data-from-all", url: "/admin/reservations/all/1/show", postedData: url.Values{ "first_name": {"John"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, }, expectedResponseCode: http.StatusSeeOther, expectedLocation: "/admin/reservations-all", expectedHTML: "", }, { name: "valid-data-from-cal", url: "/admin/reservations/cal/1/show", postedData: url.Values{ "first_name": {"John"}, "last_name": {"Smith"}, "email": {"john@smith.com"}, "phone": {"555-555-5555"}, "year": {"2022"}, "month": {"01"}, }, expectedResponseCode: http.StatusSeeOther, expectedLocation: "/admin/reservations-calendar?y=2022&m=01", expectedHTML: "", }, } // TestAdminPostShowReservation tests the AdminPostReservation handler func TestAdminPostShowReservation(t *testing.T) { for _, e := range adminPostShowReservationTests { var req *http.Request if e.postedData != nil { req, _ = http.NewRequest("POST", "/user/login", strings.NewReader(e.postedData.Encode())) } else { req, _ = http.NewRequest("POST", "/user/login", nil) } ctx := getCtx(req) req = req.WithContext(ctx) req.RequestURI = e.url // set the header req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := httptest.NewRecorder() // call the handler handler := http.HandlerFunc(Repo.AdminPostShowReservation) handler.ServeHTTP(rr, req) if rr.Code != e.expectedResponseCode { t.Errorf("failed %s: expected code %d, but got %d", e.name, e.expectedResponseCode, rr.Code) } if e.expectedLocation != "" { // get the URL from test actualLoc, _ := rr.Result().Location() if actualLoc.String() != e.expectedLocation { t.Errorf("failed %s: expected location %s, but got location %s", e.name, e.expectedLocation, actualLoc.String()) } } // checking for expected values in HTML if e.expectedHTML != "" { // read the response body into a string html := rr.Body.String() if !strings.Contains(html, e.expectedHTML) { t.Errorf("failed %s: expected to find %s but did not", e.name, e.expectedHTML) } } } } var adminPostReservationCalendarTests = []struct { name string postedData url.Values expectedResponseCode int expectedLocation string expectedHTML string blocks int reservations int }{ { name: "cal", postedData: url.Values{ "year": {time.Now().Format("2006")}, "month": {time.Now().Format("01")}, fmt.Sprintf("add_block_1_%s", time.Now().AddDate(0, 0, 2).Format("2006-01-2")): {"1"}, }, expectedResponseCode: http.StatusSeeOther, }, { name: "cal-blocks", postedData: url.Values{}, expectedResponseCode: http.StatusSeeOther, blocks: 1, }, { name: "cal-res", postedData: url.Values{}, expectedResponseCode: http.StatusSeeOther, reservations: 1, }, } func TestPostReservationCalendar(t *testing.T) { for _, e := range adminPostReservationCalendarTests { var req *http.Request if e.postedData != nil { req, _ = http.NewRequest("POST", "/admin/reservations-calendar", strings.NewReader(e.postedData.Encode())) } else { req, _ = http.NewRequest("POST", "/admin/reservations-calendar", nil) } ctx := getCtx(req) req = req.WithContext(ctx) now := time.Now() bm := make(map[string]int) rm := make(map[string]int) currentYear, currentMonth, _ := now.Date() currentLocation := now.Location() firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation) lastOfMonth := firstOfMonth.AddDate(0, 1, -1) for d := firstOfMonth; d.After(lastOfMonth) == false; d = d.AddDate(0, 0, 1) { rm[d.Format("2006-01-2")] = 0 bm[d.Format("2006-01-2")] = 0 } if e.blocks > 0 { bm[firstOfMonth.Format("2006-01-2")] = e.blocks } if e.reservations > 0 { rm[lastOfMonth.Format("2006-01-2")] = e.reservations } session.Put(ctx, "block_map_1", bm) session.Put(ctx, "reservation_map_1", rm) // set the header req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := httptest.NewRecorder() // call the handler handler := http.HandlerFunc(Repo.AdminPostReservationsCalendar) handler.ServeHTTP(rr, req) if rr.Code != e.expectedResponseCode { t.Errorf("failed %s: expected code %d, but got %d", e.name, e.expectedResponseCode, rr.Code) } } } var adminProcessReservationTests = []struct { name string queryParams string expectedResponseCode int expectedLocation string }{ { name: "process-reservation", queryParams: "", expectedResponseCode: http.StatusSeeOther, expectedLocation: "", }, { name: "process-reservation-back-to-cal", queryParams: "?y=2021&m=12", expectedResponseCode: http.StatusSeeOther, expectedLocation: "", }, } func TestAdminProcessReservation(t *testing.T) { for _, e := range adminProcessReservationTests { req, _ := http.NewRequest("GET", fmt.Sprintf("/admin/process-reservation/cal/1/do%s", e.queryParams), nil) ctx := getCtx(req) req = req.WithContext(ctx) rr := httptest.NewRecorder() handler := http.HandlerFunc(Repo.AdminProcessReservation) handler.ServeHTTP(rr, req) if rr.Code != http.StatusSeeOther { t.Errorf("failed %s: expected code %d, but got %d", e.name, e.expectedResponseCode, rr.Code) } } } var adminDeleteReservationTests = []struct { name string queryParams string expectedResponseCode int expectedLocation string }{ { name: "delete-reservation", queryParams: "", expectedResponseCode: http.StatusSeeOther, expectedLocation: "", }, { name: "delete-reservation-back-to-cal", queryParams: "?y=2021&m=12", expectedResponseCode: http.StatusSeeOther, expectedLocation: "", }, } func TestAdminDeleteReservation(t *testing.T) { for _, e := range adminDeleteReservationTests { req, _ := http.NewRequest("GET", fmt.Sprintf("/admin/process-reservation/cal/1/do%s", e.queryParams), nil) ctx := getCtx(req) req = req.WithContext(ctx) rr := httptest.NewRecorder() handler := http.HandlerFunc(Repo.AdminDeleteReservation) handler.ServeHTTP(rr, req) if rr.Code != http.StatusSeeOther { t.Errorf("failed %s: expected code %d, but got %d", e.name, e.expectedResponseCode, rr.Code) } } } // gets the context 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 }