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

282 lines
7.7 KiB
Go

package service
import (
"context"
"fmt"
"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 setupAgentBotInboxService(t *testing.T) (*AgentBotInboxService, *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.AgentBot{},
&model.Inbox{},
&model.AgentBotInbox{},
), "failed to auto-migrate")
t.Cleanup(func() {
sqlDB, _ := db.DB()
sqlDB.Close()
})
repo := repository.NewAgentBotInboxRepo(db)
botRepo := repository.NewAgentBotRepo(db)
svc := NewAgentBotInboxService(repo, botRepo)
return svc, db
}
// Helper: create prerequisite Account, AgentBot, and Inbox for service tests.
func createSvcPrereqs(t *testing.T, db *gorm.DB) (*model.Account, *model.AgentBot, *model.Inbox) {
t.Helper()
account := &model.Account{Name: "SvcTestOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
bot := &model.AgentBot{
AccountID: &account.ID,
Name: "SvcTestBot",
BotType: "default",
Secret: "secret-svcbot",
AccessToken: "token-svcbot",
}
require.NoError(t, db.Create(bot).Error)
inbox := &model.Inbox{
AccountID: account.ID,
Name: "SvcTestInbox",
ChannelType: "web_widget",
ChannelID: 1,
}
require.NoError(t, db.Create(inbox).Error)
return account, bot, inbox
}
// Helper: create a second bot with unique secret/token for SQLite UNIQUE constraint.
func createSvcSecondBot(t *testing.T, db *gorm.DB, accountID uint, suffix string) *model.AgentBot {
t.Helper()
bot := &model.AgentBot{
AccountID: &accountID,
Name: "SvcBot-" + suffix,
BotType: "default",
Secret: fmt.Sprintf("secret-svc-%s", suffix),
AccessToken: fmt.Sprintf("token-svc-%s", suffix),
}
require.NoError(t, db.Create(bot).Error)
return bot
}
// ========== 1. Bind ==========
func TestAgentBotInboxService_Bind(t *testing.T) {
svc, db := setupAgentBotInboxService(t)
_, bot, inbox := createSvcPrereqs(t, db)
abi, err := svc.Bind(context.Background(), inbox.AccountID, BindBotToInboxRequest{
AgentBotID: bot.ID,
InboxID: inbox.ID,
})
require.NoError(t, err)
assert.NotZero(t, abi.ID)
assert.Equal(t, bot.ID, abi.AgentBotID)
assert.Equal(t, inbox.ID, abi.InboxID)
assert.Equal(t, model.AgentBotInboxActive, abi.Status)
}
func TestAgentBotInboxService_Bind_BotNotFound(t *testing.T) {
svc, _ := setupAgentBotInboxService(t)
abi, err := svc.Bind(context.Background(), 1, BindBotToInboxRequest{
AgentBotID: 9999,
InboxID: 1,
})
assert.Error(t, err)
assert.Nil(t, abi)
assert.Contains(t, err.Error(), "agent bot not found")
}
func TestAgentBotInboxService_Bind_Duplicate(t *testing.T) {
svc, db := setupAgentBotInboxService(t)
_, bot, inbox := createSvcPrereqs(t, db)
// First bind succeeds
_, err := svc.Bind(context.Background(), inbox.AccountID, BindBotToInboxRequest{
AgentBotID: bot.ID,
InboxID: inbox.ID,
})
require.NoError(t, err)
// Second bind fails (duplicate)
abi, err := svc.Bind(context.Background(), inbox.AccountID, BindBotToInboxRequest{
AgentBotID: bot.ID,
InboxID: inbox.ID,
})
assert.Error(t, err)
assert.Nil(t, abi)
assert.Contains(t, err.Error(), "already bound")
}
// ========== 2. Unbind ==========
func TestAgentBotInboxService_Unbind(t *testing.T) {
svc, db := setupAgentBotInboxService(t)
_, bot, inbox := createSvcPrereqs(t, db)
abi, err := svc.Bind(context.Background(), inbox.AccountID, BindBotToInboxRequest{
AgentBotID: bot.ID,
InboxID: inbox.ID,
})
require.NoError(t, err)
err = svc.Unbind(context.Background(), abi.ID)
assert.NoError(t, err)
// Verify binding is gone
abis, err := svc.ListByInbox(context.Background(), inbox.ID)
assert.NoError(t, err)
assert.Len(t, abis, 0)
}
func TestAgentBotInboxService_Unbind_NotFound(t *testing.T) {
svc, _ := setupAgentBotInboxService(t)
err := svc.Unbind(context.Background(), 9999)
assert.NoError(t, err) // GORM delete on non-existent row returns no error
}
// ========== 3. UpdateStatus ==========
func TestAgentBotInboxService_UpdateStatus(t *testing.T) {
svc, db := setupAgentBotInboxService(t)
_, bot, inbox := createSvcPrereqs(t, db)
abi, err := svc.Bind(context.Background(), inbox.AccountID, BindBotToInboxRequest{
AgentBotID: bot.ID,
InboxID: inbox.ID,
})
require.NoError(t, err)
assert.Equal(t, model.AgentBotInboxActive, abi.Status)
// Toggle to inactive
updated, err := svc.UpdateStatus(context.Background(), abi.ID, UpdateBindingStatusRequest{Status: 1})
require.NoError(t, err)
assert.Equal(t, model.AgentBotInboxInactive, updated.Status)
// Toggle back to active
updated2, err := svc.UpdateStatus(context.Background(), abi.ID, UpdateBindingStatusRequest{Status: 0})
require.NoError(t, err)
assert.Equal(t, model.AgentBotInboxActive, updated2.Status)
}
func TestAgentBotInboxService_UpdateStatus_NotFound(t *testing.T) {
svc, _ := setupAgentBotInboxService(t)
abi, err := svc.UpdateStatus(context.Background(), 9999, UpdateBindingStatusRequest{Status: 1})
assert.Error(t, err)
assert.Nil(t, abi)
assert.Contains(t, err.Error(), "binding not found")
}
// ========== 4. ListByInbox ==========
func TestAgentBotInboxService_ListByInbox(t *testing.T) {
svc, db := setupAgentBotInboxService(t)
_, bot, inbox := createSvcPrereqs(t, db)
_, err := svc.Bind(context.Background(), inbox.AccountID, BindBotToInboxRequest{
AgentBotID: bot.ID,
InboxID: inbox.ID,
})
require.NoError(t, err)
abis, err := svc.ListByInbox(context.Background(), inbox.ID)
assert.NoError(t, err)
assert.Len(t, abis, 1)
assert.Equal(t, bot.ID, abis[0].AgentBotID)
}
func TestAgentBotInboxService_ListByInbox_Empty(t *testing.T) {
svc, _ := setupAgentBotInboxService(t)
abis, err := svc.ListByInbox(context.Background(), 9999)
assert.NoError(t, err)
assert.Len(t, abis, 0)
}
// ========== 5. ListActiveByInbox ==========
func TestAgentBotInboxService_ListActiveByInbox(t *testing.T) {
svc, db := setupAgentBotInboxService(t)
_, bot, inbox := createSvcPrereqs(t, db)
abi, err := svc.Bind(context.Background(), inbox.AccountID, BindBotToInboxRequest{
AgentBotID: bot.ID,
InboxID: inbox.ID,
})
require.NoError(t, err)
// Initially active
abis, err := svc.ListActiveByInbox(context.Background(), inbox.ID)
assert.NoError(t, err)
assert.Len(t, abis, 1)
// Toggle to inactive
_, err = svc.UpdateStatus(context.Background(), abi.ID, UpdateBindingStatusRequest{Status: 1})
require.NoError(t, err)
// No active bindings now
abis, err = svc.ListActiveByInbox(context.Background(), inbox.ID)
assert.NoError(t, err)
assert.Len(t, abis, 0)
// But ListByInbox still shows 1
allAbis, err := svc.ListByInbox(context.Background(), inbox.ID)
assert.NoError(t, err)
assert.Len(t, allAbis, 1)
}
// ========== 6. ListByBot ==========
func TestAgentBotInboxService_ListByBot(t *testing.T) {
svc, db := setupAgentBotInboxService(t)
_, bot, inbox := createSvcPrereqs(t, db)
_, err := svc.Bind(context.Background(), inbox.AccountID, BindBotToInboxRequest{
AgentBotID: bot.ID,
InboxID: inbox.ID,
})
require.NoError(t, err)
abis, err := svc.ListByBot(context.Background(), bot.ID)
assert.NoError(t, err)
assert.Len(t, abis, 1)
assert.Equal(t, inbox.ID, abis[0].InboxID)
}
func TestAgentBotInboxService_ListByBot_Empty(t *testing.T) {
svc, db := setupAgentBotInboxService(t)
_, bot, _ := createSvcPrereqs(t, db)
abis, err := svc.ListByBot(context.Background(), bot.ID)
assert.NoError(t, err)
assert.Len(t, abis, 0)
}