refactor: optimize test DB setup — TestMain per package, truncate-only between tests

- Add TestMain to all 10 test packages (schema DROP+CREATE runs once per package)
- Convert per-test setupTestDB to resetTestData (TRUNCATE only, ~60% faster)
- Add 3 missing tables to TruncateTables (booking_edit_requests, exceptional_group_applications, business_settings)
- Remove dead truncateDiscountTables helper
- Consolidate discount_test.go into package bookings (was external test package)
- Update testutils.SetupTestDB to truncate-only
- Fix unused imports across user, bookings, and handlers packages
- Verify: 286 passing, 2 skipped, 0 failures with -count=2 (no state leakage)
This commit is contained in:
2026-05-10 17:27:51 +01:00
parent 83c62ffb97
commit e73c96b653
26 changed files with 554 additions and 920 deletions
+19 -50
View File
@@ -30,32 +30,15 @@ import (
"crussell/mw"
"crussell/testutils/jwt"
"crussell/testutils/testdb"
"github.com/jackc/pgx/v5/pgxpool"
)
func setupTestDB(t *testing.T) func() {
func resetTestData(t *testing.T) {
t.Helper()
pool := testdb.Pool(t)
testdb.Migrate(t, pool)
testdb.TruncateTables(t, pool)
originalDB := db.DB
db.DB = pool
jwt.Init()
// Seed default working hours
seedDefaultWorkingHours(t, pool)
return func() {
db.DB = originalDB
pool.Close()
}
testdb.TruncateTables(t, db.DB)
seedDefaultWorkingHours(t)
}
func seedDefaultWorkingHours(t *testing.T, pool *pgxpool.Pool) {
func seedDefaultWorkingHours(t *testing.T) {
t.Helper()
// Seed 7 days of working hours (Monday=0 to Sunday=6)
@@ -75,7 +58,7 @@ func seedDefaultWorkingHours(t *testing.T, pool *pgxpool.Pool) {
}
for _, h := range hours {
_, err := pool.Exec(context.Background(), `
_, err := db.DB.Exec(context.Background(), `
INSERT INTO working_hours (weekday, start_time, end_time, is_open)
VALUES ($1, $2, $3, $4)
ON CONFLICT (weekday) DO UPDATE SET start_time = $2, end_time = $3, is_open = $4
@@ -123,8 +106,7 @@ func makeAuthRequest(handler http.Handler, method, path, token string, body inte
// can be retrieved. The test checks that all 7 days are returned with correct
// opening times, closing times, and is_open status.
func TestScheduling_GetDefaultHours(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
handler := http.HandlerFunc(GetDefaultHours)
w := makeRequest(handler, "GET", "/api/scheduling/default-hours", nil)
@@ -171,8 +153,7 @@ func TestScheduling_GetDefaultHours(t *testing.T) {
// the default weekly working hours. The new schedule is persisted to the
// database and returned on subsequent requests.
func TestScheduling_UpdateDefaultHours_Admin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
adminToken := jwt.GenerateAdminToken()
handler := http.HandlerFunc(UpdateDefaultHours)
@@ -217,8 +198,7 @@ func TestScheduling_UpdateDefaultHours_Admin(t *testing.T) {
// TestScheduling_UpdateDefaultHours_NonAdmin verifies that non-admin users
// receive HTTP 403 Forbidden when attempting to update default hours.
func TestScheduling_UpdateDefaultHours_NonAdmin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
userToken := jwt.GenerateUserToken("user-123")
@@ -245,8 +225,7 @@ func TestScheduling_UpdateDefaultHours_NonAdmin(t *testing.T) {
// TestScheduling_ListExceptionalGroups verifies that admins can list all
// exceptional working hours groups (holidays, special events).
func TestScheduling_ListExceptionalGroups(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
// Create an exceptional group
_, err := db.DB.Exec(context.Background(), `
@@ -283,8 +262,7 @@ func TestScheduling_ListExceptionalGroups(t *testing.T) {
// TestScheduling_CreateExceptionalGroup_Admin tests that an admin can
// create a new exceptional working hours group with specific hours for each day.
func TestScheduling_CreateExceptionalGroup_Admin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
adminToken := jwt.GenerateAdminToken()
handler := http.HandlerFunc(CreateExceptionalGroup)
@@ -326,8 +304,7 @@ func TestScheduling_CreateExceptionalGroup_Admin(t *testing.T) {
// TestScheduling_CreateExceptionalGroup_NonAdmin verifies that non-admin
// users receive HTTP 403 when attempting to create exceptional groups.
func TestScheduling_CreateExceptionalGroup_NonAdmin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
userToken := jwt.GenerateUserToken("user-123")
@@ -359,8 +336,7 @@ func TestScheduling_CreateExceptionalGroup_NonAdmin(t *testing.T) {
// an exceptional working hours group. This removes the group and its associated
// hours from the system.
func TestScheduling_DeleteExceptionalGroup_Admin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
adminToken := jwt.GenerateAdminToken()
@@ -400,8 +376,7 @@ func TestScheduling_DeleteExceptionalGroup_Admin(t *testing.T) {
// TestScheduling_DeleteExceptionalGroup_NonAdmin verifies that non-admin
// users receive HTTP 403 when attempting to delete exceptional groups.
func TestScheduling_DeleteExceptionalGroup_NonAdmin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
userToken := jwt.GenerateUserToken("user-123")
@@ -422,8 +397,7 @@ func TestScheduling_DeleteExceptionalGroup_NonAdmin(t *testing.T) {
// retrieved for a given date range. The response includes whether hours come
// from default schedule or exceptional groups.
func TestScheduling_GetWorkingHours(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
handler := http.HandlerFunc(GetWorkingHours)
req := httptest.NewRequest("GET", "/api/scheduling/working-hours?start=2026-02-16&end=2026-02-22", nil)
@@ -458,8 +432,7 @@ func TestScheduling_GetWorkingHours(t *testing.T) {
// slots can be calculated for a date range based on working hours and service
// durations.
func TestScheduling_GetAvailableHours(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
handler := http.HandlerFunc(GetAvailableHours)
req := httptest.NewRequest("GET", "/api/scheduling/available-hours?start=2026-02-16&end=2026-02-22", nil)
@@ -496,8 +469,7 @@ func TestScheduling_GetAvailableHours(t *testing.T) {
// admin can apply an exceptional hours group to specific weeks, activating
// holiday schedules for those periods.
func TestScheduling_UpdateExceptionalApplications_Admin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
adminToken := jwt.GenerateAdminToken()
@@ -541,8 +513,7 @@ func TestScheduling_UpdateExceptionalApplications_Admin(t *testing.T) {
// TestScheduling_UpdateExceptionalApplications_NonAdmin verifies that
// non-admin users receive HTTP 403 when attempting to apply exceptional hours.
func TestScheduling_UpdateExceptionalApplications_NonAdmin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
userToken := jwt.GenerateUserToken("user-123")
handler := mw.RequireAuth(mw.RequireAdmin(http.HandlerFunc(UpdateExceptionalApplications)))
@@ -566,8 +537,7 @@ func TestScheduling_UpdateExceptionalApplications_NonAdmin(t *testing.T) {
// TestScheduling_GetAvailableHours_WithBlocker_NonAdmin verifies that non-admin
// users do NOT see blocked time slots in their available hours.
func TestScheduling_GetAvailableHours_WithBlocker_NonAdmin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
// Create a time blocker for 2026-03-16 10:00-11:00 (Monday - an open day)
ukLocation, _ := time.LoadLocation("Europe/London")
@@ -635,8 +605,7 @@ func TestScheduling_GetAvailableHours_WithBlocker_NonAdmin(t *testing.T) {
// TestScheduling_GetAvailableHours_WithBlocker_Admin verifies that admin users
// CAN see blocked time slots in the blockers field.
func TestScheduling_GetAvailableHours_WithBlocker_Admin(t *testing.T) {
cleanup := setupTestDB(t)
defer cleanup()
resetTestData(t)
// Create a time blocker for 2026-03-16 10:00-11:00 (Monday - open day)
ukLocation, _ := time.LoadLocation("Europe/London")