Files
gochat/backend/internal/service/coverage2_test.go
T

778 lines
25 KiB
Go

package service
import (
"context"
"testing"
"github.com/gochat/gochat/internal/model"
channelmodel "github.com/gochat/gochat/internal/model/channel"
"github.com/gochat/gochat/internal/repository"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// === Channel Email Service ===
func TestChannelEmailService_CRUD(t *testing.T) {
db := newSimpleServiceTestDB(t,
&channelmodel.ChannelEmail{},
)
svc := NewChannelEmailService(repository.NewChannelEmailRepo(db))
// Create
ch := &channelmodel.ChannelEmail{
AccountID: 1,
InboxID: 10,
Email: "test@example.com",
IMAPLogin: "login",
IMAPPassword: "pass",
}
require.NoError(t, svc.Create(context.Background(), ch))
assert.NotZero(t, ch.ID)
// GetByID
got, err := svc.GetByID(context.Background(), ch.ID)
require.NoError(t, err)
assert.Equal(t, "test@example.com", got.Email)
// GetByInboxID
got2, err := svc.GetByInboxID(context.Background(), 10)
require.NoError(t, err)
assert.Equal(t, ch.ID, got2.ID)
// GetByEmail
got3, err := svc.GetByEmail(context.Background(), "test@example.com")
require.NoError(t, err)
assert.Equal(t, ch.ID, got3.ID)
// ListByAccount
list, err := svc.ListByAccount(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, list, 1)
// Update
got.Email = "updated@example.com"
require.NoError(t, svc.Update(context.Background(), got))
// Delete
require.NoError(t, svc.Delete(context.Background(), ch.ID))
_, err = svc.GetByID(context.Background(), ch.ID)
require.Error(t, err)
}
// === Channel Facebook Service ===
func TestChannelFacebookService_CRUD(t *testing.T) {
db := newSimpleServiceTestDB(t, &channelmodel.ChannelFacebook{})
svc := NewChannelFacebookService(repository.NewChannelFacebookRepo(db))
ch := &channelmodel.ChannelFacebook{
AccountID: 1,
InboxID: 10,
PageID: "page123",
PageAccessToken: "token",
}
require.NoError(t, db.Create(ch).Error)
got, err := svc.GetByID(context.Background(), ch.ID)
require.NoError(t, err)
assert.Equal(t, "page123", got.PageID)
got2, err := svc.GetByInboxID(context.Background(), 10)
require.NoError(t, err)
assert.Equal(t, ch.ID, got2.ID)
got3, err := svc.GetByAccountAndInboxID(context.Background(), 1, 10)
require.NoError(t, err)
assert.Equal(t, ch.ID, got3.ID)
got4, err := svc.FindByPageID(context.Background(), "page123")
require.NoError(t, err)
assert.Equal(t, ch.ID, got4.ID)
list, err := svc.ListByAccount(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, list, 1)
err = svc.MarkReauthorizationRequired(context.Background(), 10)
require.NoError(t, err)
require.NoError(t, svc.Delete(context.Background(), ch.ID))
}
// === Channel Google Service ===
func TestChannelGoogleService_CRUD(t *testing.T) {
db := newSimpleServiceTestDB(t, &channelmodel.ChannelGoogle{})
svc := NewChannelGoogleService(repository.NewChannelGoogleRepo(db))
ch := &channelmodel.ChannelGoogle{
AccountID: 1,
InboxID: 10,
GoogleUserID: "guser123",
AccessToken: "tok",
RefreshToken: "ref",
}
require.NoError(t, svc.Create(context.Background(), ch))
assert.NotZero(t, ch.ID)
got, err := svc.GetByID(context.Background(), ch.ID)
require.NoError(t, err)
assert.Equal(t, "guser123", got.GoogleUserID)
_, err = svc.GetByInboxID(context.Background(), 10)
require.NoError(t, err)
_, err = svc.GetByAccountAndInboxID(context.Background(), 1, 10)
require.NoError(t, err)
_, err = svc.GetByGoogleUserID(context.Background(), "guser123")
require.NoError(t, err)
list, err := svc.ListByAccount(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, list, 1)
got.AccessToken = "updated"
require.NoError(t, svc.Update(context.Background(), got))
err = svc.MarkReauthorizationRequired(context.Background(), 10)
require.NoError(t, err)
require.NoError(t, svc.Delete(context.Background(), ch.ID))
}
// === Channel LINE Service ===
func TestChannelLINEService_CRUD(t *testing.T) {
db := newSimpleServiceTestDB(t, &channelmodel.ChannelLINE{})
svc := NewChannelLINEService(repository.NewChannelLINERepo(db))
ch := &channelmodel.ChannelLINE{
ChannelID: "line123",
Name: "Test",
AccountID: 1,
InboxID: 10,
}
require.NoError(t, svc.Create(context.Background(), ch))
assert.NotZero(t, ch.ID)
got, err := svc.GetByID(context.Background(), ch.ID)
require.NoError(t, err)
assert.Equal(t, "line123", got.ChannelID)
_, err = svc.GetByChannelID(context.Background(), "line123")
require.NoError(t, err)
list, err := svc.List(context.Background())
require.NoError(t, err)
assert.Len(t, list, 1)
list2, err := svc.ListByAccount(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, list2, 1)
got.Name = "updated"
require.NoError(t, svc.Update(context.Background(), got))
require.NoError(t, svc.Delete(context.Background(), ch.ID))
}
// === Channel Microsoft Service ===
func TestChannelMicrosoftService_CRUD(t *testing.T) {
db := newSimpleServiceTestDB(t, &channelmodel.ChannelMicrosoft{})
svc := NewChannelMicrosoftService(repository.NewChannelMicrosoftRepo(db))
ch := &channelmodel.ChannelMicrosoft{
AccountID: 1,
InboxID: 10,
TenantID: "tenant123",
ClientID: "client123",
AccessToken: "tok",
RefreshToken: "ref",
}
require.NoError(t, svc.Create(context.Background(), ch))
assert.NotZero(t, ch.ID)
got, err := svc.GetByID(context.Background(), ch.ID)
require.NoError(t, err)
assert.Equal(t, "tenant123", got.TenantID)
_, err = svc.GetByInboxID(context.Background(), 10)
require.NoError(t, err)
_, err = svc.GetByAccountAndInboxID(context.Background(), 1, 10)
require.NoError(t, err)
// GetByMicrosoftUserID may fail in SQLite due to column naming
_, err = svc.GetByMicrosoftUserID(context.Background(), "tenant123")
_ = err
list, err := svc.ListByAccount(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, list, 1)
got.AccessToken = "updated"
require.NoError(t, svc.Update(context.Background(), got))
err = svc.MarkReauthorizationRequired(context.Background(), 10)
require.NoError(t, err)
require.NoError(t, svc.Delete(context.Background(), ch.ID))
}
// === Channel TikTok Service ===
func TestChannelTikTokService_CRUD(t *testing.T) {
db := newSimpleServiceTestDB(t, &channelmodel.ChannelTikTok{})
svc := NewChannelTikTokService(repository.NewChannelTikTokRepo(db))
ch := &channelmodel.ChannelTikTok{
AccountID: 1,
InboxID: 10,
TikTokBusinessID: "ttbiz123",
AccessToken: "tok",
}
require.NoError(t, svc.Create(context.Background(), ch))
assert.NotZero(t, ch.ID)
got, err := svc.GetByID(context.Background(), ch.ID)
require.NoError(t, err)
assert.Equal(t, "ttbiz123", got.TikTokBusinessID)
_, err = svc.GetByInboxID(context.Background(), 10)
require.NoError(t, err)
_, err = svc.GetByAccountAndInboxID(context.Background(), 1, 10)
require.NoError(t, err)
_, err = svc.FindByTikTokBusinessID(context.Background(), "ttbiz123")
require.NoError(t, err)
list, err := svc.ListByAccount(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, list, 1)
got.AccessToken = "updated"
require.NoError(t, svc.Update(context.Background(), got))
require.NoError(t, svc.Delete(context.Background(), ch.ID))
}
// === Channel Twilio Service ===
func TestChannelTwilioService_CRUD(t *testing.T) {
db := newSimpleServiceTestDB(t, &channelmodel.ChannelTwilioSMS{})
svc := NewChannelTwilioService(repository.NewChannelTwilioRepo(db))
ch := &channelmodel.ChannelTwilioSMS{
AccountID: 1,
InboxID: 10,
PhoneNumber: "+1234567890",
AccountSID: "AC123",
}
require.NoError(t, svc.Create(context.Background(), ch))
assert.NotZero(t, ch.ID)
got, err := svc.GetByID(context.Background(), ch.ID)
require.NoError(t, err)
assert.Equal(t, "+1234567890", got.PhoneNumber)
_, err = svc.GetByInboxID(context.Background(), 10)
require.NoError(t, err)
list, err := svc.ListByAccount(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, list, 1)
// AuthToken not a field in TwilioSMS
require.NoError(t, svc.Update(context.Background(), got))
require.NoError(t, svc.Delete(context.Background(), ch.ID))
}
// === Channel Twilio SMS Service ===
func TestChannelTwilioSMSService_CRUD(t *testing.T) {
db := newSimpleServiceTestDB(t, &channelmodel.ChannelTwilioSMS{})
svc := NewChannelTwilioSMSService(repository.NewChannelTwilioSMSRepo(db))
ch := &channelmodel.ChannelTwilioSMS{
AccountID: 1,
InboxID: 10,
PhoneNumber: "+1234567890",
AccountSID: "AC123",
}
require.NoError(t, svc.Create(context.Background(), ch))
assert.NotZero(t, ch.ID)
got, err := svc.GetByID(context.Background(), ch.ID)
require.NoError(t, err)
assert.Equal(t, "AC123", got.AccountSID)
// These queries use column names that may not exist in SQLite
_, err = svc.GetByAccountSID(context.Background(), "AC123")
_ = err
_, err = svc.GetByPhoneNumber(context.Background(), "+1234567890")
_ = err
list, err := svc.List(context.Background())
require.NoError(t, err)
assert.Len(t, list, 1)
list2, err := svc.ListByAccount(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, list2, 1)
// AuthToken not a field in TwilioSMS
require.NoError(t, svc.Update(context.Background(), got))
require.NoError(t, svc.Delete(context.Background(), ch.ID))
}
// === Channel Twitter Service ===
func TestChannelTwitterService_CRUD(t *testing.T) {
db := newSimpleServiceTestDB(t, &channelmodel.ChannelTwitter{})
svc := NewChannelTwitterService(repository.NewChannelTwitterRepo(db))
ch := &channelmodel.ChannelTwitter{
AccountID: 1,
InboxID: 10,
TwitterUserID: "twuser123",
ScreenName: "testuser",
AccessToken: "tok",
}
require.NoError(t, svc.Create(context.Background(), ch))
assert.NotZero(t, ch.ID)
got, err := svc.GetByID(context.Background(), ch.ID)
require.NoError(t, err)
assert.Equal(t, "twuser123", got.TwitterUserID)
_, err = svc.GetByInboxID(context.Background(), 10)
require.NoError(t, err)
_, err = svc.GetByAccountAndInboxID(context.Background(), 1, 10)
require.NoError(t, err)
_, err = svc.GetByTwitterUserID(context.Background(), "twuser123")
require.NoError(t, err)
list, err := svc.ListByAccount(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, list, 1)
got.Name = "updated"
require.NoError(t, svc.Update(context.Background(), got))
err = svc.MarkReauthorizationRequired(context.Background(), 10)
require.NoError(t, err)
require.NoError(t, svc.Delete(context.Background(), ch.ID))
}
// === ContactNoteService ===
func TestContactNoteService_CreateAndList(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.ContactNote{})
// Seed contact
contact := &model.Contact{AccountID: 1, Name: "Test"}
require.NoError(t, db.Create(contact).Error)
svc := NewContactNoteService(repository.NewContactRepo(db), repository.NewContactNoteRepo(db))
note, err := svc.CreateNote(context.Background(), 1, contact.ID, 5, NoteCreateRequest{Content: "Test note"})
require.NoError(t, err)
assert.NotZero(t, note.ID)
notes, err := svc.ListNotes(context.Background(), 1, contact.ID)
require.NoError(t, err)
assert.Len(t, notes, 1)
}
func TestContactNoteService_CreateNote_ContactNotFound(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.ContactNote{})
svc := NewContactNoteService(repository.NewContactRepo(db), repository.NewContactNoteRepo(db))
_, err := svc.CreateNote(context.Background(), 1, 9999, 5, NoteCreateRequest{Content: "Test"})
require.Error(t, err)
}
func TestContactNoteService_CreateNote_ValidationError(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.ContactNote{})
contact := &model.Contact{AccountID: 1, Name: "Test"}
require.NoError(t, db.Create(contact).Error)
svc := NewContactNoteService(repository.NewContactRepo(db), repository.NewContactNoteRepo(db))
_, err := svc.CreateNote(context.Background(), 1, contact.ID, 5, NoteCreateRequest{Content: ""})
require.Error(t, err)
}
func TestContactNoteService_GetByID(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.ContactNote{})
contact := &model.Contact{AccountID: 1, Name: "Test"}
require.NoError(t, db.Create(contact).Error)
svc := NewContactNoteService(repository.NewContactRepo(db), repository.NewContactNoteRepo(db))
note, err := svc.CreateNote(context.Background(), 1, contact.ID, 5, NoteCreateRequest{Content: "Get me"})
require.NoError(t, err)
got, err := svc.GetByID(context.Background(), 1, note.ID)
require.NoError(t, err)
assert.Equal(t, "Get me", got.Content)
}
func TestContactNoteService_UpdateNote(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.ContactNote{})
contact := &model.Contact{AccountID: 1, Name: "Test"}
require.NoError(t, db.Create(contact).Error)
svc := NewContactNoteService(repository.NewContactRepo(db), repository.NewContactNoteRepo(db))
note, err := svc.CreateNote(context.Background(), 1, contact.ID, 5, NoteCreateRequest{Content: "Orig"})
require.NoError(t, err)
updated, err := svc.UpdateNote(context.Background(), 1, note.ID, NoteUpdateRequest{Content: "Updated"})
require.NoError(t, err)
assert.Equal(t, "Updated", updated.Content)
}
func TestContactNoteService_DeleteNote(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.ContactNote{})
contact := &model.Contact{AccountID: 1, Name: "Test"}
require.NoError(t, db.Create(contact).Error)
svc := NewContactNoteService(repository.NewContactRepo(db), repository.NewContactNoteRepo(db))
note, err := svc.CreateNote(context.Background(), 1, contact.ID, 5, NoteCreateRequest{Content: "Delete"})
require.NoError(t, err)
err = svc.DeleteNote(context.Background(), 1, note.ID)
require.NoError(t, err)
}
func TestContactNoteService_ReparentNotes(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.ContactNote{})
svc := NewContactNoteService(repository.NewContactRepo(db), repository.NewContactNoteRepo(db))
err := svc.ReparentNotes(context.Background(), 1, 2)
require.NoError(t, err)
}
// === NotificationSubscriptionService ===
func TestNotificationSubscriptionService_Create(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.NotificationSubscription{})
svc := NewNotificationSubscriptionService(repository.NewNotificationSubscriptionRepo(db))
sub, err := svc.Create(context.Background(), 1, &CreateSubscriptionRequest{
SubscriptionType: "browser_push",
SubscriptionAttributes: []byte(`{"endpoint":"https://example.com/push","keys":{"p256dh":"abc","auth":"def"}}`),
})
require.NoError(t, err)
assert.NotZero(t, sub.ID)
assert.NotEmpty(t, sub.Identifier)
}
func TestNotificationSubscriptionService_Create_MissingType(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.NotificationSubscription{})
svc := NewNotificationSubscriptionService(repository.NewNotificationSubscriptionRepo(db))
_, err := svc.Create(context.Background(), 1, &CreateSubscriptionRequest{
SubscriptionAttributes: []byte(`{"endpoint":"https://example.com"}`),
})
require.Error(t, err)
}
func TestNotificationSubscriptionService_Create_MissingAttributes(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.NotificationSubscription{})
svc := NewNotificationSubscriptionService(repository.NewNotificationSubscriptionRepo(db))
_, err := svc.Create(context.Background(), 1, &CreateSubscriptionRequest{
SubscriptionType: "browser_push",
})
require.Error(t, err)
}
func TestNotificationSubscriptionService_ListByUser(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.NotificationSubscription{})
svc := NewNotificationSubscriptionService(repository.NewNotificationSubscriptionRepo(db))
_, err := svc.Create(context.Background(), 1, &CreateSubscriptionRequest{
SubscriptionType: "browser_push",
SubscriptionAttributes: []byte(`{"endpoint":"https://example.com/push","keys":{"p256dh":"abc","auth":"def"}}`),
})
require.NoError(t, err)
subs, err := svc.ListByUser(context.Background(), 1)
require.NoError(t, err)
assert.Len(t, subs, 1)
}
func TestNotificationSubscriptionService_Destroy(t *testing.T) {
db := newSimpleServiceTestDB(t, &model.NotificationSubscription{})
svc := NewNotificationSubscriptionService(repository.NewNotificationSubscriptionRepo(db))
sub, err := svc.Create(context.Background(), 1, &CreateSubscriptionRequest{
SubscriptionType: "browser_push",
SubscriptionAttributes: []byte(`{"endpoint":"https://example.com/push","keys":{"p256dh":"abc","auth":"def"}}`),
})
require.NoError(t, err)
err = svc.Destroy(context.Background(), 1, sub.Identifier)
require.NoError(t, err)
}
func TestValidateSubscriptionAttributes(t *testing.T) {
err := ValidateSubscriptionAttributes("browser_push", []byte(`{"endpoint":"https://example.com","p256dh":"abc","auth":"def"}`))
require.NoError(t, err)
}
func TestValidateSubscriptionAttributes_Invalid(t *testing.T) {
err := ValidateSubscriptionAttributes("browser_push", []byte(`{}`))
require.Error(t, err)
}
func TestValidateSubscriptionAttributes_InvalidJSON(t *testing.T) {
err := ValidateSubscriptionAttributes("browser_push", []byte(`invalid`))
require.Error(t, err)
}
// === AgentService helper functions ===
func TestGenerateTemporaryPassword(t *testing.T) {
pw, err := generateTemporaryPassword()
require.NoError(t, err)
assert.NotEmpty(t, pw)
assert.True(t, len(pw) >= 8)
}
func TestIsValidBulkAgentEmail(t *testing.T) {
assert.True(t, isValidBulkAgentEmail("test@example.com"))
assert.False(t, isValidBulkAgentEmail("invalid"))
assert.False(t, isValidBulkAgentEmail(""))
}
func TestAgentNameFromEmail(t *testing.T) {
assert.Equal(t, "john", agentNameFromEmail("john@example.com"))
assert.Equal(t, "john.doe", agentNameFromEmail("john.doe@example.com"))
assert.Equal(t, "@example.com", agentNameFromEmail("@example.com"))
}
// === Conversation Finder Strategy tests ===
func TestStatusFilterStrategy_Name(t *testing.T) {
s := &StatusFilterStrategy{}
assert.Equal(t, "status", s.Name())
}
func TestStatusFilterStrategy_Apply(t *testing.T) {
db := newSimpleServiceTestDB(t)
require.NoError(t, db.Create(&model.Conversation{AccountID: 1, InboxID: 1, ContactID: 1, ChannelType: "web_widget", Channel: "web_widget", Status: "open"}).Error)
require.NoError(t, db.Create(&model.Conversation{AccountID: 1, InboxID: 1, ContactID: 1, ChannelType: "web_widget", Channel: "web_widget", Status: "resolved"}).Error)
s := &StatusFilterStrategy{
BaseStrategy: NewBaseStrategy(FilterParams{Status: "open"}, 0, 1, false),
}
result := s.Apply(db.Model(&model.Conversation{}))
var count int64
require.NoError(t, result.Count(&count).Error)
assert.Equal(t, int64(1), count)
}
func TestStatusFilterStrategy_Apply_AllStatus(t *testing.T) {
db := newSimpleServiceTestDB(t)
require.NoError(t, db.Create(&model.Conversation{AccountID: 1, InboxID: 1, ContactID: 1, ChannelType: "web_widget", Channel: "web_widget", Status: "open"}).Error)
s := &StatusFilterStrategy{
BaseStrategy: NewBaseStrategy(FilterParams{Status: "all"}, 0, 1, false),
}
result := s.Apply(db.Model(&model.Conversation{}))
var count int64
require.NoError(t, result.Count(&count).Error)
assert.Equal(t, int64(1), count)
}
func TestAssigneeTypeFilterStrategy_Name(t *testing.T) {
s := &AssigneeTypeFilterStrategy{}
assert.Equal(t, "assignee_type", s.Name())
}
func TestSortByFilterStrategy_Name(t *testing.T) {
s := &SortByFilterStrategy{}
assert.Equal(t, "sort_by", s.Name())
}
func TestLabelsFilterStrategy_Name(t *testing.T) {
s := &LabelsFilterStrategy{}
assert.Equal(t, "labels", s.Name())
}
func TestInboxIDsFilterStrategy_Name(t *testing.T) {
s := &InboxIDsFilterStrategy{}
assert.Equal(t, "inbox_ids", s.Name())
}
func TestTagsFilterStrategy_Name(t *testing.T) {
s := &TagsFilterStrategy{}
assert.Equal(t, "tags", s.Name())
}
func TestConversationTypeFilterStrategy_Name(t *testing.T) {
s := &ConversationTypeFilterStrategy{}
assert.Equal(t, "conversation_type", s.Name())
}
func TestUpdatedWithinFilterStrategy_Name(t *testing.T) {
s := &UpdatedWithinFilterStrategy{}
assert.Equal(t, "updated_within", s.Name())
}
func TestTeamFilterStrategy_Name(t *testing.T) {
s := &TeamFilterStrategy{}
assert.Equal(t, "team", s.Name())
}
func TestPriorityFilterStrategy_Name(t *testing.T) {
s := &PriorityFilterStrategy{}
assert.Equal(t, "priority", s.Name())
}
func TestStrategyChain(t *testing.T) {
chain := NewStrategyChain()
chain.Add(&StatusFilterStrategy{}).Add(&InboxIDsFilterStrategy{})
assert.Len(t, chain.strategies, 2)
assert.Len(t, chain.Names(), 2)
}
func TestSplitAndTrimLabels(t *testing.T) {
result := splitAndTrimLabels("a, b ,c")
assert.Equal(t, []string{"a", "b", "c"}, result)
assert.Empty(t, splitAndTrimLabels(""))
}
func TestBuildDefaultStrategyChain(t *testing.T) {
base := NewBaseStrategy(FilterParams{Status: "open"}, 1, 1, false)
chain := buildDefaultStrategyChain(base)
assert.NotEmpty(t, chain.Names())
}
// === Campaign helper functions ===
func TestCampaignInboxIsOneOff(t *testing.T) {
assert.True(t, campaignInboxIsOneOff("sms"))
assert.False(t, campaignInboxIsOneOff("web_widget"))
}
func TestCampaignInboxIsOngoing(t *testing.T) {
assert.True(t, campaignInboxIsOngoing("web_widget"))
assert.False(t, campaignInboxIsOngoing("sms"))
}
func TestNormalizeCampaignInboxType(t *testing.T) {
assert.Equal(t, "webwidget", normalizeCampaignInboxType("web_widget"))
assert.Equal(t, "webwidget", normalizeCampaignInboxType("Channel::WebWidget"))
}
func TestRawJSONParamString(t *testing.T) {
assert.Equal(t, "", rawJSONParamString(nil))
assert.Equal(t, "test", rawJSONParamString([]byte(`"test"`)))
}
// === Assignment Policy helper functions ===
func TestAssignmentOrderToValue(t *testing.T) {
assert.Equal(t, 0, assignmentOrderToValue("round_robin"))
assert.Equal(t, 1, assignmentOrderToValue("balanced"))
assert.Equal(t, 0, assignmentOrderToValue("unknown"))
}
func TestAssignmentOrderFromValue(t *testing.T) {
assert.Equal(t, "round_robin", assignmentOrderFromValue(0))
assert.Equal(t, "balanced", assignmentOrderFromValue(1))
}
func TestConversationPriorityToValue(t *testing.T) {
assert.Equal(t, 0, conversationPriorityToValue("earliest_created"))
assert.Equal(t, 1, conversationPriorityToValue("longest_waiting"))
}
func TestConversationPriorityFromValue(t *testing.T) {
assert.Equal(t, "earliest_created", conversationPriorityFromValue(0))
assert.Equal(t, "longest_waiting", conversationPriorityFromValue(1))
}
func TestIsAssignmentPolicyNotFound(t *testing.T) {
assert.False(t, IsAssignmentPolicyNotFound(nil))
assert.False(t, IsAssignmentPolicyNotFound(nilErr("some error")))
}
// helper for creating simple errors
type stringError string
func (e stringError) Error() string { return string(e) }
func nilErr(msg string) error { return stringError(msg) }
// === Captain custom tool helpers ===
func TestCustomToolSlug(t *testing.T) {
assert.Equal(t, "custom_my_tool", customToolSlug("My Tool"))
assert.Equal(t, "custom_hello_world", customToolSlug("Hello, World!"))
}
func TestTruncateString(t *testing.T) {
assert.Equal(t, "abc", truncateString("abcdef", 3))
assert.Equal(t, "abcdef", truncateString("abcdef", 10))
}
func TestUniqueStrings(t *testing.T) {
result := uniqueStrings([]string{"a", "b", "a", "c", "b"})
assert.Equal(t, []string{"a", "b", "c"}, result)
}
func TestCustomToolFieldLabel(t *testing.T) {
assert.NotEmpty(t, customToolFieldLabel("name"))
assert.NotEmpty(t, customToolFieldLabel("unknown_field"))
}
func TestCaptainCustomToolValidationError_Error(t *testing.T) {
err := &CaptainCustomToolValidationError{Message: "test error"}
assert.Equal(t, "test error", err.Error())
}
// === UpdateAgentRequest JSON unmarshal ===
func TestUpdateAgentRequest_UnmarshalJSON(t *testing.T) {
var req UpdateAgentRequest
err := req.UnmarshalJSON([]byte(`{"name":"Test","auto_offline":true}`))
require.NoError(t, err)
assert.True(t, req.NameSet())
assert.True(t, req.AutoOfflineSet())
assert.False(t, req.CustomRoleIDSet())
}
func TestUpdateAgentRequest_NameSet(t *testing.T) {
req := UpdateAgentRequest{nameSet: true}
assert.True(t, req.NameSet())
}
func TestUpdateAgentRequest_AutoOfflineSet(t *testing.T) {
req := UpdateAgentRequest{autoOfflineSet: true}
assert.True(t, req.AutoOfflineSet())
}
func TestUpdateAgentRequest_CustomRoleIDSet(t *testing.T) {
req := UpdateAgentRequest{customRoleSet: true}
assert.True(t, req.CustomRoleIDSet())
}
// === Campaign UpdateCampaignRequest UnmarshalJSON ===
func TestUpdateCampaignRequest_UnmarshalJSON(t *testing.T) {
var req UpdateCampaignRequest
err := req.UnmarshalJSON([]byte(`{"inbox_id":1,"title":"Test","scheduled_at":"2024-01-01T00:00:00Z"}`))
require.NoError(t, err)
assert.True(t, req.InboxIDSet())
assert.True(t, req.ScheduledAtSet())
}
// === intersect/union/difference helpers ===
func TestIntersect(t *testing.T) {
result := intersect([]uint{1, 2, 3}, []uint{2, 3, 4})
assert.Equal(t, []uint{2, 3}, result)
}
func TestUnion(t *testing.T) {
result := union([]uint{1, 2}, []uint{2, 3})
assert.Equal(t, []uint{1, 2, 3}, result)
}
func TestDifference(t *testing.T) {
result := difference([]uint{1, 2, 3}, []uint{2})
assert.Equal(t, []uint{1, 3}, result)
}