feat(backend): increase per_page cap to 500 in bookings list handler

Raise per_page limit from 100 to 500 in parseGetAllBookingsRequest to support large booking lists. Add test coverage for per_page=500 acceptance and per_page=600 rejection (fallback to 10).

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-06-15 20:27:41 +01:00
co-authored by Sisyphus
parent 2b942a48bd
commit 459adf7001
2 changed files with 72 additions and 1 deletions
+71
View File
@@ -7,6 +7,7 @@ package admin
//
// Test Coverage:
// - GetAllAdminBookingsHandler: GET /api/admin/bookings - List all bookings with filters
// - GetAllAdminBookingsHandler Pagination: per_page cap up to 500, fallback to 10
// - SearchAdminBookingsHandler: POST /api/admin/bookings/search - Search bookings
// - GetAdminBookingHandler: GET /api/admin/bookings/{id} - Get booking details
// - AdminCreateBookingForUserHandler: POST /api/admin/bookings - Create booking for user
@@ -130,6 +131,76 @@ func TestAdminBookings_List(t *testing.T) {
}
}
// TestAdminBookings_List_PerPageCap tests that per_page parameter up to 500
// is accepted (was previously capped at 100, causing per_page=500 to fall
// back to default 10 and miss bookings on page 2+).
func TestAdminBookings_List_PerPageCap(t *testing.T) {
resetTestData(t)
adminID, err := fixtures.CreateTestAdminUser(db.DB)
if err != nil {
t.Fatalf("failed to create admin user: %v", err)
}
defer fixtures.DeleteUser(db.DB, adminID)
userID, err := fixtures.CreateTestUser(db.DB)
if err != nil {
t.Fatalf("failed to create test user: %v", err)
}
defer fixtures.DeleteUser(db.DB, userID)
serviceID, err := fixtures.CreateTestService(db.DB)
if err != nil {
t.Fatalf("failed to create test service: %v", err)
}
defer fixtures.DeleteService(db.DB, serviceID)
// Create 3 bookings so we can verify per_page=500 returns all of them
for i := 0; i < 3; i++ {
bookingID, err := fixtures.CreateTestBooking(db.DB, userID, serviceID)
if err != nil {
t.Fatalf("failed to create test booking %d: %v", i+1, err)
}
defer fixtures.DeleteBooking(db.DB, bookingID)
}
// Test per_page=500 (should be accepted and return all 3 bookings)
handler := http.HandlerFunc(bookings.GetAllAdminBookingsHandler)
w := makeAdminRequest(handler, "GET", "/api/admin/bookings?per_page=500", nil)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
}
var resp bookings.BookingListResponse
if err := parseResponseBody(w, &resp); err != nil {
t.Fatalf("failed to parse response: %v", err)
}
if len(resp.Bookings) != 3 {
t.Errorf("expected 3 bookings with per_page=500, got %d (per_page was likely rejected)", len(resp.Bookings))
}
if resp.PerPage != 500 {
t.Errorf("expected per_page=500 in response, got %d", resp.PerPage)
}
if resp.Total != 3 {
t.Errorf("expected total 3, got %d", resp.Total)
}
// Test per_page=600 (should be rejected and fall back to default 10)
w2 := makeAdminRequest(handler, "GET", "/api/admin/bookings?per_page=600", nil)
if w2.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w2.Code)
}
var resp2 bookings.BookingListResponse
if err := parseResponseBody(w2, &resp2); err != nil {
t.Fatalf("failed to parse response: %v", err)
}
if resp2.PerPage != 10 {
t.Errorf("expected per_page defaults to 10 when >500, got %d", resp2.PerPage)
}
}
// TestAdminBookings_List_FilterByStatus tests that an admin can filter
// bookings by status (e.g., pending, confirmed, completed).
func TestAdminBookings_List_FilterByStatus(t *testing.T) {
+1 -1
View File
@@ -347,7 +347,7 @@ func parseGetAllBookingsRequest(r *http.Request) GetAllBookingsRequest {
}
}
if perPageStr := r.URL.Query().Get("per_page"); perPageStr != "" {
if perPage, err := strconv.Atoi(perPageStr); err == nil && perPage > 0 && perPage <= 100 {
if perPage, err := strconv.Atoi(perPageStr); err == nil && perPage > 0 && perPage <= 500 {
req.PerPage = perPage
}
}