//go:build test // +build test package fixtures import ( "context" "fmt" "github.com/jackc/pgx/v5/pgxpool" "golang.org/x/crypto/bcrypt" ) // Global counter for unique emails in tests var testEmailCounter int64 func CreateTestAdminUser(pool *pgxpool.Pool) (string, error) { return createTestUser(pool, "Admin", "User", "", "admin") } func CreateTestUser(pool *pgxpool.Pool) (string, error) { return createTestUser(pool, "Test", "User", "", "verified_email") } func CreateTestUserWithEmail(pool *pgxpool.Pool, email, role string) (string, error) { return createTestUser(pool, "Test", "User", email, role) } func createTestUser(pool *pgxpool.Pool, firstName, lastName, email, role string) (string, error) { passwordHash, err := bcrypt.GenerateFromPassword([]byte("testpassword123"), bcrypt.DefaultCost) if err != nil { return "", fmt.Errorf("failed to hash password: %w", err) } // Generate unique email if not provided if email == "" { testEmailCounter++ email = fmt.Sprintf("%s.%s.%d@test.com", firstName, lastName, testEmailCounter) } ctx := context.Background() var userID string err = pool.QueryRow(ctx, ` INSERT INTO users (n_first_name, n_last_name, email, phone, date_of_birth, password_hash, account_role, account_type) VALUES ($1, $2, $3, $4, $5, $6, $7, 'email') RETURNING id `, firstName, lastName, email, "+447123456789", "1990-01-01", string(passwordHash), role).Scan(&userID) if err != nil { return "", fmt.Errorf("failed to create user: %w", err) } return userID, nil } func CreateTestService(pool *pgxpool.Pool) (string, error) { ctx := context.Background() var serviceID string err := pool.QueryRow(ctx, ` INSERT INTO services (name, description, price, duration_minutes, is_active, patch_test_duration_hours, minimum_age_required) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id `, "Test Service", "A test service for unit tests", 50.00, 60, true, 0, 16).Scan(&serviceID) if err != nil { return "", fmt.Errorf("failed to create service: %w", err) } return serviceID, nil } func CreateTestServiceWithPatchTest(pool *pgxpool.Pool) (string, error) { ctx := context.Background() var serviceID string err := pool.QueryRow(ctx, ` INSERT INTO services (name, description, price, duration_minutes, is_active, patch_test_duration_hours, minimum_age_required) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id `, "Test Patch Test Service", "A test service requiring patch test", 75.00, 90, true, 48, 18).Scan(&serviceID) if err != nil { return "", fmt.Errorf("failed to create service: %w", err) } return serviceID, nil } func CreateTestBooking(pool *pgxpool.Pool, userID, serviceID string) (string, error) { ctx := context.Background() var bookingID string err := pool.QueryRow(ctx, ` INSERT INTO bookings (user_id, start_time, status, notes) VALUES ($1, $2, $3, $4) RETURNING id `, userID, "2099-12-31 10:00:00+00", "pending", "Test booking").Scan(&bookingID) if err != nil { return "", fmt.Errorf("failed to create booking: %w", err) } _, err = pool.Exec(ctx, ` INSERT INTO booking_services (booking_id, service_id) VALUES ($1, $2) `, bookingID, serviceID) if err != nil { return "", fmt.Errorf("failed to link service to booking: %w", err) } return bookingID, nil } func CreateTestVerifiedUser(pool *pgxpool.Pool) (string, error) { return createTestUser(pool, "Verified", "User", "verified@test.com", "verified_email") } func CreateTestUnverifiedUser(pool *pgxpool.Pool) (string, error) { return createTestUser(pool, "Unverified", "User", "unverified@test.com", "unverified_email") } func CreateTestGuestUser(pool *pgxpool.Pool) (string, error) { return createTestUser(pool, "Guest", "User", "guest@test.com", "guest") } func DeleteUser(pool *pgxpool.Pool, userID string) error { ctx := context.Background() _, err := pool.Exec(ctx, "DELETE FROM users WHERE id = $1", userID) return err } func DeleteService(pool *pgxpool.Pool, serviceID string) error { ctx := context.Background() _, err := pool.Exec(ctx, "DELETE FROM services WHERE id = $1", serviceID) return err } func DeleteBooking(pool *pgxpool.Pool, bookingID string) error { ctx := context.Background() _, err := pool.Exec(ctx, "DELETE FROM bookings WHERE id = $1", bookingID) return err } // SafeDeleteUser wraps DeleteUser and returns error (for tests that care about cleanup failure) func SafeDeleteUser(db *pgxpool.Pool, userID string) error { return DeleteUser(db, userID) } // SafeDeleteService wraps DeleteService and returns error (for tests that care about cleanup failure) func SafeDeleteService(db *pgxpool.Pool, serviceID string) error { return DeleteService(db, serviceID) } // SafeDeleteBooking wraps DeleteBooking and returns error (for tests that care about cleanup failure) func SafeDeleteBooking(db *pgxpool.Pool, bookingID string) error { return DeleteBooking(db, bookingID) }