package service import ( "encoding/json" "strings" "testing" "github.com/user-management-system/internal/domain" ) // ============================================================================= // Webhook Utility Functions Tests // ============================================================================= func TestGenerateEventID(t *testing.T) { t.Run("generates valid event ID", func(t *testing.T) { id, err := generateEventID() if err != nil { t.Fatalf("generateEventID failed: %v", err) } if !strings.HasPrefix(id, "evt_") { t.Errorf("Expected ID to start with 'evt_', got %q", id) } if len(id) != 20 { // "evt_" + 16 hex chars (8 bytes) t.Errorf("Expected ID length 20, got %d", len(id)) } }) t.Run("generates unique IDs", func(t *testing.T) { id1, _ := generateEventID() id2, _ := generateEventID() if id1 == id2 { t.Error("Expected different IDs on each call") } }) } func TestGenerateWebhookSecret(t *testing.T) { t.Run("generates valid secret", func(t *testing.T) { secret, err := generateWebhookSecret() if err != nil { t.Fatalf("generateWebhookSecret failed: %v", err) } if len(secret) != 48 { // 24 bytes = 48 hex chars t.Errorf("Expected secret length 48, got %d", len(secret)) } // Check that secret is lowercase hex for _, c := range secret { if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) { t.Errorf("Expected lowercase hex characters, got %c", c) break } } }) t.Run("generates unique secrets", func(t *testing.T) { secret1, _ := generateWebhookSecret() secret2, _ := generateWebhookSecret() if secret1 == secret2 { t.Error("Expected different secrets on each call") } }) } func TestWebhookSubscribesTo(t *testing.T) { tests := []struct { name string events []domain.WebhookEventType event domain.WebhookEventType expected bool }{ {"empty events list", []domain.WebhookEventType{}, "user.created", false}, {"exact match", []domain.WebhookEventType{"user.created", "user.updated"}, "user.created", true}, {"no match", []domain.WebhookEventType{"user.created", "user.updated"}, "user.deleted", false}, {"all events wildcard", []domain.WebhookEventType{"*"}, "any.event", true}, {"exact match different event", []domain.WebhookEventType{"user.created"}, "user.updated", false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { eventsJSON, _ := json.Marshal(tt.events) webhook := &domain.Webhook{ Events: string(eventsJSON), } result := webhookSubscribesTo(webhook, tt.event) if result != tt.expected { t.Errorf("webhookSubscribesTo(%v, %q) = %v, want %v", tt.events, tt.event, result, tt.expected) } }) } } func TestWebhookSubscribesTo_InvalidJSON(t *testing.T) { t.Run("invalid JSON returns false", func(t *testing.T) { webhook := &domain.Webhook{ Events: "invalid json", } result := webhookSubscribesTo(webhook, "user.created") if result { t.Error("Expected false for invalid JSON") } }) }