480 lines
16 KiB
Go
480 lines
16 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/gochat/gochat/internal/model"
|
|
)
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// AccountUserRepo
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func TestAccountUserRepo_FindByAccountAndUser(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
au := &model.AccountUser{AccountID: 10, UserID: 20, Role: "agent"}
|
|
require.NoError(t, db.Create(au).Error)
|
|
|
|
found, err := repo.FindByAccountAndUser(ctx, 10, 20)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, found)
|
|
assert.Equal(t, au.ID, found.ID)
|
|
}
|
|
|
|
func TestAccountUserRepo_FindByAccountAndUser_NotFound(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
found, err := repo.FindByAccountAndUser(ctx, 9999, 9999)
|
|
require.NoError(t, err)
|
|
assert.Nil(t, found)
|
|
}
|
|
|
|
func TestAccountUserRepo_FindOnlineAgentsByAccount(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 1, Role: "agent", Availability: "online"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 2, Role: "agent", Availability: "offline"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 3, Role: "agent", Availability: "online"}).Error)
|
|
|
|
agents, err := repo.FindOnlineAgentsByAccount(ctx, 1)
|
|
require.NoError(t, err)
|
|
assert.Len(t, agents, 2)
|
|
}
|
|
|
|
func TestAccountUserRepo_FindByAccount(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 1, Role: "agent"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 2, Role: "admin"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 2, UserID: 3, Role: "agent"}).Error)
|
|
|
|
agents, total, err := repo.FindByAccount(ctx, 1, 0, 10)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(2), total)
|
|
assert.Len(t, agents, 2)
|
|
|
|
// Pagination
|
|
agents, total, err = repo.FindByAccount(ctx, 1, 0, 1)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(2), total)
|
|
assert.Len(t, agents, 1)
|
|
}
|
|
|
|
func TestAccountUserRepo_UpdateAvailability(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 10, Role: "agent", Availability: "offline"}).Error)
|
|
|
|
require.NoError(t, repo.UpdateAvailability(ctx, 1, 10, "online"))
|
|
|
|
au, err := repo.FindByAccountAndUser(ctx, 1, 10)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "online", au.Availability)
|
|
}
|
|
|
|
func TestAccountUserRepo_IsAdministrator(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 10, Role: "administrator"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 20, Role: "agent"}).Error)
|
|
|
|
isAdmin, err := repo.IsAdministrator(ctx, 1, 10)
|
|
require.NoError(t, err)
|
|
assert.True(t, isAdmin)
|
|
|
|
isAdmin, err = repo.IsAdministrator(ctx, 1, 20)
|
|
require.NoError(t, err)
|
|
assert.False(t, isAdmin)
|
|
}
|
|
|
|
func TestAccountUserRepo_IsAgentOrAdmin(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 10, Role: "administrator"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 20, Role: "agent"}).Error)
|
|
|
|
isAgentOrAdmin, err := repo.IsAgentOrAdmin(ctx, 1, 10)
|
|
require.NoError(t, err)
|
|
assert.True(t, isAgentOrAdmin)
|
|
|
|
isAgentOrAdmin, err = repo.IsAgentOrAdmin(ctx, 1, 20)
|
|
require.NoError(t, err)
|
|
assert.True(t, isAgentOrAdmin)
|
|
|
|
isAgentOrAdmin, err = repo.IsAgentOrAdmin(ctx, 1, 9999)
|
|
require.NoError(t, err)
|
|
assert.False(t, isAgentOrAdmin)
|
|
}
|
|
|
|
func TestAccountUserRepo_FindTeamMembersByAccount(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
require.NoError(t, db.Create(&model.Team{AccountID: 1, Name: "T"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 10, Role: "agent"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 20, Role: "agent"}).Error)
|
|
require.NoError(t, db.Create(&model.TeamMember{TeamID: 1, UserID: 10}).Error)
|
|
require.NoError(t, db.Create(&model.TeamMember{TeamID: 1, UserID: 20}).Error)
|
|
|
|
members, err := repo.FindTeamMembersByAccount(ctx, 1, 1)
|
|
require.NoError(t, err)
|
|
assert.Len(t, members, 2)
|
|
}
|
|
|
|
func TestAccountUserRepo_UpdateAutoOffline(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: 1, UserID: 10, Role: "agent", AutoOffline: true}).Error)
|
|
|
|
require.NoError(t, repo.UpdateAutoOffline(ctx, 1, 10, false))
|
|
|
|
au, err := repo.FindByAccountAndUser(ctx, 1, 10)
|
|
require.NoError(t, err)
|
|
assert.False(t, au.AutoOffline)
|
|
}
|
|
|
|
func TestAccountUserRepo_FindByAccountAndUserOrFail(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: 10, Role: "agent"}).Error)
|
|
|
|
au, err := repo.FindByAccountAndUserOrFail(ctx, account.ID, 10)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "agent", au.Role)
|
|
assert.NotNil(t, au.Account) // Preloaded
|
|
}
|
|
|
|
func TestAccountUserRepo_FindByAccountAndUserOrFail_NotFound(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
_, err := repo.FindByAccountAndUserOrFail(ctx, 9999, 9999)
|
|
assert.ErrorIs(t, err, gorm.ErrRecordNotFound)
|
|
}
|
|
|
|
func TestAccountUserRepo_FindByUserWithAccounts(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
account1 := &model.Account{Name: "A1"}
|
|
require.NoError(t, db.Create(account1).Error)
|
|
account2 := &model.Account{Name: "A2"}
|
|
require.NoError(t, db.Create(account2).Error)
|
|
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account1.ID, UserID: 10, Role: "agent"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account2.ID, UserID: 10, Role: "admin"}).Error)
|
|
|
|
result, err := repo.FindByUserWithAccounts(ctx, 10)
|
|
require.NoError(t, err)
|
|
assert.Len(t, result, 2)
|
|
assert.NotNil(t, result[0].Account) // Preloaded
|
|
}
|
|
|
|
func TestAccountUserRepo_Create(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
au := &model.AccountUser{AccountID: 1, UserID: 10, Role: "agent"}
|
|
err := repo.Create(ctx, au)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, au.ID)
|
|
}
|
|
|
|
func TestAccountUserRepo_Delete(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
au := &model.AccountUser{AccountID: 1, UserID: 10, Role: "agent"}
|
|
require.NoError(t, db.Create(au).Error)
|
|
|
|
require.NoError(t, repo.Delete(ctx, au.ID))
|
|
|
|
found, err := repo.FindByAccountAndUser(ctx, 1, 10)
|
|
require.NoError(t, err)
|
|
assert.Nil(t, found)
|
|
}
|
|
|
|
func TestAccountUserRepo_UpdateRole(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAccountUserRepo(db)
|
|
|
|
au := &model.AccountUser{AccountID: 1, UserID: 10, Role: "agent"}
|
|
require.NoError(t, db.Create(au).Error)
|
|
|
|
require.NoError(t, repo.UpdateRole(ctx, au.ID, "administrator"))
|
|
|
|
found, err := repo.FindByAccountAndUser(ctx, 1, 10)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "administrator", found.Role)
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// AgentRepo
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func TestAgentRepo_ListByAccount(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
user1 := &model.User{Name: "Alice", Email: "alice@e.com", Password: "p", AccountID: account.ID}
|
|
require.NoError(t, db.Create(user1).Error)
|
|
user2 := &model.User{Name: "Bob", Email: "bob@e.com", Password: "p", AccountID: account.ID}
|
|
require.NoError(t, db.Create(user2).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user1.ID, Role: "agent"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user2.ID, Role: "admin"}).Error)
|
|
|
|
agents, total, err := repo.ListByAccount(ctx, account.ID, 0, 10)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(2), total)
|
|
assert.Len(t, agents, 2)
|
|
|
|
// Test pagination
|
|
agents, total, err = repo.ListByAccount(ctx, account.ID, 1, 1)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(2), total)
|
|
assert.Len(t, agents, 1)
|
|
}
|
|
|
|
func TestAgentRepo_ListByAccount_Empty(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
agents, total, err := repo.ListByAccount(ctx, 9999, 0, 10)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(0), total)
|
|
assert.Empty(t, agents)
|
|
}
|
|
|
|
func TestAgentRepo_FindAgentByID(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
user := &model.User{Name: "Alice", Email: "alice@e.com", Password: "p", AccountID: account.ID}
|
|
require.NoError(t, db.Create(user).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user.ID, Role: "agent", Availability: "online"}).Error)
|
|
|
|
agent, err := repo.FindAgentByID(ctx, user.ID, account.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, user.Name, agent.Name)
|
|
assert.Equal(t, "agent", agent.Role)
|
|
assert.Equal(t, "online", agent.Availability)
|
|
}
|
|
|
|
func TestAgentRepo_FindAgentByID_NotFound(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
_, err := repo.FindAgentByID(ctx, 9999, 9999)
|
|
assert.ErrorIs(t, err, gorm.ErrRecordNotFound)
|
|
}
|
|
|
|
func TestAgentRepo_CreateAgent_NewUser(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
|
|
confirmedAt := time.Now()
|
|
agent, err := repo.CreateAgent(ctx, account.ID, 1, "John", "john@e.com", "agent", "online", true, 0, "hashedpw", confirmedAt)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "John", agent.Name)
|
|
assert.Equal(t, "agent", agent.Role)
|
|
assert.True(t, agent.IsNewUser)
|
|
}
|
|
|
|
func TestAgentRepo_CreateAgent_ExistingUser(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
|
|
// Create user first
|
|
user := &model.User{Name: "John", Email: "john@e.com", Password: "p", AccountID: account.ID}
|
|
require.NoError(t, db.Create(user).Error)
|
|
|
|
confirmedAt := time.Now()
|
|
agent, err := repo.CreateAgent(ctx, account.ID, 1, "John", "john@e.com", "agent", "online", true, 0, "hashedpw", confirmedAt)
|
|
require.NoError(t, err)
|
|
assert.False(t, agent.IsNewUser)
|
|
}
|
|
|
|
func TestAgentRepo_CreateAgent_AlreadyMember(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
user := &model.User{Name: "John", Email: "john@e.com", Password: "p", AccountID: account.ID}
|
|
require.NoError(t, db.Create(user).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user.ID, Role: "agent"}).Error)
|
|
|
|
confirmedAt := time.Now()
|
|
_, err := repo.CreateAgent(ctx, account.ID, 1, "John", "john@e.com", "agent", "online", true, 0, "hashedpw", confirmedAt)
|
|
assert.ErrorIs(t, err, ErrAlreadyMember)
|
|
}
|
|
|
|
func TestAgentRepo_CreateAgent_NameFromEmail(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
|
|
confirmedAt := time.Now()
|
|
agent, err := repo.CreateAgent(ctx, account.ID, 1, "", "john.doe@e.com", "agent", "online", true, 0, "hashedpw", confirmedAt)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "john.doe", agent.Name)
|
|
}
|
|
|
|
func TestAgentRepo_UpdateAgent(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
user := &model.User{Name: "John", Email: "john@e.com", Password: "p", AccountID: account.ID}
|
|
require.NoError(t, db.Create(user).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user.ID, Role: "agent", Availability: "offline"}).Error)
|
|
|
|
agent, err := repo.UpdateAgent(ctx, user.ID, account.ID, "Johnny", "admin", "online", true, true, nil, false)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Johnny", agent.Name)
|
|
assert.Equal(t, "admin", agent.Role)
|
|
assert.Equal(t, "online", agent.Availability)
|
|
assert.True(t, agent.AutoOffline)
|
|
}
|
|
|
|
func TestAgentRepo_UpdateAgent_CustomRole(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
user := &model.User{Name: "John", Email: "john@e.com", Password: "p", AccountID: account.ID}
|
|
require.NoError(t, db.Create(user).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user.ID, Role: "agent"}).Error)
|
|
|
|
roleID := uint(5)
|
|
agent, err := repo.UpdateAgent(ctx, user.ID, account.ID, "", "", "", false, false, &roleID, true)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, roleID, agent.CustomRoleID)
|
|
}
|
|
|
|
func TestAgentRepo_UpdateAgent_SetCustomRoleToZero(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
user := &model.User{Name: "John", Email: "john@e.com", Password: "p", AccountID: account.ID}
|
|
require.NoError(t, db.Create(user).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user.ID, Role: "agent", CustomRoleID: 5}).Error)
|
|
|
|
agent, err := repo.UpdateAgent(ctx, user.ID, account.ID, "", "", "", false, false, nil, true)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, uint(0), agent.CustomRoleID)
|
|
}
|
|
|
|
func TestAgentRepo_DeleteAgent(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
user := &model.User{Name: "John", Email: "john@e.com", Password: "p", AccountID: account.ID}
|
|
require.NoError(t, db.Create(user).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user.ID, Role: "agent"}).Error)
|
|
|
|
require.NoError(t, repo.DeleteAgent(ctx, user.ID, account.ID))
|
|
|
|
// AccountUser should be deleted
|
|
var count int64
|
|
db.Model(&model.AccountUser{}).Where("user_id = ? AND account_id = ?", user.ID, account.ID).Count(&count)
|
|
assert.Equal(t, int64(0), count)
|
|
|
|
// User should also be deleted (no other memberships)
|
|
var userCount int64
|
|
db.Model(&model.User{}).Where("id = ?", user.ID).Count(&userCount)
|
|
assert.Equal(t, int64(0), userCount)
|
|
}
|
|
|
|
func TestAgentRepo_DeleteAgent_NotFound(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
err := repo.DeleteAgent(ctx, 9999, 9999)
|
|
assert.ErrorIs(t, err, gorm.ErrRecordNotFound)
|
|
}
|
|
|
|
func TestAgentRepo_CountByAccount(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
ctx := context.Background()
|
|
repo := NewAgentRepo(db)
|
|
|
|
account := &model.Account{Name: "A"}
|
|
require.NoError(t, db.Create(account).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: 1, Role: "agent"}).Error)
|
|
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: 2, Role: "agent"}).Error)
|
|
|
|
count, err := repo.CountByAccount(ctx, account.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(2), count)
|
|
}
|
|
|
|
func TestIndexOfAt(t *testing.T) {
|
|
assert.Equal(t, 4, indexOfAt("test@example.com"))
|
|
assert.Equal(t, -1, indexOfAt("noemail"))
|
|
}
|