Files
gochat/internal/service/dyte_integration_service_test.go
T

128 lines
6.2 KiB
Go

package service
import (
"context"
"encoding/json"
"net/http"
"testing"
"github.com/stretchr/testify/require"
"gorm.io/datatypes"
"gorm.io/gorm"
"github.com/gochat/gochat/internal/model"
"github.com/gochat/gochat/internal/repository"
)
type fakeDyteBackend struct {
createPayload map[string]any
createError *DyteAPIError
joinPayload map[string]any
joinError *DyteAPIError
lastTitle string
lastMeetingID string
}
func (f *fakeDyteBackend) CreateMeeting(_ context.Context, _ DyteCredentials, title string) (map[string]any, *DyteAPIError, error) {
f.lastTitle = title
return f.createPayload, f.createError, nil
}
func (f *fakeDyteBackend) AddParticipant(_ context.Context, _ DyteCredentials, meetingID string, _ DyteParticipant) (map[string]any, *DyteAPIError, error) {
f.lastMeetingID = meetingID
return f.joinPayload, f.joinError, nil
}
func TestDyteIntegrationServiceCreateMeetingCreatesIntegrationMessage(t *testing.T) {
db := setupServiceTestDB(t)
require.NoError(t, db.AutoMigrate(&model.IntegrationHook{}))
account := createTestAccount(t, db)
user := createTestUser(t, db, account.ID)
user.Name = "Ada Agent"
require.NoError(t, db.Save(user).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "Website", ChannelType: "web_widget", Enabled: true}
require.NoError(t, db.Create(inbox).Error)
require.NoError(t, db.Create(&model.InboxMember{InboxID: inbox.ID, UserID: user.ID, Role: "agent"}).Error)
contact := &model.Contact{AccountID: account.ID, Name: "Visitor"}
require.NoError(t, db.Create(contact).Error)
displayID := uint(42)
conversation := &model.Conversation{AccountID: account.ID, InboxID: inbox.ID, ContactID: contact.ID, DisplayID: &displayID, Status: "pending", ChannelType: "web_widget", Channel: "web_widget"}
require.NoError(t, db.Create(conversation).Error)
settings, _ := json.Marshal(map[string]any{"organization_id": "org", "api_key": "key"})
require.NoError(t, db.Create(&model.IntegrationHook{AccountID: account.ID, AppID: "dyte", HookType: model.HookType("dyte"), Settings: datatypes.JSON(settings)}).Error)
backend := &fakeDyteBackend{createPayload: map[string]any{"id": "meeting_id"}}
svc := NewDyteIntegrationService(repository.NewIntegrationHookRepo(db), repository.NewMessageRepo(db))
svc.SetBackend(backend)
message, resolvedConversation, apiErr, err := svc.CreateMeeting(context.Background(), account.ID, user.ID, displayID, "agent")
require.NoError(t, err)
require.Nil(t, apiErr)
require.Equal(t, conversation.ID, resolvedConversation.ID)
require.Equal(t, "Ada Agent has started a meeting", backend.lastTitle)
require.Equal(t, "integrations", message.ContentType)
require.Equal(t, "outgoing", message.MessageType)
require.Equal(t, "Ada Agent has started a meeting", message.Content)
require.Equal(t, user.ID, *message.SenderID)
require.Equal(t, "meeting_id", dyteMeetingID(message.ContentAttributes))
}
func TestDyteIntegrationServiceCreateMeetingPropagatesDyteErrors(t *testing.T) {
db, account, user, displayID := setupDyteServiceFixture(t)
backend := &fakeDyteBackend{createError: &DyteAPIError{Payload: map[string]any{"success": false, "data": map[string]any{"message": "Title is required"}}, Status: http.StatusUnprocessableEntity}}
svc := NewDyteIntegrationService(repository.NewIntegrationHookRepo(db), repository.NewMessageRepo(db))
svc.SetBackend(backend)
message, _, apiErr, err := svc.CreateMeeting(context.Background(), account.ID, user.ID, displayID, "agent")
require.NoError(t, err)
require.Nil(t, message)
require.NotNil(t, apiErr)
require.Equal(t, http.StatusUnprocessableEntity, apiErr.Status)
var count int64
require.NoError(t, db.Model(&model.Message{}).Count(&count).Error)
require.Zero(t, count)
}
func TestDyteIntegrationServiceAddParticipant(t *testing.T) {
db, account, user, _ := setupDyteServiceFixture(t)
message := createDyteIntegrationMessage(t, db, account.ID, user.ID)
backend := &fakeDyteBackend{joinPayload: map[string]any{"id": "participant", "auth_token": "jwt"}}
svc := NewDyteIntegrationService(repository.NewIntegrationHookRepo(db), repository.NewMessageRepo(db))
svc.SetBackend(backend)
payload, apiErr, err := svc.AddParticipant(context.Background(), account.ID, user.ID, message.ID, "agent")
require.NoError(t, err)
require.Nil(t, apiErr)
require.Equal(t, "m_id", backend.lastMeetingID)
require.Equal(t, "jwt", payload["auth_token"])
}
func setupDyteServiceFixture(t *testing.T) (*gorm.DB, *model.Account, *model.User, uint) {
t.Helper()
db := setupServiceTestDB(t)
require.NoError(t, db.AutoMigrate(&model.IntegrationHook{}))
account := createTestAccount(t, db)
user := createTestUser(t, db, account.ID)
inbox := &model.Inbox{AccountID: account.ID, Name: "Website", ChannelType: "web_widget", Enabled: true}
require.NoError(t, db.Create(inbox).Error)
require.NoError(t, db.Create(&model.InboxMember{InboxID: inbox.ID, UserID: user.ID, Role: "agent"}).Error)
contact := &model.Contact{AccountID: account.ID, Name: "Visitor"}
require.NoError(t, db.Create(contact).Error)
displayID := uint(7)
conversation := &model.Conversation{AccountID: account.ID, InboxID: inbox.ID, ContactID: contact.ID, DisplayID: &displayID, Status: "pending", ChannelType: "web_widget", Channel: "web_widget"}
require.NoError(t, db.Create(conversation).Error)
settings, _ := json.Marshal(map[string]any{"organization_id": "org", "api_key": "key"})
require.NoError(t, db.Create(&model.IntegrationHook{AccountID: account.ID, AppID: "dyte", HookType: model.HookType("dyte"), Settings: datatypes.JSON(settings)}).Error)
return db, account, user, displayID
}
func createDyteIntegrationMessage(t *testing.T, db *gorm.DB, accountID, userID uint) *model.Message {
t.Helper()
var conversation model.Conversation
require.NoError(t, db.Where("account_id = ?", accountID).First(&conversation).Error)
attrs, _ := json.Marshal(map[string]any{"type": "dyte", "data": map[string]any{"meeting_id": "m_id"}})
message := &model.Message{AccountID: accountID, InboxID: conversation.InboxID, ConversationID: conversation.ID, SenderID: &userID, SenderType: "user", MessageType: "outgoing", ContentType: "integrations", Content: "Join", Status: "sent", ContentAttributes: datatypes.JSON(attrs)}
require.NoError(t, db.Create(message).Error)
return message
}