fix: improve test infrastructure and add ID validation

- Add TestMain to set test env vars and testdb.TruncateTables for test
  isolation
- Add chi routing context to test helpers for path parameter extraction
- Fix SQL error handling to use errors.Is() instead of ==
- Add validators package with ID validation
- Fix admin test middleware chain (RequireAdmin wrapper)
- Update test user inserts to include phone and date_of_birth fields
- Update service delete test to check soft-delete (is_active=false)
- Update holiday hours test to use new schema (weekday, is_open)
- Add phone number validation tests for UK mobile numbers
This commit is contained in:
2026-02-23 00:59:32 +00:00
parent 355e8a26c1
commit df3439bd70
30 changed files with 1081 additions and 360 deletions
+78 -5
View File
@@ -58,14 +58,81 @@ func NewPool(dsn string) (*pgxpool.Pool, error) {
func Migrate(t *testing.T, pool *pgxpool.Pool) {
t.Helper()
// Check if database already has tables by checking for the users table
ctx := context.Background()
// Check if database already has tables
var err error
// Check if database already has tables - use information_schema which is more reliable
var tableCount int
err := pool.QueryRow(ctx, "SELECT COUNT(*) FROM pg_tables WHERE tablename = 'users'").Scan(&tableCount)
err = pool.QueryRow(ctx, "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public' AND table_type = 'BASE TABLE'").Scan(&tableCount)
if err == nil && tableCount > 0 {
// Tables already exist, skip migration
t.Log("Database already has tables, skipping migration")
return
t.Log("Database already has types, dropping and recreating for clean state...")
// Drop all tables, sequences, and views in correct order
dropOrder := []string{
"admin_notifications",
"user_notification_preferences",
"user_referrals",
"booking_services",
"payments",
"bookings",
"user_service_patch_tests",
"services",
"verification_codes",
"user_social_logins",
"users",
"images",
"tags",
"working_hours",
"exceptional_group_applications",
"exceptional_working_hours",
"exceptional_working_hours_groups",
"business_settings",
}
// Drop all objects with error logging
allDropStmts := append([]string{}, dropOrder...)
allDropStmts = append(allDropStmts,
"DROP SEQUENCE IF EXISTS invoice_number_seq",
"DROP SEQUENCE IF EXISTS tags_id_seq",
"DROP SEQUENCE IF EXISTS exceptional_working_hours_id_seq",
"DROP SEQUENCE IF EXISTS exceptional_working_hours_groups_id_seq",
"DROP TYPE IF EXISTS account_role CASCADE",
"DROP TYPE IF EXISTS account_type CASCADE",
"DROP TYPE IF EXISTS payment_type CASCADE",
"DROP TYPE IF EXISTS payment_method CASCADE",
"DROP TYPE IF EXISTS payment_status CASCADE",
"DROP TYPE IF EXISTS booking_status CASCADE",
"DROP TYPE IF EXISTS verification_purpose CASCADE",
"DROP TYPE IF EXISTS admin_notification_reason CASCADE",
)
for _, item := range dropOrder {
stmt := fmt.Sprintf("DROP TABLE IF EXISTS %s CASCADE", item)
if _, err := pool.Exec(ctx, stmt); err != nil {
t.Logf("Warning dropping table %s: %v (expected if using IF EXISTS)", item, err)
}
}
// Drop sequences and types
for _, item := range []string{
"DROP SEQUENCE IF EXISTS invoice_number_seq",
"DROP SEQUENCE IF EXISTS tags_id_seq",
"DROP SEQUENCE IF EXISTS exceptional_working_hours_id_seq",
"DROP SEQUENCE IF EXISTS exceptional_working_hours_groups_id_seq",
"DROP TYPE IF EXISTS account_role CASCADE",
"DROP TYPE IF EXISTS account_type CASCADE",
"DROP TYPE IF EXISTS payment_type CASCADE",
"DROP TYPE IF EXISTS payment_method CASCADE",
"DROP TYPE IF EXISTS payment_status CASCADE",
"DROP TYPE IF EXISTS booking_status CASCADE",
"DROP TYPE IF EXISTS verification_purpose CASCADE",
"DROP TYPE IF EXISTS admin_notification_reason CASCADE",
} {
if _, err := pool.Exec(ctx, item); err != nil {
t.Logf("Warning dropping item: %v", err)
}
}
}
paths := []string{
@@ -91,6 +158,12 @@ func Migrate(t *testing.T, pool *pgxpool.Pool) {
// Note: This doesn't handle stored procedures properly, but the database
// should already be set up with the correct schema
t.Log("Running migration...")
// Execute the schema SQL
_, err = pool.Exec(ctx, schemaSQL)
if err != nil {
t.Fatalf("Failed to execute migration: %v", err)
}
}
func Tx(t *testing.T, pool *pgxpool.Pool) pgx.Tx {