package automation import ( "context" "testing" ) func TestBotRuleService_Create(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) accountID, _ := seedTestAccount(dbProvider.DB(), t) svc := NewBotRuleService(dbProvider) rule := &BotRule{ AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventConversationCreated, Name: "Auto-respond on create", Conditions: Conditions{ {Attribute: "status", FilterOperator: "equal", Values: []string{"open"}, QueryOperator: "and"}, }, Actions: Actions{ {ActionName: "send_message", ActionParams: map[string]interface{}{"content": "Hello!"}}, }, Status: BotRuleStatusActive, } err := svc.Create(context.Background(), rule) if err != nil { t.Fatalf("expected no error creating bot rule, got: %v", err) } if rule.ID == 0 { t.Fatal("expected bot rule ID to be set after creation") } } func TestBotRuleService_GetByID(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) accountID, _ := seedTestAccount(dbProvider.DB(), t) svc := NewBotRuleService(dbProvider) rule := &BotRule{ AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventMessageCreated, Name: "Auto-label spam", Conditions: Conditions{ {Attribute: "content", FilterOperator: "contains", Values: []string{"spam"}, QueryOperator: "and"}, }, Actions: Actions{ {ActionName: "add_label", ActionParams: map[string]interface{}{"labels": []string{"spam"}}}, }, Status: BotRuleStatusActive, } err := svc.Create(context.Background(), rule) if err != nil { t.Fatalf("create failed: %v", err) } found, err := svc.GetByID(context.Background(), rule.ID) if err != nil { t.Fatalf("GetByID failed: %v", err) } if found.EventName != BotRuleEventMessageCreated { t.Fatalf("expected event_name message_created, got %s", found.EventName) } } func TestBotRuleService_GetByID_NotFound(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) svc := NewBotRuleService(dbProvider) _, err := svc.GetByID(context.Background(), 9999) if err == nil { t.Fatal("expected error for non-existent bot rule, got nil") } } func TestBotRuleService_ListByAccount(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) accountID, _ := seedTestAccount(dbProvider.DB(), t) svc := NewBotRuleService(dbProvider) r1 := &BotRule{AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventConversationCreated, Name: "rule1", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusActive} r2 := &BotRule{AccountID: accountID, AgentBotID: 2, EventName: BotRuleEventMessageCreated, Name: "rule2", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusActive} svc.Create(context.Background(), r1) svc.Create(context.Background(), r2) rules, err := svc.ListByAccount(context.Background(), accountID) if err != nil { t.Fatalf("ListByAccount failed: %v", err) } if len(rules) != 2 { t.Fatalf("expected 2 rules, got %d", len(rules)) } } func TestBotRuleService_ListByAgentBot(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) accountID, _ := seedTestAccount(dbProvider.DB(), t) svc := NewBotRuleService(dbProvider) r1 := &BotRule{AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventConversationCreated, Name: "rule1", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusActive} r2 := &BotRule{AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventMessageCreated, Name: "rule2", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusActive} r3 := &BotRule{AccountID: accountID, AgentBotID: 2, EventName: BotRuleEventConversationUpdated, Name: "rule3", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusActive} svc.Create(context.Background(), r1) svc.Create(context.Background(), r2) svc.Create(context.Background(), r3) rules, err := svc.ListByAgentBot(context.Background(), accountID, 1) if err != nil { t.Fatalf("ListByAgentBot failed: %v", err) } if len(rules) != 2 { t.Fatalf("expected 2 rules for agent_bot_id=1, got %d", len(rules)) } } func TestBotRuleService_ListActiveByAccountAndEvent(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) accountID, _ := seedTestAccount(dbProvider.DB(), t) svc := NewBotRuleService(dbProvider) r1 := &BotRule{AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventConversationCreated, Name: "rule1", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusActive} r2 := &BotRule{AccountID: accountID, AgentBotID: 2, EventName: BotRuleEventConversationCreated, Name: "rule2", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusActive} r3 := &BotRule{AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventMessageCreated, Name: "rule3", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusInactive} svc.Create(context.Background(), r1) svc.Create(context.Background(), r2) svc.Create(context.Background(), r3) rules, err := svc.ListActiveByAccountAndEvent(context.Background(), accountID, "conversation_created") if err != nil { t.Fatalf("ListActiveByAccountAndEvent failed: %v", err) } if len(rules) != 2 { t.Fatalf("expected 2 active rules for conversation_created, got %d", len(rules)) } } func TestBotRuleService_Update(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) accountID, _ := seedTestAccount(dbProvider.DB(), t) svc := NewBotRuleService(dbProvider) rule := &BotRule{ AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventConversationCreated, Name: "rule1", Conditions: Conditions{{Attribute: "status", FilterOperator: "equal", Values: []string{"open"}, QueryOperator: "and"}}, Actions: Actions{{ActionName: "send_message", ActionParams: map[string]interface{}{"content": "Hi"}}}, Status: BotRuleStatusActive, } svc.Create(context.Background(), rule) // Update the rule rule.EventName = BotRuleEventMessageCreated rule.Status = BotRuleStatusInactive err := svc.Update(context.Background(), rule) if err != nil { t.Fatalf("Update failed: %v", err) } found, _ := svc.GetByID(context.Background(), rule.ID) if found.EventName != BotRuleEventMessageCreated { t.Fatalf("expected event_name message_created, got %s", found.EventName) } if found.Status != BotRuleStatusInactive { t.Fatal("expected status=inactive after update") } } func TestBotRuleService_Delete(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) accountID, _ := seedTestAccount(dbProvider.DB(), t) svc := NewBotRuleService(dbProvider) rule := &BotRule{AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventConversationCreated, Name: "rule1", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusActive} svc.Create(context.Background(), rule) err := svc.Delete(context.Background(), rule.ID) if err != nil { t.Fatalf("Delete failed: %v", err) } _, err = svc.GetByID(context.Background(), rule.ID) if err == nil { t.Fatal("expected error after deletion, got nil") } } func TestBotRuleService_Clone(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) accountID, _ := seedTestAccount(dbProvider.DB(), t) svc := NewBotRuleService(dbProvider) rule := &BotRule{ AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventConversationCreated, Name: "Auto-respond", Conditions: Conditions{{Attribute: "status", FilterOperator: "equal", Values: []string{"open"}, QueryOperator: "and"}}, Actions: Actions{{ActionName: "send_message", ActionParams: map[string]interface{}{"content": "Hi"}}}, Status: BotRuleStatusActive, } svc.Create(context.Background(), rule) cloned, err := svc.Clone(context.Background(), rule.ID) if err != nil { t.Fatalf("Clone failed: %v", err) } if cloned.Name != "Auto-respond (copy)" { t.Fatalf("expected cloned name 'Auto-respond (copy)', got %s", cloned.Name) } if cloned.ID == rule.ID { t.Fatal("cloned rule should have a different ID") } } func TestBotRuleService_ToggleStatus(t *testing.T) { dbProvider := setupAutomationTestDBProvider(t) accountID, _ := seedTestAccount(dbProvider.DB(), t) svc := NewBotRuleService(dbProvider) rule := &BotRule{AccountID: accountID, AgentBotID: 1, EventName: BotRuleEventConversationCreated, Name: "rule1", Conditions: Conditions{}, Actions: Actions{}, Status: BotRuleStatusActive} svc.Create(context.Background(), rule) err := svc.ToggleStatus(context.Background(), rule.ID, BotRuleStatusInactive) if err != nil { t.Fatalf("ToggleStatus failed: %v", err) } found, err := svc.GetByID(context.Background(), rule.ID) if err != nil { t.Fatalf("GetByID after toggle failed: %v", err) } if found.Status != BotRuleStatusInactive { t.Fatal("expected status=inactive after toggle") } // Toggle back to active svc.ToggleStatus(context.Background(), rule.ID, BotRuleStatusActive) found2, err := svc.GetByID(context.Background(), rule.ID) if err != nil { t.Fatalf("GetByID after second toggle failed: %v", err) } if found2.Status != BotRuleStatusActive { t.Fatal("expected status=active after second toggle") } }