package service import ( "context" "encoding/json" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/repository" ) func setupSlackIntegrationServiceTestDB(t *testing.T) *gorm.DB { t.Helper() db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), }) require.NoError(t, err, "failed to open SQLite test database") require.NoError(t, db.AutoMigrate( &model.Account{}, &model.IntegrationHook{}, &model.IntegrationApp{}, ), "failed to auto-migrate models") t.Cleanup(func() { sqlDB, _ := db.DB() sqlDB.Close() }) return db } func setupSlackIntegrationService(t *testing.T) (*SlackIntegrationService, *gorm.DB) { t.Helper() db := setupSlackIntegrationServiceTestDB(t) hookRepo := repository.NewIntegrationHookRepo(db) svc := NewSlackIntegrationService(hookRepo) return svc, db } func seedSlackAccount(db *gorm.DB, t *testing.T) uint { t.Helper() account := &model.Account{Name: "Test Slack Account"} require.NoError(t, db.Create(account).Error, "failed to seed account") return account.ID } // ======================================== // SlackIntegrationService — Create tests // ======================================== func TestSlackIntegrationService_Create(t *testing.T) { svc, db := setupSlackIntegrationService(t) accountID := seedSlackAccount(db, t) req := CreateSlackRequest{ ChannelID: "C12345678", ChannelName: "general", SlackToken: "xoxb-test-token", } hook, err := svc.Create(context.Background(), accountID, req) assert.NoError(t, err) assert.NotZero(t, hook.ID) assert.Equal(t, model.HookTypeSlack, hook.HookType) assert.Equal(t, model.HookStatusActive, hook.Status) assert.Equal(t, accountID, hook.AccountID) assert.NotNil(t, hook.Settings) } func TestSlackIntegrationService_Create_SettingsStored(t *testing.T) { svc, db := setupSlackIntegrationService(t) accountID := seedSlackAccount(db, t) req := CreateSlackRequest{ ChannelID: "C99999999", ChannelName: "notifications", SlackToken: "xoxb-special-token", } hook, err := svc.Create(context.Background(), accountID, req) require.NoError(t, err) // Verify that the settings JSON contains the Slack fields var settings model.SlackSettings err = json.Unmarshal(hook.Settings, &settings) require.NoError(t, err, "failed to unmarshal settings JSON") assert.Equal(t, "C99999999", settings.ChannelID) assert.Equal(t, "notifications", settings.ChannelName) assert.Equal(t, "xoxb-special-token", settings.SlackToken) } // ======================================== // SlackIntegrationService — Update tests // ======================================== func TestSlackIntegrationService_Update(t *testing.T) { svc, db := setupSlackIntegrationService(t) accountID := seedSlackAccount(db, t) // Create first createReq := CreateSlackRequest{ ChannelID: "C10000001", ChannelName: "old-channel", SlackToken: "xoxb-old-token", } _, err := svc.Create(context.Background(), accountID, createReq) require.NoError(t, err) // Update updateReq := UpdateSlackRequest{ ChannelID: "C20000002", ChannelName: "new-channel", SlackToken: "xoxb-new-token", } updated, err := svc.Update(context.Background(), accountID, updateReq) assert.NoError(t, err) // Verify updated settings var settings model.SlackSettings err = json.Unmarshal(updated.Settings, &settings) require.NoError(t, err) assert.Equal(t, "C20000002", settings.ChannelID) assert.Equal(t, "new-channel", settings.ChannelName) assert.Equal(t, "xoxb-new-token", settings.SlackToken) } func TestSlackIntegrationService_Update_NotFound(t *testing.T) { svc, db := setupSlackIntegrationService(t) accountID := seedSlackAccount(db, t) // No Slack hook created for this account — update should fail updateReq := UpdateSlackRequest{ ChannelID: "C00000000", } updated, err := svc.Update(context.Background(), accountID, updateReq) assert.Error(t, err) assert.Nil(t, updated) assert.Contains(t, err.Error(), "not found") } // ======================================== // SlackIntegrationService — Delete tests // ======================================== func TestSlackIntegrationService_Delete(t *testing.T) { svc, db := setupSlackIntegrationService(t) accountID := seedSlackAccount(db, t) // Create first createReq := CreateSlackRequest{ ChannelID: "C30000003", ChannelName: "delete-me", SlackToken: "xoxb-delete-token", } _, err := svc.Create(context.Background(), accountID, createReq) require.NoError(t, err) // Delete err = svc.Delete(context.Background(), accountID) assert.NoError(t, err) // Verify it's gone — no Slack hooks should remain for this account hookRepo := repository.NewIntegrationHookRepo(db) hooks, err := hookRepo.FindByAccountAndType(context.Background(), accountID, model.HookTypeSlack) assert.NoError(t, err) assert.Empty(t, hooks) } func TestSlackIntegrationService_Delete_NotFound(t *testing.T) { svc, db := setupSlackIntegrationService(t) accountID := seedSlackAccount(db, t) // No Slack hook exists for this account — delete should fail err := svc.Delete(context.Background(), accountID) assert.Error(t, err) assert.Contains(t, err.Error(), "not found") } // ======================================== // SlackIntegrationService — ListAllChannels tests // ======================================== func TestSlackIntegrationService_ListAllChannels(t *testing.T) { svc, db := setupSlackIntegrationService(t) accountID := seedSlackAccount(db, t) // Create a Slack integration first createReq := CreateSlackRequest{ ChannelID: "C40000004", ChannelName: "list-channels", SlackToken: "xoxb-list-token", } _, err := svc.Create(context.Background(), accountID, createReq) require.NoError(t, err) channels, err := svc.ListAllChannels(context.Background(), accountID) assert.NoError(t, err) assert.Len(t, channels, 1) // The placeholder response contains the configured channel assert.Equal(t, "C40000004", channels[0]["id"]) assert.Equal(t, "list-channels", channels[0]["name"]) } func TestSlackIntegrationService_ListAllChannels_NotFound(t *testing.T) { svc, db := setupSlackIntegrationService(t) accountID := seedSlackAccount(db, t) // No Slack integration exists for this account channels, err := svc.ListAllChannels(context.Background(), accountID) assert.Error(t, err) assert.Nil(t, channels) assert.Contains(t, err.Error(), "not found") }