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:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user