package service import ( "context" "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 setupIntegrationHookTestDB(t *testing.T) (*repository.IntegrationHookRepo, *repository.IntegrationAppRepo) { t.Helper() db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), }) require.NoError(t, err) require.NoError(t, db.AutoMigrate( &model.Account{}, &model.User{}, &model.AccountUser{}, &model.Inbox{}, &model.IntegrationHook{}, &model.IntegrationApp{}, )) return repository.NewIntegrationHookRepo(db), repository.NewIntegrationAppRepo(db) } func TestIntegrationHookService_Create(t *testing.T) { hookRepo, appRepo := setupIntegrationHookTestDB(t) svc := NewIntegrationHookService(hookRepo, appRepo, nil) // nil registry — webhook processing tests are separate ctx := context.Background() req := CreateHookRequest{ HookType: "webhook", URL: "https://example.com/webhook", } hook, err := svc.Create(ctx, 1, req) require.NoError(t, err) assert.Equal(t, model.HookTypeWebhook, hook.HookType) assert.Equal(t, "https://example.com/webhook", hook.URL) assert.Equal(t, uint(1), hook.AccountID) } func TestIntegrationHookService_Create_InvalidHookType(t *testing.T) { hookRepo, appRepo := setupIntegrationHookTestDB(t) svc := NewIntegrationHookService(hookRepo, appRepo, nil) // nil registry — webhook processing tests are separate ctx := context.Background() req := CreateHookRequest{ HookType: "invalid_type", URL: "https://example.com/hook", } _, err := svc.Create(ctx, 1, req) assert.Error(t, err, "should reject invalid hook type") } func TestIntegrationHookService_Create_Slack(t *testing.T) { hookRepo, appRepo := setupIntegrationHookTestDB(t) svc := NewIntegrationHookService(hookRepo, appRepo, nil) // nil registry — webhook processing tests are separate ctx := context.Background() req := CreateHookRequest{ HookType: "slack", URL: "https://slack.example.com/hook", } hook, err := svc.Create(ctx, 1, req) require.NoError(t, err) assert.Equal(t, model.HookTypeSlack, hook.HookType) } func TestIntegrationHookService_Get(t *testing.T) { hookRepo, appRepo := setupIntegrationHookTestDB(t) svc := NewIntegrationHookService(hookRepo, appRepo, nil) // nil registry — webhook processing tests are separate ctx := context.Background() req := CreateHookRequest{ HookType: "webhook", URL: "https://example.com/get-test", } hook, err := svc.Create(ctx, 1, req) require.NoError(t, err) found, err := svc.Get(ctx, hook.ID) require.NoError(t, err) assert.Equal(t, hook.ID, found.ID) } func TestIntegrationHookService_List(t *testing.T) { hookRepo, appRepo := setupIntegrationHookTestDB(t) svc := NewIntegrationHookService(hookRepo, appRepo, nil) // nil registry — webhook processing tests are separate ctx := context.Background() for _, ht := range []string{"webhook", "slack"} { req := CreateHookRequest{ HookType: ht, URL: "https://example.com/" + ht, } _, err := svc.Create(ctx, 1, req) require.NoError(t, err) } hooks, total, err := svc.List(ctx, 1, 0, 10) require.NoError(t, err) assert.Equal(t, int64(2), total) assert.Len(t, hooks, 2) } func TestIntegrationHookService_Update(t *testing.T) { hookRepo, appRepo := setupIntegrationHookTestDB(t) svc := NewIntegrationHookService(hookRepo, appRepo, nil) // nil registry — webhook processing tests are separate ctx := context.Background() req := CreateHookRequest{ HookType: "webhook", URL: "https://example.com/old-url", } hook, err := svc.Create(ctx, 1, req) require.NoError(t, err) updateReq := UpdateHookRequest{ URL: "https://example.com/new-url", Status: "inactive", } updated, err := svc.Update(ctx, hook.ID, updateReq) require.NoError(t, err) assert.Equal(t, "https://example.com/new-url", updated.URL) assert.Equal(t, model.HookStatusInactive, updated.Status) } func TestIntegrationHookService_Delete(t *testing.T) { hookRepo, appRepo := setupIntegrationHookTestDB(t) svc := NewIntegrationHookService(hookRepo, appRepo, nil) // nil registry — webhook processing tests are separate ctx := context.Background() req := CreateHookRequest{ HookType: "webhook", URL: "https://example.com/to-delete", } hook, err := svc.Create(ctx, 1, req) require.NoError(t, err) require.NoError(t, svc.Delete(ctx, hook.ID)) _, err = svc.Get(ctx, hook.ID) assert.Error(t, err, "should not find deleted hook") } func TestIntegrationHookService_Create_WithInboxID(t *testing.T) { hookRepo, appRepo := setupIntegrationHookTestDB(t) svc := NewIntegrationHookService(hookRepo, appRepo, nil) // nil registry — webhook processing tests are separate ctx := context.Background() inboxID := uint(10) req := CreateHookRequest{ HookType: "webhook", URL: "https://example.com/inbox-hook", InboxID: &inboxID, } hook, err := svc.Create(ctx, 1, req) require.NoError(t, err) assert.Equal(t, inboxID, *hook.InboxID) } func TestIntegrationHookService_Create_WithSettings(t *testing.T) { hookRepo, appRepo := setupIntegrationHookTestDB(t) svc := NewIntegrationHookService(hookRepo, appRepo, nil) // nil registry — webhook processing tests are separate ctx := context.Background() settings := map[string]interface{}{ "channel": "#alerts", "notify": true, } req := CreateHookRequest{ HookType: "slack", URL: "https://slack.example.com/hook", Settings: settings, } hook, err := svc.Create(ctx, 1, req) require.NoError(t, err) assert.NotNil(t, hook.Settings) }