package mysql import ( "context" "fmt" "testing" "time" "gorm.io/driver/sqlite" "gorm.io/gorm" mastersettings "wucher/internal/domain/master_settings" "wucher/internal/shared/pkg/uuidv7" ) func openMasterSettingsTestDB(t *testing.T) *gorm.DB { t.Helper() dsn := fmt.Sprintf("file:master_settings_test_%d?mode=memory&cache=shared", time.Now().UnixNano()) db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{ NowFunc: func() time.Time { return time.Now().UTC() }, }) if err != nil { t.Fatalf("open sqlite: %v", err) } if err := db.AutoMigrate(&mastersettings.MasterSettings{}, &mastersettings.MasterSettingValue{}); err != nil { t.Fatalf("auto migrate: %v", err) } return db } func TestNewMasterSettingsRepository(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) if repo == nil || repo.db == nil { t.Fatalf("expected repository initialized") } } func TestMasterSettingsRepositoryCreate(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) row := &mastersettings.MasterSettings{ CompanyName: "Wucher", Title: "Welcome", Subtitle: "Flight ops", } if err := repo.Create(context.Background(), row); err != nil { t.Fatalf("unexpected error: %v", err) } if len(row.ID) == 0 { t.Fatalf("expected id set") } sqlDB, _ := db.DB() _ = sqlDB.Close() if err := repo.Create(context.Background(), &mastersettings.MasterSettings{CompanyName: "AfterClose"}); err == nil { t.Fatalf("expected error on closed DB") } } func TestMasterSettingsRepositoryUpdate(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) row := &mastersettings.MasterSettings{ CompanyName: "Wucher", Title: "Old", Subtitle: "Old subtitle", } if err := repo.Create(context.Background(), row); err != nil { t.Fatalf("seed create: %v", err) } row.Title = "New" row.Subtitle = "New subtitle" if err := repo.Update(context.Background(), row); err != nil { t.Fatalf("unexpected update error: %v", err) } got, err := repo.GetByID(context.Background(), row.ID) if err != nil { t.Fatalf("get after update: %v", err) } if got == nil || got.Title != "New" || got.Subtitle != "New subtitle" { t.Fatalf("expected updated values persisted") } sqlDB, _ := db.DB() _ = sqlDB.Close() if err := repo.Update(context.Background(), row); err == nil { t.Fatalf("expected error on closed DB") } } func TestMasterSettingsRepositoryDelete(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) row := &mastersettings.MasterSettings{CompanyName: "Delete Me"} if err := repo.Create(context.Background(), row); err != nil { t.Fatalf("seed create: %v", err) } deletedBy := uuidv7.MustBytes() if err := repo.Delete(context.Background(), row.ID, deletedBy); err != nil { t.Fatalf("unexpected delete error: %v", err) } got, err := repo.GetByID(context.Background(), row.ID) if err != nil { t.Fatalf("get by id after delete: %v", err) } if got != nil { t.Fatalf("expected soft deleted row hidden from GetByID") } sqlDB, _ := db.DB() _ = sqlDB.Close() if err := repo.Delete(context.Background(), row.ID, deletedBy); err == nil { t.Fatalf("expected error on closed DB") } } func TestMasterSettingsRepositoryGetByID(t *testing.T) { t.Run("found", func(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) row := &mastersettings.MasterSettings{CompanyName: "Wucher"} if err := repo.Create(context.Background(), row); err != nil { t.Fatalf("seed create: %v", err) } got, err := repo.GetByID(context.Background(), row.ID) if err != nil { t.Fatalf("unexpected error: %v", err) } if got == nil || got.CompanyName != "Wucher" { t.Fatalf("expected row found") } }) t.Run("not found", func(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) got, err := repo.GetByID(context.Background(), uuidv7.MustBytes()) if err != nil { t.Fatalf("unexpected error: %v", err) } if got != nil { t.Fatalf("expected nil for not found") } }) t.Run("db error", func(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) sqlDB, _ := db.DB() _ = sqlDB.Close() if _, err := repo.GetByID(context.Background(), uuidv7.MustBytes()); err == nil { t.Fatalf("expected error on closed DB") } }) } func TestMasterSettingsRepositoryList(t *testing.T) { t.Run("success without limit", func(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) _ = repo.Create(context.Background(), &mastersettings.MasterSettings{CompanyName: "Beta", Title: "T1"}) _ = repo.Create(context.Background(), &mastersettings.MasterSettings{CompanyName: "Alpha", Title: "T2"}) rows, total, err := repo.List(context.Background(), "", "", 0, 0) if err != nil { t.Fatalf("unexpected error: %v", err) } if total != 2 || len(rows) != 2 { t.Fatalf("expected 2 rows, total=%d len=%d", total, len(rows)) } }) t.Run("success with filter sort and limit", func(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) _ = repo.Create(context.Background(), &mastersettings.MasterSettings{CompanyName: "Wucher", Title: "Primary"}) _ = repo.Create(context.Background(), &mastersettings.MasterSettings{CompanyName: "Other", Title: "Secondary"}) rows, total, err := repo.List(context.Background(), "Wuc", "company_name DESC", 1, 0) if err != nil { t.Fatalf("unexpected error: %v", err) } if total != 1 || len(rows) != 1 || rows[0].CompanyName != "Wucher" { t.Fatalf("unexpected list result") } }) t.Run("count error", func(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) if err := db.Migrator().DropTable(&mastersettings.MasterSettings{}); err != nil { t.Fatalf("drop table: %v", err) } if _, _, err := repo.List(context.Background(), "", "", 10, 0); err == nil { t.Fatalf("expected count error") } }) t.Run("find error", func(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) _ = repo.Create(context.Background(), &mastersettings.MasterSettings{CompanyName: "Wucher"}) if _, _, err := repo.List(context.Background(), "", "company_name ASC, )", 10, 0); err == nil { t.Fatalf("expected find error from invalid sort") } }) } func TestMasterSettingsRepositorySettingValues(t *testing.T) { db := openMasterSettingsTestDB(t) repo := NewMasterSettingsRepository(db) actor := []byte("abcdefghijklmnop") rows := []mastersettings.MasterSettingValue{ { SettingKey: mastersettings.SettingMicrosoftEntraTenantID, Value: "tenant-a", CreatedBy: actor, UpdatedBy: actor, IsEncrypted: false, }, { SettingKey: mastersettings.SettingMicrosoftEntraClientSecret, Value: "ciphertext", CreatedBy: actor, UpdatedBy: actor, IsEncrypted: true, }, } if err := repo.UpsertSettingValues(context.Background(), rows); err != nil { t.Fatalf("upsert setting values: %v", err) } got, err := repo.GetSettingValuesByKeys(context.Background(), []string{ mastersettings.SettingMicrosoftEntraTenantID, mastersettings.SettingMicrosoftEntraClientSecret, }) if err != nil { t.Fatalf("get setting values: %v", err) } if len(got) != 2 { t.Fatalf("expected 2 rows, got %d", len(got)) } if err := repo.UpsertSettingValues(context.Background(), []mastersettings.MasterSettingValue{ { SettingKey: mastersettings.SettingMicrosoftEntraTenantID, Value: "tenant-b", UpdatedBy: actor, IsEncrypted: false, }, }); err != nil { t.Fatalf("upsert update row: %v", err) } got, err = repo.GetSettingValuesByKeys(context.Background(), []string{ mastersettings.SettingMicrosoftEntraTenantID, }) if err != nil { t.Fatalf("get updated value: %v", err) } if len(got) != 1 || got[0].Value != "tenant-b" { t.Fatalf("expected updated value tenant-b, got %#v", got) } }