Files
gochat/internal/service/agent_capacity_policy_service_test.go
T

315 lines
10 KiB
Go

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"
)
// ========== Test Setup ==========
func setupACPolicyServiceTest(t *testing.T) (*AgentCapacityPolicyService, *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 db")
require.NoError(t, db.AutoMigrate(
&model.Account{},
&model.User{},
&model.AccountUser{},
&model.Inbox{},
&model.AgentCapacityPolicy{},
&model.InboxCapacityLimit{},
), "failed to auto-migrate")
t.Cleanup(func() {
sqlDB, _ := db.DB()
sqlDB.Close()
})
repo := repository.NewAgentCapacityPolicyRepo(db)
svc := NewAgentCapacityPolicyService(repo)
return svc, db
}
func acStringPtr(value string) *string { return &value }
func createACPSvcTestAccount(t *testing.T, db *gorm.DB) *model.Account {
t.Helper()
account := &model.Account{Name: "ACPServiceOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
return account
}
// ========== List ==========
func TestAgentCapacityPolicyService_List(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
_, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "PolicyA",
AssignmentLogic: "round_robin",
ExclusionRules: json.RawMessage(`{"exclude_offline":true}`),
})
require.NoError(t, err)
_, err = svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "PolicyB",
AssignmentLogic: "least_busy",
ExclusionRules: json.RawMessage(`{"exclude_offline":false}`),
})
require.NoError(t, err)
policies, total, err := svc.List(context.Background(), account.ID, 1, 25)
assert.NoError(t, err)
assert.Equal(t, int64(2), total)
assert.Len(t, policies, 2)
}
func TestAgentCapacityPolicyService_List_Empty(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
policies, total, err := svc.List(context.Background(), account.ID, 1, 25)
assert.NoError(t, err)
assert.Equal(t, int64(0), total)
assert.Len(t, policies, 0)
}
// ========== Create ==========
func TestAgentCapacityPolicyService_Create(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
policy, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "RoundRobinPolicy",
ExclusionRules: json.RawMessage(`{"exclude_offline":true}`),
})
assert.NoError(t, err)
assert.NotZero(t, policy.ID)
assert.Equal(t, "RoundRobinPolicy", policy.Name)
assert.Equal(t, "round_robin", policy.AssignmentLogic)
}
func TestAgentCapacityPolicyService_Create_InvalidLogic(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
_, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "BadPolicy",
AssignmentLogic: "invalid_logic",
})
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid assignment_logic")
}
// ========== GetByID ==========
func TestAgentCapacityPolicyService_GetByID(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
created, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "TestPolicy",
AssignmentLogic: "least_busy",
})
require.NoError(t, err)
found, err := svc.GetByID(context.Background(), created.ID, account.ID)
assert.NoError(t, err)
assert.Equal(t, created.ID, found.ID)
assert.Equal(t, "TestPolicy", found.Name)
}
func TestAgentCapacityPolicyService_GetByID_WrongAccount(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
created, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "TestPolicy",
AssignmentLogic: "round_robin",
})
require.NoError(t, err)
_, err = svc.GetByID(context.Background(), created.ID, 9999)
assert.Error(t, err)
}
func TestAgentCapacityPolicyService_GetByID_NotFound(t *testing.T) {
svc, _ := setupACPolicyServiceTest(t)
_, err := svc.GetByID(context.Background(), 9999, 1)
assert.Error(t, err)
}
// ========== Update ==========
func TestAgentCapacityPolicyService_Update(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
created, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "OldPolicy",
AssignmentLogic: "round_robin",
})
require.NoError(t, err)
updated, err := svc.Update(context.Background(), created.ID, account.ID, UpdateAgentCapacityPolicyRequest{
Name: acStringPtr("NewPolicy"),
AssignmentLogic: "least_busy",
})
assert.NoError(t, err)
assert.Equal(t, "NewPolicy", updated.Name)
assert.Equal(t, "least_busy", updated.AssignmentLogic)
}
func TestAgentCapacityPolicyService_Update_InvalidLogic(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
created, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "TestPolicy",
AssignmentLogic: "round_robin",
})
require.NoError(t, err)
_, err = svc.Update(context.Background(), created.ID, account.ID, UpdateAgentCapacityPolicyRequest{
AssignmentLogic: "invalid",
})
assert.Error(t, err)
}
func TestAgentCapacityPolicyService_Update_NotFound(t *testing.T) {
svc, _ := setupACPolicyServiceTest(t)
_, err := svc.Update(context.Background(), 9999, 1, UpdateAgentCapacityPolicyRequest{
Name: acStringPtr("Ghost"),
})
assert.Error(t, err)
}
func TestAgentCapacityPolicyService_InboxCapacityLimitFlow(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
inbox := &model.Inbox{AccountID: account.ID, Name: "Priority", ChannelType: "web_widget"}
require.NoError(t, db.Create(inbox).Error)
otherAccount := createACPSvcTestAccount(t, db)
otherInbox := &model.Inbox{AccountID: otherAccount.ID, Name: "Other", ChannelType: "web_widget"}
require.NoError(t, db.Create(otherInbox).Error)
policy, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{Name: "Policy"})
require.NoError(t, err)
limit, err := svc.CreateInboxCapacityLimit(context.Background(), policy.ID, account.ID, CreateInboxCapacityLimitRequest{
InboxID: inbox.ID,
ConversationLimit: 7,
})
require.NoError(t, err)
assert.Equal(t, inbox.ID, limit.InboxID)
assert.Equal(t, 7, limit.ConversationLimit)
_, err = svc.CreateInboxCapacityLimit(context.Background(), policy.ID, account.ID, CreateInboxCapacityLimitRequest{InboxID: inbox.ID, ConversationLimit: 9})
assert.Error(t, err)
assert.Contains(t, err.Error(), "already been assigned")
_, err = svc.CreateInboxCapacityLimit(context.Background(), policy.ID, account.ID, CreateInboxCapacityLimitRequest{InboxID: otherInbox.ID, ConversationLimit: 1})
assert.Error(t, err)
assert.Contains(t, err.Error(), "inbox not found")
_, err = svc.UpdateInboxCapacityLimit(context.Background(), policy.ID, account.ID, limit.ID, UpdateInboxCapacityLimitRequest{ConversationLimit: -1})
assert.Error(t, err)
assert.Contains(t, err.Error(), "greater than or equal")
updated, err := svc.UpdateInboxCapacityLimit(context.Background(), policy.ID, account.ID, limit.ID, UpdateInboxCapacityLimitRequest{ConversationLimit: 11})
require.NoError(t, err)
assert.Equal(t, 11, updated.ConversationLimit)
assert.Equal(t, "Priority", updated.Inbox.Name)
require.NoError(t, svc.DeleteInboxCapacityLimit(context.Background(), policy.ID, account.ID, limit.ID))
_, err = svc.UpdateInboxCapacityLimit(context.Background(), policy.ID, account.ID, limit.ID, UpdateInboxCapacityLimitRequest{ConversationLimit: 1})
assert.Error(t, err)
}
func TestAgentCapacityPolicyService_UserAssignmentFlow(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
policy, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{Name: "Policy"})
require.NoError(t, err)
user := &model.User{AccountID: account.ID, Name: "Agent", Email: "agent@example.com", Password: "secret", Role: "agent"}
require.NoError(t, db.Create(user).Error)
accountUser := &model.AccountUser{AccountID: account.ID, UserID: user.ID, Role: "agent"}
require.NoError(t, db.Create(accountUser).Error)
assigned, err := svc.AssignUser(context.Background(), policy.ID, account.ID, AssignCapacityPolicyUserRequest{UserID: user.ID})
require.NoError(t, err)
assert.Equal(t, user.ID, assigned.ID)
users, err := svc.ListUsers(context.Background(), policy.ID, account.ID)
require.NoError(t, err)
assert.Len(t, users, 1)
require.NoError(t, svc.RemoveUser(context.Background(), policy.ID, account.ID, user.ID))
users, err = svc.ListUsers(context.Background(), policy.ID, account.ID)
require.NoError(t, err)
assert.Empty(t, users)
}
// ========== Delete ==========
func TestAgentCapacityPolicyService_Delete(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
created, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "DeletablePolicy",
AssignmentLogic: "round_robin",
})
require.NoError(t, err)
err = svc.Delete(context.Background(), created.ID, account.ID)
assert.NoError(t, err)
// Should no longer find it
_, err = svc.GetByID(context.Background(), created.ID, account.ID)
assert.Error(t, err)
}
func TestAgentCapacityPolicyService_Delete_WrongAccount(t *testing.T) {
svc, db := setupACPolicyServiceTest(t)
account := createACPSvcTestAccount(t, db)
created, err := svc.Create(context.Background(), account.ID, CreateAgentCapacityPolicyRequest{
Name: "ProtectedPolicy",
AssignmentLogic: "round_robin",
})
require.NoError(t, err)
err = svc.Delete(context.Background(), created.ID, 9999)
assert.Error(t, err)
// Policy should still exist
found, err := svc.GetByID(context.Background(), created.ID, account.ID)
assert.NoError(t, err)
assert.Equal(t, created.ID, found.ID)
}
func TestAgentCapacityPolicyService_Delete_NotFound(t *testing.T) {
svc, _ := setupACPolicyServiceTest(t)
err := svc.Delete(context.Background(), 9999, 1)
assert.Error(t, err)
}