feat(widget): finish chatwoot widget stub burn-down
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
@@ -108,13 +109,17 @@ func setupWidgetHandlerTest(t *testing.T) (*gorm.DB, *gin.Engine, *WidgetHandler
|
||||
chatwootWidgetGroup.POST("/config", handler.Config)
|
||||
chatwootWidgetGroup.GET("/messages", handler.GetLatestMessages)
|
||||
chatwootWidgetGroup.POST("/messages", handler.SendMessage)
|
||||
chatwootWidgetGroup.PATCH("/messages/:message_id", handler.UpdateMessage)
|
||||
chatwootWidgetGroup.POST("/conversations", handler.CreateConversation)
|
||||
chatwootWidgetGroup.POST("/conversations/transcript", handler.SendTranscript)
|
||||
chatwootWidgetGroup.GET("/contact", handler.GetContact)
|
||||
chatwootWidgetGroup.PATCH("/contact/set_user", handler.SetUser)
|
||||
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)
|
||||
chatwootWidgetGroup.POST("/integrations/dyte/add_participant_to_meeting", handler.AddDyteParticipantToMeeting)
|
||||
}
|
||||
|
||||
return db, router, handler
|
||||
@@ -292,6 +297,149 @@ func TestWidgetHandler_ChatwootMessages_AuthTokenAndNestedPayload(t *testing.T)
|
||||
require.Equal(t, http.StatusOK, wContact.Code)
|
||||
}
|
||||
|
||||
func TestWidgetHandler_ChatwootMessageUpdate_SubmitsEmail(t *testing.T) {
|
||||
db, router, _ := setupWidgetHandlerTest(t)
|
||||
_, inbox := seedWidgetHandlerData(t, db)
|
||||
|
||||
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": "start"}}
|
||||
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)
|
||||
|
||||
var conversation model.Conversation
|
||||
require.NoError(t, db.Where("inbox_id = ?", inbox.ID).First(&conversation).Error)
|
||||
formMessage := &model.Message{
|
||||
ConversationID: conversation.ID,
|
||||
AccountID: conversation.AccountID,
|
||||
InboxID: conversation.InboxID,
|
||||
Content: "Email?",
|
||||
ContentType: "input_email",
|
||||
MessageType: "outgoing",
|
||||
ContentAttributes: datatypes.JSON(`{}`),
|
||||
}
|
||||
require.NoError(t, db.Create(formMessage).Error)
|
||||
|
||||
updateBody, _ := json.Marshal(map[string]interface{}{
|
||||
"contact": map[string]interface{}{"email": "Visitor@Example.TEST"},
|
||||
"message": map[string]interface{}{"submitted_values": []map[string]interface{}{{"name": "email", "value": "Visitor@Example.TEST"}}},
|
||||
})
|
||||
wUpdate := httptest.NewRecorder()
|
||||
reqUpdate, _ := http.NewRequest("PATCH", "/api/v1/widget/messages/"+strconv.FormatUint(uint64(formMessage.ID), 10), bytes.NewReader(updateBody))
|
||||
reqUpdate.Header.Set("Content-Type", "application/json")
|
||||
reqUpdate.Header.Set("X-Auth-Token", authToken)
|
||||
router.ServeHTTP(wUpdate, reqUpdate)
|
||||
require.Equal(t, http.StatusOK, wUpdate.Code)
|
||||
|
||||
require.NoError(t, db.First(formMessage, formMessage.ID).Error)
|
||||
attrs := map[string]interface{}{}
|
||||
require.NoError(t, json.Unmarshal(formMessage.ContentAttributes, &attrs))
|
||||
assert.Equal(t, "visitor@example.test", attrs["submitted_email"])
|
||||
|
||||
var contact model.Contact
|
||||
require.NoError(t, db.First(&contact, conversation.ContactID).Error)
|
||||
assert.Equal(t, "visitor@example.test", contact.Email)
|
||||
}
|
||||
|
||||
func TestWidgetHandler_ChatwootSetUserAndTranscript(t *testing.T) {
|
||||
db, router, _ := setupWidgetHandlerTest(t)
|
||||
_, _ = seedWidgetHandlerData(t, db)
|
||||
|
||||
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)
|
||||
hash := hmac.New(sha256.New, []byte("handler_hmac_secret"))
|
||||
_, _ = hash.Write([]byte("external-123"))
|
||||
identifierHash := hex.EncodeToString(hash.Sum(nil))
|
||||
|
||||
setUserBody, _ := json.Marshal(map[string]interface{}{
|
||||
"identifier": "external-123",
|
||||
"identifier_hash": identifierHash,
|
||||
"email": "external@example.test",
|
||||
"name": "External Visitor",
|
||||
})
|
||||
wSetUser := httptest.NewRecorder()
|
||||
reqSetUser, _ := http.NewRequest("PATCH", "/api/v1/widget/contact/set_user?website_token=handler_ws_token_123", bytes.NewReader(setUserBody))
|
||||
reqSetUser.Header.Set("Content-Type", "application/json")
|
||||
reqSetUser.Header.Set("X-Auth-Token", authToken)
|
||||
router.ServeHTTP(wSetUser, reqSetUser)
|
||||
require.Equal(t, http.StatusOK, wSetUser.Code)
|
||||
|
||||
var setUserResp map[string]interface{}
|
||||
require.NoError(t, json.Unmarshal(wSetUser.Body.Bytes(), &setUserResp))
|
||||
assert.Equal(t, "external-123", setUserResp["identifier"])
|
||||
assert.Equal(t, true, setUserResp["has_email"])
|
||||
|
||||
body := map[string]interface{}{"message": map[string]interface{}{"content": "Need transcript"}}
|
||||
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)
|
||||
|
||||
wTranscript := httptest.NewRecorder()
|
||||
reqTranscript, _ := http.NewRequest("POST", "/api/v1/widget/conversations/transcript", nil)
|
||||
reqTranscript.Header.Set("X-Auth-Token", authToken)
|
||||
router.ServeHTTP(wTranscript, reqTranscript)
|
||||
require.Equal(t, http.StatusOK, wTranscript.Code)
|
||||
}
|
||||
|
||||
func TestWidgetHandler_ChatwootDyteParticipant(t *testing.T) {
|
||||
db, router, _ := setupWidgetHandlerTest(t)
|
||||
_, inbox := seedWidgetHandlerData(t, db)
|
||||
contact := &model.Contact{AccountID: inbox.AccountID, Name: "Video Visitor"}
|
||||
require.NoError(t, db.Create(contact).Error)
|
||||
conversation := &model.Conversation{
|
||||
AccountID: inbox.AccountID,
|
||||
InboxID: inbox.ID,
|
||||
ContactID: contact.ID,
|
||||
Status: "open",
|
||||
ChannelType: inbox.ChannelType,
|
||||
Channel: inbox.ChannelType,
|
||||
}
|
||||
require.NoError(t, db.Create(conversation).Error)
|
||||
message := &model.Message{
|
||||
ConversationID: conversation.ID,
|
||||
AccountID: inbox.AccountID,
|
||||
InboxID: inbox.ID,
|
||||
Content: "Join video",
|
||||
ContentType: "integrations",
|
||||
MessageType: "outgoing",
|
||||
ContentAttributes: datatypes.JSON(`{"data":{"meeting_id":"meeting-123"}}`),
|
||||
}
|
||||
require.NoError(t, db.Create(message).Error)
|
||||
|
||||
body, _ := json.Marshal(map[string]interface{}{"message_id": message.ID})
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("POST", "/api/v1/widget/integrations/dyte/add_participant_to_meeting?website_token=handler_ws_token_123", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
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))
|
||||
assert.Equal(t, "dyte_meeting-123", resp["token"])
|
||||
}
|
||||
|
||||
func TestWidgetHandler_ChatwootInboxMembers_Success(t *testing.T) {
|
||||
db, router, _ := setupWidgetHandlerTest(t)
|
||||
_, inbox := seedWidgetHandlerData(t, db)
|
||||
|
||||
Reference in New Issue
Block a user