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

645 lines
22 KiB
Go

package repository
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/datatypes"
"gorm.io/gorm"
"github.com/gochat/gochat/internal/model"
)
func createTestConversation(t *testing.T, db *gorm.DB, accountID, inboxID, contactID uint, status string) *model.Conversation {
t.Helper()
conv := &model.Conversation{
AccountID: accountID,
InboxID: inboxID,
ContactID: contactID,
Status: status,
ChannelType: "web_widget",
Channel: "web_widget",
}
require.NoError(t, db.Create(conv).Error)
return conv
}
func TestConversationRepo_FindByID(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvTestOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvTestInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvTestContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
found, err := repo.FindByID(context.Background(), conv.ID)
assert.NoError(t, err)
assert.Equal(t, conv.ID, found.ID)
assert.Equal(t, "open", found.Status)
assert.Equal(t, account.ID, found.AccountID)
}
func TestConversationRepo_FindByID_NotFound(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
found, err := repo.FindByID(context.Background(), 9999)
assert.Error(t, err)
assert.Nil(t, found)
}
func TestConversationRepo_FindByAccountAndID(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvAcctOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvAcctInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvAcctContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
found, err := repo.FindByAccountAndID(context.Background(), account.ID, conv.ID)
assert.NoError(t, err)
assert.Equal(t, conv.ID, found.ID)
}
func TestConversationRepo_FindByAccountAndID_WrongAccount(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvAcctOrg2", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvAcctInbox2", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvAcctContact2"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
// Different account should not find the conversation
found, err := repo.FindByAccountAndID(context.Background(), 9999, conv.ID)
assert.Error(t, err)
assert.Nil(t, found)
}
func TestConversationRepo_FindByAccount(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvListOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvListInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvListContact"}
require.NoError(t, db.Create(contact).Error)
for i := 0; i < 5; i++ {
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
}
conversations, total, err := repo.FindByAccount(context.Background(), account.ID, 0, 10)
assert.NoError(t, err)
assert.Equal(t, int64(5), total)
assert.Len(t, conversations, 5)
}
func TestConversationRepo_FindByAccount_Empty(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
conversations, total, err := repo.FindByAccount(context.Background(), 1, 0, 10)
assert.NoError(t, err)
assert.Equal(t, int64(0), total)
assert.Len(t, conversations, 0)
}
func TestConversationRepo_FindByStatus(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvStatusOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvStatusInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvStatusContact"}
require.NoError(t, db.Create(contact).Error)
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "resolved")
conversations, total, err := repo.FindByStatus(context.Background(), account.ID, "open", 0, 10)
assert.NoError(t, err)
assert.Equal(t, int64(2), total)
assert.Len(t, conversations, 2)
resolved, total, err := repo.FindByStatus(context.Background(), account.ID, "resolved", 0, 10)
assert.NoError(t, err)
assert.Equal(t, int64(1), total)
assert.Len(t, resolved, 1)
}
func TestConversationRepo_FindByInbox(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvInboxOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvInbox1", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
inbox2 := &model.Inbox{AccountID: account.ID, Name: "ConvInbox2", ChannelType: "web_widget", ChannelID: 2}
require.NoError(t, db.Create(inbox2).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvInboxContact"}
require.NoError(t, db.Create(contact).Error)
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
createTestConversation(t, db, account.ID, inbox2.ID, contact.ID, "open")
conversations, total, err := repo.FindByInbox(context.Background(), account.ID, inbox.ID, 0, 10)
assert.NoError(t, err)
assert.Equal(t, int64(2), total)
assert.Len(t, conversations, 2)
}
func TestConversationRepo_FindByAssignee(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvAssignOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvAssignInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvAssignContact"}
require.NoError(t, db.Create(contact).Error)
assigneeID := uint(100)
conv1 := &model.Conversation{
AccountID: account.ID,
InboxID: inbox.ID,
ContactID: contact.ID,
AssigneeID: &assigneeID,
Status: "open",
ChannelType: "web_widget",
Channel: "web_widget",
}
require.NoError(t, db.Create(conv1).Error)
conv2 := &model.Conversation{
AccountID: account.ID,
InboxID: inbox.ID,
ContactID: contact.ID,
Status: "open",
ChannelType: "web_widget",
Channel: "web_widget",
}
require.NoError(t, db.Create(conv2).Error)
conversations, total, err := repo.FindByAssignee(context.Background(), account.ID, assigneeID, 0, 10)
assert.NoError(t, err)
assert.Equal(t, int64(1), total)
assert.Len(t, conversations, 1)
}
func TestConversationRepo_FindUnassigned(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvUnassignedOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvUnassignedInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvUnassignedContact"}
require.NoError(t, db.Create(contact).Error)
assigneeID := uint(100)
// One assigned
conv1 := &model.Conversation{
AccountID: account.ID,
InboxID: inbox.ID,
ContactID: contact.ID,
AssigneeID: &assigneeID,
Status: "open",
ChannelType: "web_widget",
Channel: "web_widget",
}
require.NoError(t, db.Create(conv1).Error)
// One unassigned
conv2 := &model.Conversation{
AccountID: account.ID,
InboxID: inbox.ID,
ContactID: contact.ID,
Status: "open",
ChannelType: "web_widget",
Channel: "web_widget",
}
require.NoError(t, db.Create(conv2).Error)
conversations, total, err := repo.FindUnassigned(context.Background(), account.ID, 0, 10)
assert.NoError(t, err)
assert.Equal(t, int64(1), total)
assert.Len(t, conversations, 1)
}
func TestConversationRepo_Create(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvCreateOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
conv := &model.Conversation{
AccountID: account.ID,
InboxID: 1,
ContactID: 1,
Status: "open",
ChannelType: "web_widget",
Channel: "web_widget",
}
err := repo.Create(context.Background(), conv)
assert.NoError(t, err)
assert.NotZero(t, conv.ID)
}
func TestConversationRepo_Update(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvUpdateOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvUpdateInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvUpdateContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
conv.Status = "resolved"
err := repo.Update(context.Background(), conv)
assert.NoError(t, err)
found, err := repo.FindByID(context.Background(), conv.ID)
assert.NoError(t, err)
assert.Equal(t, "resolved", found.Status)
}
func TestConversationRepo_UpdateStatus(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvStatusUpdateOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvStatusUpdInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvStatusUpdContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
err := repo.UpdateStatus(context.Background(), conv.ID, model.ConversationStatusResolved)
assert.NoError(t, err)
found, err := repo.FindByID(context.Background(), conv.ID)
assert.NoError(t, err)
assert.Equal(t, string(model.ConversationStatusResolved), found.Status)
}
func TestConversationRepo_AssignAgent(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvAssignAgentOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvAssignAgentInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvAssignAgentContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
agentID := uint(42)
err := repo.AssignAgent(context.Background(), conv.ID, agentID)
assert.NoError(t, err)
found, err := repo.FindByID(context.Background(), conv.ID)
assert.NoError(t, err)
assert.Equal(t, agentID, *found.AssigneeID)
}
func TestConversationRepo_UpdateLabels(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvLabelsOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvLabelsInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvLabelsContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
err := repo.UpdateLabels(context.Background(), conv.ID, "bug,urgent")
assert.NoError(t, err)
found, err := repo.FindByID(context.Background(), conv.ID)
assert.NoError(t, err)
assert.Equal(t, "bug,urgent", found.Labels)
}
func TestConversationRepo_Delete(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvDeleteOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvDeleteInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvDeleteContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
err := repo.Delete(context.Background(), conv.ID)
assert.NoError(t, err)
found, err := repo.FindByID(context.Background(), conv.ID)
assert.Error(t, err)
assert.Nil(t, found)
}
func TestConversationRepo_CountByAccount(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "ConvCountOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "ConvCountInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "ConvCountContact"}
require.NoError(t, db.Create(contact).Error)
for i := 0; i < 5; i++ {
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
}
total, err := repo.CountByAccount(context.Background(), account.ID)
assert.NoError(t, err)
assert.Equal(t, int64(5), total)
}
// ========== GetMeta Tests ==========
func TestConversationRepo_GetMeta(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "MetaTestOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "MetaTestInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "MetaTestContact"}
require.NoError(t, db.Create(contact).Error)
// Create conversations with different statuses and labels
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
conv2 := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "resolved")
// Update labels on conv2
require.NoError(t, db.Model(conv2).Update("labels", "bug,critical").Error)
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "pending")
conv4 := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
require.NoError(t, db.Model(conv4).Update("labels", "bug,feature").Error)
meta, err := repo.GetMeta(context.Background(), account.ID)
assert.NoError(t, err)
assert.Equal(t, int64(4), meta.TotalCount)
assert.Equal(t, int64(2), meta.StatusCounts["open"])
assert.Equal(t, int64(1), meta.StatusCounts["resolved"])
assert.Equal(t, int64(1), meta.StatusCounts["pending"])
assert.Equal(t, int64(2), meta.LabelCounts["bug"])
assert.Equal(t, int64(1), meta.LabelCounts["critical"])
assert.Equal(t, int64(1), meta.LabelCounts["feature"])
}
func TestConversationRepo_GetMeta_EmptyAccount(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "MetaEmptyOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
meta, err := repo.GetMeta(context.Background(), account.ID)
assert.NoError(t, err)
assert.Equal(t, int64(0), meta.TotalCount)
assert.Empty(t, meta.StatusCounts)
assert.Empty(t, meta.LabelCounts)
}
func TestConversationRepo_GetMeta_WrongAccount(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "MetaWrongOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "MetaWrongInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "MetaWrongContact"}
require.NoError(t, db.Create(contact).Error)
createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
// Query a non-existent account ID — should return empty meta
meta, err := repo.GetMeta(context.Background(), 9999)
assert.NoError(t, err)
assert.Equal(t, int64(0), meta.TotalCount)
assert.Empty(t, meta.StatusCounts)
}
// ========== MarkUnread Tests ==========
func TestConversationRepo_MarkUnread(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "UnreadTestOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "UnreadTestInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "UnreadTestContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
// Set agent_last_seen_at to a non-nil value
seenAt := int64(1700000000)
require.NoError(t, db.Model(conv).Update("agent_last_seen_at", seenAt).Error)
// Mark unread — resets agent_last_seen_at to nil
err := repo.MarkUnread(context.Background(), conv.ID)
assert.NoError(t, err)
// Verify agent_last_seen_at was cleared
updated, err := repo.FindByID(context.Background(), conv.ID)
assert.NoError(t, err)
assert.Nil(t, updated.AgentLastSeenAt)
}
func TestConversationRepo_MarkUnread_NotFound(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
// MarkUnread on non-existent ID — GORM Update with WHERE id=? that doesn't match
// returns no error (0 rows affected is not an error in GORM)
err := repo.MarkUnread(context.Background(), 9999)
assert.NoError(t, err) // GORM doesn't error on 0 rows affected
}
// ========== UpdateAgentLastSeenAt Tests ==========
func TestConversationRepo_UpdateAgentLastSeenAt(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "UpdateSeenAtOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "UpdateSeenAtInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "UpdateSeenAtContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
seenAt := int64(1700000100)
err := repo.UpdateAgentLastSeenAt(context.Background(), conv.ID, time.Unix(seenAt, 0))
assert.NoError(t, err)
updated, err := repo.FindByID(context.Background(), conv.ID)
assert.NoError(t, err)
assert.NotNil(t, updated.AgentLastSeenAt)
assert.Equal(t, seenAt, *updated.AgentLastSeenAt)
}
func TestConversationRepo_UpdateAgentLastSeenAt_NotFound(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
err := repo.UpdateAgentLastSeenAt(context.Background(), 9999, time.Unix(1700000100, 0))
assert.NoError(t, err) // GORM doesn't error on 0 rows affected
}
// ========== UpdateCustomAttributes Tests ==========
func TestConversationRepo_UpdateCustomAttributes(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "CustomAttributesTestOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "CustomAttributesTestInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "CustomAttributesTestContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
attrs := datatypes.JSON(`{"priority_reason": "vip_customer", "region": "us-west"}`)
err := repo.UpdateCustomAttributes(context.Background(), conv.ID, attrs)
assert.NoError(t, err)
// Verify attributes were updated
updated, err := repo.FindByID(context.Background(), conv.ID)
assert.NoError(t, err)
assert.NotNil(t, updated.CustomAttributes)
}
func TestConversationRepo_UpdateCustomAttributes_NotFound(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
attrs := datatypes.JSON(`{"key": "value"}`)
// UpdateCustomAttributes on non-existent ID — GORM returns no error for 0 rows affected
err := repo.UpdateCustomAttributes(context.Background(), 9999, attrs)
assert.NoError(t, err) // GORM doesn't error on 0 rows affected
}
func TestConversationRepo_UpdateCustomAttributes_EmptyJSON(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "CustomAttributesEmptyOrg", Locale: "en", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "CustomAttributesEmptyInbox", ChannelType: "web_widget", ChannelID: 1}
require.NoError(t, db.Create(inbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "CustomAttributesEmptyContact"}
require.NoError(t, db.Create(contact).Error)
conv := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
// First set some attributes
initialAttrs := datatypes.JSON(`{"foo": "bar"}`)
require.NoError(t, repo.UpdateCustomAttributes(context.Background(), conv.ID, initialAttrs))
// Now update to empty object
emptyAttrs := datatypes.JSON(`{}`)
err := repo.UpdateCustomAttributes(context.Background(), conv.ID, emptyAttrs)
assert.NoError(t, err)
// Verify attributes were cleared to empty object
updated, err := repo.FindByID(context.Background(), conv.ID)
assert.NoError(t, err)
assert.NotNil(t, updated.CustomAttributes)
}