Files
gochat/internal/automation/service_test.go
T
2026-06-04 15:44:48 +08:00

295 lines
8.7 KiB
Go

package automation
import (
"context"
"testing"
)
func TestAutomationRuleService_Create(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
accountID, _ := seedTestAccount(dbProvider.DB(), t)
svc := NewAutomationRuleService(dbProvider)
rule := &AutomationRule{
AccountID: accountID,
EventName: "conversation_created",
Name: "Auto-assign on create",
Description: "Assigns new conversations to team",
Conditions: Conditions{
{Attribute: "status", FilterOperator: "equal", Values: []string{"open"}, QueryOperator: "and"},
},
Actions: Actions{
{ActionName: "assign_team", ActionParams: map[string]interface{}{"team_id": "1"}},
},
Active: true,
}
err := svc.Create(context.Background(), rule)
if err != nil {
t.Fatalf("expected no error creating rule, got: %v", err)
}
if rule.ID == 0 {
t.Fatal("expected rule ID to be set after creation")
}
}
func TestAutomationRuleService_GetByID(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
accountID, _ := seedTestAccount(dbProvider.DB(), t)
svc := NewAutomationRuleService(dbProvider)
rule := &AutomationRule{
AccountID: accountID,
EventName: "message_created",
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"}}},
},
Active: true,
}
if err := svc.Create(context.Background(), rule); err != nil {
t.Fatalf("setup: failed to create rule: %v", err)
}
found, err := svc.GetByID(context.Background(), rule.ID)
if err != nil {
t.Fatalf("expected no error getting rule, got: %v", err)
}
if found.ID != rule.ID {
t.Fatalf("expected rule ID %d, got %d", rule.ID, found.ID)
}
if found.Name != "Auto-label spam" {
t.Fatalf("expected name 'Auto-label spam', got %q", found.Name)
}
}
func TestAutomationRuleService_GetByID_NotFound(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
svc := NewAutomationRuleService(dbProvider)
_, err := svc.GetByID(context.Background(), 9999)
if err == nil {
t.Fatal("expected error for non-existent rule, got nil")
}
}
func TestAutomationRuleService_Update(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
accountID, _ := seedTestAccount(dbProvider.DB(), t)
svc := NewAutomationRuleService(dbProvider)
rule := &AutomationRule{
AccountID: accountID,
EventName: "conversation_created",
Name: "Original name",
Conditions: Conditions{},
Actions: Actions{},
Active: true,
}
if err := svc.Create(context.Background(), rule); err != nil {
t.Fatalf("setup: failed to create rule: %v", err)
}
rule.Name = "Updated name"
rule.Active = false
err := svc.Update(context.Background(), rule)
if err != nil {
t.Fatalf("expected no error updating rule, got: %v", err)
}
found, _ := svc.GetByID(context.Background(), rule.ID)
if found.Name != "Updated name" {
t.Fatalf("expected name 'Updated name', got %q", found.Name)
}
if found.Active != false {
t.Fatal("expected active to be false after update")
}
}
func TestAutomationRuleService_Delete(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
accountID, _ := seedTestAccount(dbProvider.DB(), t)
svc := NewAutomationRuleService(dbProvider)
rule := &AutomationRule{
AccountID: accountID,
EventName: "conversation_created",
Name: "Delete me",
Conditions: Conditions{},
Actions: Actions{},
Active: true,
}
if err := svc.Create(context.Background(), rule); err != nil {
t.Fatalf("setup: failed to create rule: %v", err)
}
err := svc.Delete(context.Background(), rule.ID)
if err != nil {
t.Fatalf("expected no error deleting rule, got: %v", err)
}
_, err = svc.GetByID(context.Background(), rule.ID)
if err == nil {
t.Fatal("expected error getting deleted rule, got nil")
}
}
func TestAutomationRuleService_ListByAccount(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
accountID, _ := seedTestAccount(dbProvider.DB(), t)
svc := NewAutomationRuleService(dbProvider)
// Create 3 rules
for i := 0; i < 3; i++ {
rule := &AutomationRule{
AccountID: accountID,
EventName: "conversation_created",
Name: "Rule " + string(rune('A'+i)),
Conditions: Conditions{},
Actions: Actions{},
Active: true,
}
if err := svc.Create(context.Background(), rule); err != nil {
t.Fatalf("setup: failed to create rule %d: %v", i, err)
}
}
rules, err := svc.ListByAccount(context.Background(), accountID)
if err != nil {
t.Fatalf("expected no error listing rules, got: %v", err)
}
if len(rules) != 3 {
t.Fatalf("expected 3 rules, got %d", len(rules))
}
}
func TestAutomationRuleService_ListActiveByAccountAndEvent(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
accountID, _ := seedTestAccount(dbProvider.DB(), t)
svc := NewAutomationRuleService(dbProvider)
// Create active rule for conversation_created
rule1 := &AutomationRule{
AccountID: accountID, EventName: "conversation_created", Name: "Active rule",
Conditions: Conditions{}, Actions: Actions{}, Active: true,
}
if err := svc.Create(context.Background(), rule1); err != nil {
t.Fatalf("setup: %v", err)
}
// Create inactive rule for conversation_created
rule2 := &AutomationRule{
AccountID: accountID, EventName: "conversation_created", Name: "Inactive rule",
Conditions: Conditions{}, Actions: Actions{}, Active: false,
}
if err := svc.Create(context.Background(), rule2); err != nil {
t.Fatalf("setup: %v", err)
}
// Create active rule for different event
rule3 := &AutomationRule{
AccountID: accountID, EventName: "message_created", Name: "Different event",
Conditions: Conditions{}, Actions: Actions{}, Active: true,
}
if err := svc.Create(context.Background(), rule3); err != nil {
t.Fatalf("setup: %v", err)
}
rules, err := svc.ListActiveByAccountAndEvent(context.Background(), accountID, "conversation_created")
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
if len(rules) != 1 {
t.Fatalf("expected 1 active rule for conversation_created, got %d", len(rules))
}
if rules[0].Name != "Active rule" {
t.Fatalf("expected 'Active rule', got %q", rules[0].Name)
}
}
func TestAutomationRuleService_ToggleActive(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
accountID, _ := seedTestAccount(dbProvider.DB(), t)
svc := NewAutomationRuleService(dbProvider)
rule := &AutomationRule{
AccountID: accountID, EventName: "conversation_created", Name: "Toggle test",
Conditions: Conditions{}, Actions: Actions{}, Active: true,
}
if err := svc.Create(context.Background(), rule); err != nil {
t.Fatalf("setup: %v", err)
}
// Toggle to inactive
err := svc.ToggleActive(context.Background(), rule.ID, false)
if err != nil {
t.Fatalf("expected no error toggling active, got: %v", err)
}
found, _ := svc.GetByID(context.Background(), rule.ID)
if found.Active {
t.Fatal("expected active=false after toggle")
}
// Toggle back to active
err = svc.ToggleActive(context.Background(), rule.ID, true)
if err != nil {
t.Fatalf("expected no error toggling active back, got: %v", err)
}
found, _ = svc.GetByID(context.Background(), rule.ID)
if !found.Active {
t.Fatal("expected active=true after toggle back")
}
}
func TestAutomationRuleService_Clone(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
accountID, _ := seedTestAccount(dbProvider.DB(), t)
svc := NewAutomationRuleService(dbProvider)
rule := &AutomationRule{
AccountID: accountID,
EventName: "conversation_created",
Name: "Source rule",
Conditions: Conditions{
{Attribute: "status", FilterOperator: "equal", Values: []string{"open"}, QueryOperator: "and"},
},
Actions: Actions{
{ActionName: "assign_team", ActionParams: map[string]interface{}{"team_id": "1"}},
},
Active: true,
}
if err := svc.Create(context.Background(), rule); err != nil {
t.Fatalf("setup: %v", err)
}
cloned, err := svc.Clone(context.Background(), rule.ID)
if err != nil {
t.Fatalf("expected no error cloning rule, got: %v", err)
}
if cloned.ID == rule.ID {
t.Fatal("expected cloned rule to have different ID")
}
if cloned.Name != "Source rule (copy)" {
t.Fatalf("expected cloned name 'Source rule (copy)', got %q", cloned.Name)
}
if len(cloned.Conditions) != 1 {
t.Fatalf("expected 1 cloned condition, got %d", len(cloned.Conditions))
}
if len(cloned.Actions) != 1 {
t.Fatalf("expected 1 cloned action, got %d", len(cloned.Actions))
}
}
func TestAutomationRuleService_Clone_NotFound(t *testing.T) {
dbProvider := setupAutomationTestDBProvider(t)
svc := NewAutomationRuleService(dbProvider)
_, err := svc.Clone(context.Background(), 9999)
if err == nil {
t.Fatal("expected error cloning non-existent rule, got nil")
}
}