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

309 lines
9.6 KiB
Go

package repository
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
"github.com/gochat/gochat/internal/model"
)
// --- Helpers for CustomAttributeDefinition repo tests ---
func setupCustomAttrDefTestDB(t *testing.T) *gorm.DB {
t.Helper()
return setupTestDB(t, &model.CustomAttributeDefinition{})
}
func createCustomAttrDefTestAccount(t *testing.T, db *gorm.DB) *model.Account {
t.Helper()
account := &model.Account{Name: "Custom Attr Def Test Account"}
err := db.Create(account).Error
require.NoError(t, err, "failed to create test account")
return account
}
// ===========================================================================
// Create tests
// ===========================================================================
func TestCustomAttributeDefinitionRepo_Create(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
account := createCustomAttrDefTestAccount(t, db)
def := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: "priority",
AttributeDisplayName: "Priority",
AttributeType: "text",
AttributeModel: "conversation",
Description: "Conversation priority level",
}
err := repo.Create(ctx, def)
require.NoError(t, err)
assert.NotZero(t, def.ID)
assert.Equal(t, account.ID, def.AccountID)
assert.Equal(t, "priority", def.AttributeName)
assert.Equal(t, "text", def.AttributeType)
assert.Equal(t, "conversation", def.AttributeModel)
}
func TestCustomAttributeDefinitionRepo_Create_DuplicateAttributeName(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
account := createCustomAttrDefTestAccount(t, db)
def1 := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: "priority",
AttributeDisplayName: "Priority",
AttributeType: "text",
AttributeModel: "conversation",
}
require.NoError(t, repo.Create(ctx, def1))
// Same attribute_name + same account + same model should fail (unique index)
def2 := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: "priority",
AttributeDisplayName: "Priority Level",
AttributeType: "number",
AttributeModel: "conversation",
}
err := repo.Create(ctx, def2)
assert.Error(t, err, "duplicate attribute_name within same account+model should fail")
}
// ===========================================================================
// GetByID tests
// ===========================================================================
func TestCustomAttributeDefinitionRepo_GetByID(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
account := createCustomAttrDefTestAccount(t, db)
def := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: "status",
AttributeDisplayName: "Status",
AttributeType: "list",
AttributeModel: "contact",
}
require.NoError(t, repo.Create(ctx, def))
found, err := repo.GetByID(ctx, def.ID)
require.NoError(t, err)
assert.Equal(t, def.ID, found.ID)
assert.Equal(t, "status", found.AttributeName)
assert.Equal(t, "list", found.AttributeType)
}
func TestCustomAttributeDefinitionRepo_GetByID_NotFound(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
_, err := repo.GetByID(ctx, 9999)
assert.ErrorIs(t, err, gorm.ErrRecordNotFound)
}
// ===========================================================================
// FindByAccount tests
// ===========================================================================
func TestCustomAttributeDefinitionRepo_FindByAccount(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
account := createCustomAttrDefTestAccount(t, db)
// Create multiple definitions for the same account
for i, name := range []string{"attr_a", "attr_b", "attr_c"} {
def := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: name,
AttributeDisplayName: "Attr " + name,
AttributeType: "text",
AttributeModel: "conversation",
Description: "Test desc " + string(rune('A'+i)),
}
require.NoError(t, repo.Create(ctx, def))
}
defs, total, err := repo.FindByAccount(ctx, account.ID, 0, 10)
require.NoError(t, err)
assert.Equal(t, int64(3), total)
assert.Len(t, defs, 3)
}
func TestCustomAttributeDefinitionRepo_FindByAccount_Pagination(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
account := createCustomAttrDefTestAccount(t, db)
for i := 0; i < 5; i++ {
def := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: "paged_attr_" + string(rune('A'+i)),
AttributeDisplayName: "Paged Attr",
AttributeType: "text",
AttributeModel: "conversation",
}
require.NoError(t, repo.Create(ctx, def))
}
defs, total, err := repo.FindByAccount(ctx, account.ID, 0, 2)
require.NoError(t, err)
assert.Equal(t, int64(5), total)
assert.Len(t, defs, 2)
defs2, total2, err := repo.FindByAccount(ctx, account.ID, 2, 2)
require.NoError(t, err)
assert.Equal(t, int64(5), total2)
assert.Len(t, defs2, 2)
}
func TestCustomAttributeDefinitionRepo_FindByAccount_EmptyAccount(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
defs, total, err := repo.FindByAccount(ctx, 9999, 0, 10)
require.NoError(t, err)
assert.Equal(t, int64(0), total)
assert.Len(t, defs, 0)
}
// ===========================================================================
// FindByAccountAndModel tests
// ===========================================================================
func TestCustomAttributeDefinitionRepo_FindByAccountAndModel(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
account := createCustomAttrDefTestAccount(t, db)
// Create conversation attributes
for _, name := range []string{"conv_priority", "conv_status"} {
def := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: name,
AttributeDisplayName: name,
AttributeType: "text",
AttributeModel: "conversation",
}
require.NoError(t, repo.Create(ctx, def))
}
// Create contact attributes
for _, name := range []string{"contact_level", "contact_source"} {
def := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: name,
AttributeDisplayName: name,
AttributeType: "text",
AttributeModel: "contact",
}
require.NoError(t, repo.Create(ctx, def))
}
convDefs, convTotal, err := repo.FindByAccountAndModel(ctx, account.ID, "conversation", 0, 10)
require.NoError(t, err)
assert.Equal(t, int64(2), convTotal)
assert.Len(t, convDefs, 2)
contactDefs, contactTotal, err := repo.FindByAccountAndModel(ctx, account.ID, "contact", 0, 10)
require.NoError(t, err)
assert.Equal(t, int64(2), contactTotal)
assert.Len(t, contactDefs, 2)
}
// ===========================================================================
// Update tests
// ===========================================================================
func TestCustomAttributeDefinitionRepo_Update(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
account := createCustomAttrDefTestAccount(t, db)
def := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: "priority",
AttributeDisplayName: "Priority",
AttributeType: "text",
AttributeModel: "conversation",
}
require.NoError(t, repo.Create(ctx, def))
def.AttributeDisplayName = "Priority Level"
def.Description = "Updated description"
err := repo.Update(ctx, def)
require.NoError(t, err)
found, err := repo.GetByID(ctx, def.ID)
require.NoError(t, err)
assert.Equal(t, "Priority Level", found.AttributeDisplayName)
assert.Equal(t, "Updated description", found.Description)
}
// ===========================================================================
// Delete tests (soft delete)
// ===========================================================================
func TestCustomAttributeDefinitionRepo_Delete(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
account := createCustomAttrDefTestAccount(t, db)
def := &model.CustomAttributeDefinition{
AccountID: account.ID,
AttributeName: "temp_attr",
AttributeDisplayName: "Temp",
AttributeType: "text",
AttributeModel: "conversation",
}
require.NoError(t, repo.Create(ctx, def))
err := repo.Delete(ctx, def.ID)
require.NoError(t, err)
// Should not be findable via GetByID (soft delete filters it)
_, err = repo.GetByID(ctx, def.ID)
assert.ErrorIs(t, err, gorm.ErrRecordNotFound)
}
func TestCustomAttributeDefinitionRepo_Delete_NotFound(t *testing.T) {
db := setupCustomAttrDefTestDB(t)
ctx := context.Background()
repo := NewCustomAttributeDefinitionRepo(db)
// Deleting a non-existent record should still succeed (GORM soft delete on zero rows)
err := repo.Delete(ctx, 9999)
// GORM Delete with a specific ID that doesn't exist may or may not error depending on version
// In practice, GORM won't return an error even if the record doesn't exist for soft delete
assert.NoError(t, err)
}