feat(widget): cover campaigns events and labels
This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
|
||||
"github.com/gochat/gochat/internal/campaign"
|
||||
"github.com/gochat/gochat/internal/model"
|
||||
"github.com/gochat/gochat/internal/repository"
|
||||
"github.com/gochat/gochat/internal/service"
|
||||
@@ -56,6 +57,11 @@ func setupWidgetHandlerTest(t *testing.T) (*gorm.DB, *gin.Engine, *WidgetHandler
|
||||
&model.PreChatForm{},
|
||||
&model.WidgetFileUpload{},
|
||||
&model.WidgetOfflineMessage{},
|
||||
&model.User{},
|
||||
&model.AccountUser{},
|
||||
&model.InboxMember{},
|
||||
&model.Tag{},
|
||||
&campaign.Campaign{},
|
||||
))
|
||||
|
||||
t.Cleanup(func() {
|
||||
@@ -72,11 +78,14 @@ func setupWidgetHandlerTest(t *testing.T) (*gorm.DB, *gin.Engine, *WidgetHandler
|
||||
preChatFormRepo := repository.NewPreChatFormRepo(db)
|
||||
fileUploadRepo := repository.NewWidgetFileUploadRepo(db)
|
||||
offlineMsgRepo := repository.NewWidgetOfflineMessageRepo(db)
|
||||
inboxMemberRepo := repository.NewInboxMemberRepo(db)
|
||||
tagRepo := repository.NewTagRepo(db)
|
||||
campaignRepo := repository.NewCampaignRepo(db)
|
||||
|
||||
widgetSvc := service.NewWidgetService(
|
||||
inboxRepo, contactRepo, contactInboxRepo, conversationRepo,
|
||||
messageRepo, &noopTypingIndicatorWidget{}, themeConfigRepo, preChatFormRepo,
|
||||
fileUploadRepo, offlineMsgRepo,
|
||||
fileUploadRepo, offlineMsgRepo, inboxMemberRepo, tagRepo, campaignRepo,
|
||||
)
|
||||
|
||||
handler := NewHandler(widgetSvc)
|
||||
@@ -101,6 +110,11 @@ func setupWidgetHandlerTest(t *testing.T) (*gorm.DB, *gin.Engine, *WidgetHandler
|
||||
chatwootWidgetGroup.POST("/messages", handler.SendMessage)
|
||||
chatwootWidgetGroup.POST("/conversations", handler.CreateConversation)
|
||||
chatwootWidgetGroup.GET("/contact", handler.GetContact)
|
||||
chatwootWidgetGroup.GET("/campaigns", handler.ListCampaigns)
|
||||
chatwootWidgetGroup.GET("/inbox_members", handler.ListInboxMembers)
|
||||
chatwootWidgetGroup.POST("/events", handler.CreateEvent)
|
||||
chatwootWidgetGroup.POST("/labels", handler.AddLabel)
|
||||
chatwootWidgetGroup.DELETE("/labels/:label_id", handler.RemoveLabel)
|
||||
}
|
||||
|
||||
return db, router, handler
|
||||
@@ -278,6 +292,133 @@ func TestWidgetHandler_ChatwootMessages_AuthTokenAndNestedPayload(t *testing.T)
|
||||
require.Equal(t, http.StatusOK, wContact.Code)
|
||||
}
|
||||
|
||||
func TestWidgetHandler_ChatwootInboxMembers_Success(t *testing.T) {
|
||||
db, router, _ := setupWidgetHandlerTest(t)
|
||||
_, inbox := seedWidgetHandlerData(t, db)
|
||||
|
||||
user := &model.User{
|
||||
AccountID: inbox.AccountID,
|
||||
Name: "Ada Agent",
|
||||
Email: "ada@handler.test",
|
||||
Password: "secret",
|
||||
AvatarURL: "https://example.test/ada.png",
|
||||
Active: true,
|
||||
}
|
||||
require.NoError(t, db.Create(user).Error)
|
||||
require.NoError(t, db.Create(&model.InboxMember{
|
||||
InboxID: inbox.ID,
|
||||
UserID: user.ID,
|
||||
Role: "agent",
|
||||
AvailabilityStatus: "online",
|
||||
}).Error)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", "/api/v1/widget/inbox_members?website_token=handler_ws_token_123", nil)
|
||||
router.ServeHTTP(w, req)
|
||||
require.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
var resp map[string]interface{}
|
||||
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
|
||||
payload := resp["payload"].([]interface{})
|
||||
require.Len(t, payload, 1)
|
||||
member := payload[0].(map[string]interface{})
|
||||
assert.Equal(t, "Ada Agent", member["name"])
|
||||
assert.Equal(t, "online", member["availability_status"])
|
||||
}
|
||||
|
||||
func TestWidgetHandler_ChatwootCampaigns_Success(t *testing.T) {
|
||||
db, router, _ := setupWidgetHandlerTest(t)
|
||||
_, inbox := seedWidgetHandlerData(t, db)
|
||||
|
||||
require.NoError(t, db.Create(&campaign.Campaign{
|
||||
AccountID: inbox.AccountID,
|
||||
InboxID: inbox.ID,
|
||||
DisplayID: 42,
|
||||
Title: "Welcome",
|
||||
Message: "Welcome to support",
|
||||
CampaignType: campaign.CampaignTypeOngoing,
|
||||
TriggerRules: `{"url":"https://example.test","time_on_page":10}`,
|
||||
Enabled: true,
|
||||
}).Error)
|
||||
disabledCampaign := &campaign.Campaign{
|
||||
AccountID: inbox.AccountID,
|
||||
InboxID: inbox.ID,
|
||||
DisplayID: 43,
|
||||
Title: "Disabled",
|
||||
Message: "Hidden",
|
||||
CampaignType: campaign.CampaignTypeOngoing,
|
||||
Enabled: false,
|
||||
}
|
||||
require.NoError(t, db.Create(disabledCampaign).Error)
|
||||
require.NoError(t, db.Model(disabledCampaign).Update("enabled", false).Error)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", "/api/v1/widget/campaigns?website_token=handler_ws_token_123", nil)
|
||||
router.ServeHTTP(w, req)
|
||||
require.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
var resp []map[string]interface{}
|
||||
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
|
||||
require.Len(t, resp, 1)
|
||||
assert.Equal(t, float64(42), resp[0]["id"])
|
||||
assert.Equal(t, "Welcome to support", resp[0]["message"])
|
||||
rules := resp[0]["trigger_rules"].(map[string]interface{})
|
||||
assert.Equal(t, "https://example.test", rules["url"])
|
||||
}
|
||||
|
||||
func TestWidgetHandler_ChatwootEventsAndLabels(t *testing.T) {
|
||||
db, router, _ := setupWidgetHandlerTest(t)
|
||||
_, inbox := seedWidgetHandlerData(t, db)
|
||||
require.NoError(t, db.Create(&model.Tag{AccountID: inbox.AccountID, Name: "vip"}).Error)
|
||||
|
||||
wConfig := httptest.NewRecorder()
|
||||
reqConfig, _ := http.NewRequest("POST", "/api/v1/widget/config?website_token=handler_ws_token_123", nil)
|
||||
router.ServeHTTP(wConfig, reqConfig)
|
||||
require.Equal(t, http.StatusOK, wConfig.Code)
|
||||
|
||||
var configResp map[string]interface{}
|
||||
require.NoError(t, json.Unmarshal(wConfig.Body.Bytes(), &configResp))
|
||||
authToken := configResp["contact"].(map[string]interface{})["pubsub_token"].(string)
|
||||
|
||||
body := map[string]interface{}{"message": map[string]interface{}{"content": "Label me"}}
|
||||
bodyJSON, _ := json.Marshal(body)
|
||||
wMessage := httptest.NewRecorder()
|
||||
reqMessage, _ := http.NewRequest("POST", "/api/v1/widget/messages", bytes.NewReader(bodyJSON))
|
||||
reqMessage.Header.Set("Content-Type", "application/json")
|
||||
reqMessage.Header.Set("X-Auth-Token", authToken)
|
||||
router.ServeHTTP(wMessage, reqMessage)
|
||||
require.Equal(t, http.StatusOK, wMessage.Code)
|
||||
|
||||
wEvent := httptest.NewRecorder()
|
||||
eventBody, _ := json.Marshal(map[string]interface{}{"name": "widget.opened", "event_info": map[string]interface{}{"source": "test"}})
|
||||
reqEvent, _ := http.NewRequest("POST", "/api/v1/widget/events?website_token=handler_ws_token_123", bytes.NewReader(eventBody))
|
||||
reqEvent.Header.Set("Content-Type", "application/json")
|
||||
reqEvent.Header.Set("X-Auth-Token", authToken)
|
||||
router.ServeHTTP(wEvent, reqEvent)
|
||||
require.Equal(t, http.StatusNoContent, wEvent.Code)
|
||||
|
||||
wAdd := httptest.NewRecorder()
|
||||
labelBody, _ := json.Marshal(map[string]interface{}{"label": "vip"})
|
||||
reqAdd, _ := http.NewRequest("POST", "/api/v1/widget/labels", bytes.NewReader(labelBody))
|
||||
reqAdd.Header.Set("Content-Type", "application/json")
|
||||
reqAdd.Header.Set("X-Auth-Token", authToken)
|
||||
router.ServeHTTP(wAdd, reqAdd)
|
||||
require.Equal(t, http.StatusNoContent, wAdd.Code)
|
||||
|
||||
var conversation model.Conversation
|
||||
require.NoError(t, db.Where("inbox_id = ?", inbox.ID).First(&conversation).Error)
|
||||
assert.Equal(t, "vip", conversation.Labels)
|
||||
|
||||
wRemove := httptest.NewRecorder()
|
||||
reqRemove, _ := http.NewRequest("DELETE", "/api/v1/widget/labels/vip", nil)
|
||||
reqRemove.Header.Set("X-Auth-Token", authToken)
|
||||
router.ServeHTTP(wRemove, reqRemove)
|
||||
require.Equal(t, http.StatusNoContent, wRemove.Code)
|
||||
|
||||
require.NoError(t, db.First(&conversation, conversation.ID).Error)
|
||||
assert.Empty(t, conversation.Labels)
|
||||
}
|
||||
|
||||
// ========== SendMessage Handler Tests ==========
|
||||
|
||||
func TestWidgetHandler_SendMessage_Success(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user