344 lines
12 KiB
Go
344 lines
12 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"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 setupConversationParticipantServiceTestDB(t *testing.T) *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.Inbox{},
|
|
&model.Contact{},
|
|
&model.ContactInbox{},
|
|
&model.Conversation{},
|
|
&model.ConversationParticipant{},
|
|
), "failed to auto-migrate")
|
|
|
|
t.Cleanup(func() {
|
|
sqlDB, _ := db.DB()
|
|
sqlDB.Close()
|
|
})
|
|
|
|
return db
|
|
}
|
|
|
|
func createParticipantTestAccount(t *testing.T, db *gorm.DB) *model.Account {
|
|
t.Helper()
|
|
account := &model.Account{Name: "ParticipantTestOrg", Locale: "en", Active: true}
|
|
require.NoError(t, db.Create(account).Error)
|
|
return account
|
|
}
|
|
|
|
func createParticipantTestUser(t *testing.T, db *gorm.DB) *model.User {
|
|
t.Helper()
|
|
user := &model.User{Name: "TestAgent", Email: "agent@test.com", Provider: "email", Role: "agent"}
|
|
require.NoError(t, db.Create(user).Error)
|
|
return user
|
|
}
|
|
|
|
func createParticipantTestInbox(t *testing.T, db *gorm.DB, accountID uint) *model.Inbox {
|
|
t.Helper()
|
|
inbox := &model.Inbox{AccountID: accountID, Name: "TestInbox", ChannelType: "web_widget", ChannelID: 1, Enabled: true}
|
|
require.NoError(t, db.Create(inbox).Error)
|
|
return inbox
|
|
}
|
|
|
|
func createParticipantTestContact(t *testing.T, db *gorm.DB, accountID uint) *model.Contact {
|
|
t.Helper()
|
|
contact := &model.Contact{AccountID: accountID, Name: "TestContact", Email: "contact@test.com"}
|
|
require.NoError(t, db.Create(contact).Error)
|
|
return contact
|
|
}
|
|
|
|
func createParticipantTestConversation(t *testing.T, db *gorm.DB, accountID, inboxID, contactID uint) *model.Conversation {
|
|
t.Helper()
|
|
conversation := &model.Conversation{
|
|
AccountID: accountID,
|
|
InboxID: inboxID,
|
|
ContactID: contactID,
|
|
ChannelType: "web_widget",
|
|
Channel: "web_widget",
|
|
Status: "open",
|
|
}
|
|
require.NoError(t, db.Create(conversation).Error)
|
|
return conversation
|
|
}
|
|
|
|
func setupConversationParticipantService(t *testing.T) (*ConversationParticipantService, *gorm.DB) {
|
|
t.Helper()
|
|
db := setupConversationParticipantServiceTestDB(t)
|
|
repo := repository.NewConversationParticipantRepo(db)
|
|
conversationRepo := repository.NewConversationRepo(db)
|
|
svc := NewConversationParticipantService(repo, conversationRepo)
|
|
return svc, db
|
|
}
|
|
|
|
// ========== Add Participant Tests ==========
|
|
|
|
func TestConversationParticipantService_Add_Success(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
participant, err := svc.Add(ctx, account.ID, conversation.ID, user.ID, "assignee")
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, participant)
|
|
assert.Equal(t, conversation.ID, participant.ConversationID)
|
|
assert.Equal(t, user.ID, participant.UserID)
|
|
assert.Equal(t, "assignee", participant.Role)
|
|
}
|
|
|
|
func TestConversationParticipantService_Add_DefaultRole(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
participant, err := svc.Add(ctx, account.ID, conversation.ID, user.ID, "")
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, participant)
|
|
assert.Equal(t, "participant", participant.Role)
|
|
}
|
|
|
|
func TestConversationParticipantService_Add_ConversationNotFound(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
|
|
participant, err := svc.Add(ctx, account.ID, 99999, user.ID, "participant")
|
|
assert.Error(t, err)
|
|
assert.Nil(t, participant)
|
|
}
|
|
|
|
func TestConversationParticipantService_Add_AccountMismatch(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
// Use a different accountID that doesn't own the conversation
|
|
wrongAccountID := uint(99999)
|
|
participant, err := svc.Add(ctx, wrongAccountID, conversation.ID, user.ID, "participant")
|
|
assert.Error(t, err)
|
|
assert.Nil(t, participant)
|
|
}
|
|
|
|
// ========== List Participants Tests ==========
|
|
|
|
func TestConversationParticipantService_List_Success(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user1 := createParticipantTestUser(t, db)
|
|
// Create second user with unique email
|
|
user2 := &model.User{Name: "TestAgent2", Email: "agent2@test.com", Provider: "email", Role: "agent"}
|
|
require.NoError(t, db.Create(user2).Error)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
// Add two participants
|
|
_, err := svc.Add(ctx, account.ID, conversation.ID, user1.ID, "assignee")
|
|
require.NoError(t, err)
|
|
_, err = svc.Add(ctx, account.ID, conversation.ID, user2.ID, "watcher")
|
|
require.NoError(t, err)
|
|
|
|
participants, err := svc.List(ctx, account.ID, conversation.ID)
|
|
require.NoError(t, err)
|
|
assert.Len(t, participants, 2)
|
|
}
|
|
|
|
func TestConversationParticipantService_List_Empty(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
participants, err := svc.List(ctx, account.ID, conversation.ID)
|
|
require.NoError(t, err)
|
|
assert.Empty(t, participants)
|
|
}
|
|
|
|
func TestConversationParticipantService_List_ConversationNotFound(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
|
|
participants, err := svc.List(ctx, account.ID, 99999)
|
|
assert.Error(t, err)
|
|
assert.Nil(t, participants)
|
|
}
|
|
|
|
func TestConversationParticipantService_List_AccountMismatch(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
participants, err := svc.List(ctx, 99999, conversation.ID)
|
|
assert.Error(t, err)
|
|
assert.Nil(t, participants)
|
|
}
|
|
|
|
// ========== Update Participant Role Tests ==========
|
|
|
|
func TestConversationParticipantService_Update_Success(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
// Add participant with "participant" role
|
|
_, err := svc.Add(ctx, account.ID, conversation.ID, user.ID, "participant")
|
|
require.NoError(t, err)
|
|
|
|
// Update role to "assignee"
|
|
updated, err := svc.Update(ctx, account.ID, conversation.ID, user.ID, "assignee")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "assignee", updated.Role)
|
|
}
|
|
|
|
func TestConversationParticipantService_Update_ConversationNotFound(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
|
|
updated, err := svc.Update(ctx, account.ID, 99999, user.ID, "assignee")
|
|
assert.Error(t, err)
|
|
assert.Nil(t, updated)
|
|
}
|
|
|
|
func TestConversationParticipantService_Update_AccountMismatch(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
_, err := svc.Add(ctx, account.ID, conversation.ID, user.ID, "participant")
|
|
require.NoError(t, err)
|
|
|
|
updated, err := svc.Update(ctx, 99999, conversation.ID, user.ID, "assignee")
|
|
assert.Error(t, err)
|
|
assert.Nil(t, updated)
|
|
}
|
|
|
|
func TestConversationParticipantService_Update_ParticipantNotFound(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
// Try to update a participant that doesn't exist in the conversation
|
|
updated, err := svc.Update(ctx, account.ID, conversation.ID, user.ID, "assignee")
|
|
assert.Error(t, err)
|
|
assert.Nil(t, updated)
|
|
}
|
|
|
|
// ========== Remove Participant Tests ==========
|
|
|
|
func TestConversationParticipantService_Remove_Success(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
_, err := svc.Add(ctx, account.ID, conversation.ID, user.ID, "participant")
|
|
require.NoError(t, err)
|
|
|
|
err = svc.Remove(ctx, account.ID, conversation.ID, user.ID)
|
|
require.NoError(t, err)
|
|
|
|
// Verify participant is removed
|
|
participants, err := svc.List(ctx, account.ID, conversation.ID)
|
|
require.NoError(t, err)
|
|
assert.Empty(t, participants)
|
|
}
|
|
|
|
func TestConversationParticipantService_Remove_ConversationNotFound(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
|
|
err := svc.Remove(ctx, account.ID, 99999, user.ID)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestConversationParticipantService_Remove_AccountMismatch(t *testing.T) {
|
|
svc, db := setupConversationParticipantService(t)
|
|
ctx := context.Background()
|
|
|
|
account := createParticipantTestAccount(t, db)
|
|
user := createParticipantTestUser(t, db)
|
|
inbox := createParticipantTestInbox(t, db, account.ID)
|
|
contact := createParticipantTestContact(t, db, account.ID)
|
|
conversation := createParticipantTestConversation(t, db, account.ID, inbox.ID, contact.ID)
|
|
|
|
_, err := svc.Add(ctx, account.ID, conversation.ID, user.ID, "participant")
|
|
require.NoError(t, err)
|
|
|
|
err = svc.Remove(ctx, 99999, conversation.ID, user.ID)
|
|
assert.Error(t, err)
|
|
} |