package controllers import ( "net/http/httptest" "testing" "doormile/utils" "github.com/gofiber/fiber/v2" ) // The page-size ceiling on the admin list endpoints. // // GetAdminBookings and GetAdminCustomers clamped `pagesize` to a hard-coded // 100 while utils.ParsePage allowed 1000. The console does not read one page — // it DRAINS the list, and it asks for 1000 a page. Being handed 100 meant ten // times the round trips for the same rows, and because the drain has its own // page budget (12), the list it renders stopped at 1,200 bookings. Past that // the counts on the screen are floors presented as totals. // // The ceiling now comes from utils.MaxPageSize so the two cannot drift apart // again. These tests pin the clamp arithmetic directly: exercising the handlers // themselves needs Postgres, and this is the part that was wrong. // clampPageSize mirrors the expression in the handlers. If the handlers change, // this stops matching and the tests below stop meaning anything — which is why // TestHandlersUseTheSharedCeiling reads the source instead of trusting it. func clampPageSize(requested int) int { return min(utils.MaxPageSize, max(1, requested)) } func TestPageSizeCeilingComesFromTheSharedConstant(t *testing.T) { if utils.MaxPageSize <= 100 { t.Fatalf("utils.MaxPageSize = %d: raising the clamp to it is pointless if it "+ "is not above the old hard-coded 100", utils.MaxPageSize) } // The exact request the console makes on every drain page. if got := clampPageSize(1000); got != 1000 { t.Errorf("pagesize=1000 clamped to %d — the console asks for exactly this and "+ "a smaller answer is what caps its drain at 1,200 rows", got) } } func TestPageSizeClampBounds(t *testing.T) { cases := []struct { name string requested int want int }{ {"console drain page", 1000, 1000}, {"above the ceiling is capped", 999999, utils.MaxPageSize}, {"at the ceiling", utils.MaxPageSize, utils.MaxPageSize}, {"one below the ceiling", utils.MaxPageSize - 1, utils.MaxPageSize - 1}, {"zero floors to one", 0, 1}, {"negative floors to one", -50, 1}, {"one stays one", 1, 1}, {"the old ceiling still works", 100, 100}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { if got := clampPageSize(tc.requested); got != tc.want { t.Errorf("clampPageSize(%d) = %d, want %d", tc.requested, got, tc.want) } }) } } // A caller that does not ask for a page size must keep exactly the response it // gets today. Widening the ceiling must not widen the default: every client // that never passed ?pagesize would suddenly be handed 50x the rows. func TestDefaultPageSizeIsUnchangedByTheWiderCeiling(t *testing.T) { app := fiber.New(fiber.Config{DisableStartupMessage: true}) app.Get("/probe", func(c *fiber.Ctx) error { // The same default the handlers pass to QueryInt. if got := c.QueryInt("pagesize", 20); got != 20 { t.Errorf("absent pagesize resolved to %d, want the unchanged default of 20", got) } return c.SendString("ok") }) resp, err := app.Test(httptest.NewRequest("GET", "/probe", nil), 5000) if err != nil { t.Fatalf("probe request: %v", err) } defer resp.Body.Close() }