package database import ( "path/filepath" "testing" "github.com/user-management-system/internal/config" "github.com/user-management-system/internal/domain" ) func newTestConfig(t *testing.T) *config.Config { t.Helper() return &config.Config{ Database: config.DatabaseConfig{ DBName: filepath.Join(t.TempDir(), "test.db"), }, } } func newTestDB(t *testing.T, cfg *config.Config) *DB { t.Helper() db, err := NewDB(cfg) if err != nil { t.Fatalf("NewDB failed: %v", err) } sqlDB, err := db.DB.DB() if err != nil { t.Fatalf("resolve sql.DB failed: %v", err) } t.Cleanup(func() { _ = sqlDB.Close() }) return db } func TestAutoMigrateSeedsDefaultRolesAndPermissions(t *testing.T) { cfg := newTestConfig(t) db := newTestDB(t, cfg) if err := db.AutoMigrate(cfg); err != nil { t.Fatalf("AutoMigrate failed: %v", err) } var roleCount int64 if err := db.DB.Model(&domain.Role{}).Count(&roleCount).Error; err != nil { t.Fatalf("count roles failed: %v", err) } if roleCount != int64(len(domain.PredefinedRoles)) { t.Fatalf("expected %d predefined roles, got %d", len(domain.PredefinedRoles), roleCount) } var permissionCount int64 if err := db.DB.Model(&domain.Permission{}).Count(&permissionCount).Error; err != nil { t.Fatalf("count permissions failed: %v", err) } if permissionCount == 0 { t.Fatal("expected default permissions to be seeded") } var userCount int64 if err := db.DB.Model(&domain.User{}).Count(&userCount).Error; err != nil { t.Fatalf("count users failed: %v", err) } if userCount != 0 { t.Fatalf("expected no users when admin config is empty, got %d users", userCount) } } func TestAutoMigrateCreatesAllTables(t *testing.T) { cfg := newTestConfig(t) db := newTestDB(t, cfg) if err := db.AutoMigrate(cfg); err != nil { t.Fatalf("AutoMigrate failed: %v", err) } tables := []interface{}{ &domain.User{}, &domain.Role{}, &domain.Permission{}, &domain.UserRole{}, &domain.RolePermission{}, &domain.Device{}, &domain.LoginLog{}, &domain.OperationLog{}, &domain.SocialAccount{}, &domain.Webhook{}, &domain.WebhookDelivery{}, &domain.PasswordHistory{}, } for _, table := range tables { if !db.DB.Migrator().HasTable(table) { t.Fatalf("expected table %T to exist", table) } } } func TestInitDefaultDataUpgradePathSeedsPermissionsForExistingRoles(t *testing.T) { cfg := newTestConfig(t) db := newTestDB(t, cfg) if err := db.DB.AutoMigrate( &domain.User{}, &domain.Role{}, &domain.Permission{}, &domain.UserRole{}, &domain.RolePermission{}, &domain.Device{}, &domain.LoginLog{}, &domain.OperationLog{}, &domain.SocialAccount{}, &domain.Webhook{}, &domain.WebhookDelivery{}, &domain.PasswordHistory{}, ); err != nil { t.Fatalf("create schema failed: %v", err) } for _, predefinedRole := range domain.PredefinedRoles { role := predefinedRole if err := db.DB.Create(&role).Error; err != nil { t.Fatalf("seed role %s failed: %v", role.Code, err) } } if err := db.initDefaultData(cfg); err != nil { t.Fatalf("initDefaultData failed: %v", err) } var permissionCount int64 if err := db.DB.Model(&domain.Permission{}).Count(&permissionCount).Error; err != nil { t.Fatalf("count permissions failed: %v", err) } if permissionCount == 0 { t.Fatal("expected permissions to be backfilled for existing roles") } var adminRole domain.Role if err := db.DB.Where("code = ?", "admin").First(&adminRole).Error; err != nil { t.Fatalf("load admin role failed: %v", err) } var adminRolePermissionCount int64 if err := db.DB.Model(&domain.RolePermission{}).Where("role_id = ?", adminRole.ID).Count(&adminRolePermissionCount).Error; err != nil { t.Fatalf("count admin role permissions failed: %v", err) } if adminRolePermissionCount == 0 { t.Fatal("expected admin role permissions to be backfilled on upgrade path") } } func TestNewDBWithValidConfig(t *testing.T) { tmpDir := t.TempDir() dbPath := filepath.Join(tmpDir, "test.db") cfg := &config.Config{ Database: config.DatabaseConfig{ DBName: dbPath, }, } db, err := NewDB(cfg) if err != nil { t.Fatalf("NewDB failed: %v", err) } if db == nil { t.Fatal("expected non-nil DB") } sqlDB, err := db.DB.DB() if err != nil { t.Fatalf("resolve sql.DB failed: %v", err) } if err := sqlDB.Close(); err != nil { t.Fatalf("close sql.DB failed: %v", err) } }