128 lines
6.2 KiB
Go
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
|
|
}
|