feat(conversations): align chatwoot message serializers

This commit is contained in:
2026-06-05 01:52:07 +08:00
parent c964d6c8fd
commit 9f89cbfe7c
12 changed files with 908 additions and 208 deletions
+51 -26
View File
@@ -84,7 +84,7 @@ func (s *MessageHandlerTestSuite) SetupSuite() {
)
s.Require().NoError(err)
// Wire up repos, services, handlers
// Wire up repos, services, handlers
msgRepo := repository.NewMessageRepo(db)
s.dispatcher = channel.NewDispatcher()
s.mockLLM = &mockMsgHandlerLLMProvider{
@@ -173,7 +173,7 @@ func (s *MessageHandlerTestSuite) SetupTest() {
s.Require().NoError(s.db.Create(msg).Error)
s.testMessage = msg
// Reset mock LLM to default success response
// Reset mock LLM to default success response
s.mockLLM.chatResponse = &llm.ChatResponse{
Choices: []llm.ChatChoice{
{
@@ -199,7 +199,7 @@ func TestMessageHandlerTestSuite(t *testing.T) {
suite.Run(t, new(MessageHandlerTestSuite))
}
// --- Helper for building message list URL ---
// --- Helper for building message list URL ---
func msgListURL(accountID, convID uint) string {
return fmt.Sprintf("/api/v1/accounts/%d/conversations/%d/messages/", accountID, convID)
@@ -217,7 +217,7 @@ func msgTranslateURL(accountID, convID, msgID uint) string {
return fmt.Sprintf("/api/v1/accounts/%d/conversations/%d/messages/%d/translate", accountID, convID, msgID)
}
// --- List Tests ---
// --- List Tests ---
func (s *MessageHandlerTestSuite) TestList_Success() {
w := httptest.NewRecorder()
@@ -228,10 +228,12 @@ func (s *MessageHandlerTestSuite) TestList_Success() {
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp map[string]interface{}
json.Unmarshal(w.Body.Bytes(), &resp)
assert.True(s.T(), resp["success"].(bool))
data, ok := resp["data"].([]interface{})
data, ok := resp["payload"].([]interface{})
assert.True(s.T(), ok)
assert.GreaterOrEqual(s.T(), len(data), 1)
meta, ok := resp["meta"].(map[string]interface{})
assert.True(s.T(), ok)
assert.NotNil(s.T(), meta["contact"])
}
func (s *MessageHandlerTestSuite) TestList_Empty() {
@@ -246,7 +248,7 @@ func (s *MessageHandlerTestSuite) TestList_Empty() {
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp map[string]interface{}
json.Unmarshal(w.Body.Bytes(), &resp)
data, ok := resp["data"].([]interface{})
data, ok := resp["payload"].([]interface{})
assert.True(s.T(), ok)
assert.Equal(s.T(), 0, len(data))
}
@@ -259,7 +261,7 @@ func (s *MessageHandlerTestSuite) TestList_InvalidConversationID() {
assert.Equal(s.T(), http.StatusBadRequest, w.Code)
}
// --- Create Tests ---
// --- Create Tests ---
func (s *MessageHandlerTestSuite) TestCreate_Success() {
payload := map[string]interface{}{
@@ -276,13 +278,39 @@ func (s *MessageHandlerTestSuite) TestCreate_Success() {
req.Header.Set("Content-Type", "application/json")
s.router.ServeHTTP(w, req)
assert.Equal(s.T(), http.StatusCreated, w.Code)
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp map[string]interface{}
json.Unmarshal(w.Body.Bytes(), &resp)
assert.True(s.T(), resp["success"].(bool))
data := resp["data"].(map[string]interface{})
assert.NotNil(s.T(), data["id"])
assert.Equal(s.T(), "New message", data["content"])
assert.NotNil(s.T(), resp["id"])
assert.Equal(s.T(), "New message", resp["content"])
assert.Equal(s.T(), float64(1), resp["message_type"])
assert.Equal(s.T(), float64(s.testConv.ID), resp["conversation_id"])
}
func (s *MessageHandlerTestSuite) TestCreate_ChatwootFrontendPayloadDefaultsOutgoing() {
payload := map[string]interface{}{
"content": "Frontend payload",
"private": true,
"echo_id": "tmp-123",
"content_attributes": map[string]interface{}{"submitted_values": []interface{}{}},
}
body, _ := json.Marshal(payload)
w := httptest.NewRecorder()
url := msgListURL(s.testAccount.ID, s.testConv.ID)
req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
s.router.ServeHTTP(w, req)
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp map[string]interface{}
json.Unmarshal(w.Body.Bytes(), &resp)
assert.Equal(s.T(), "Frontend payload", resp["content"])
assert.Equal(s.T(), true, resp["private"])
assert.Equal(s.T(), "tmp-123", resp["echo_id"])
assert.Equal(s.T(), float64(1), resp["message_type"])
assert.Equal(s.T(), "text", resp["content_type"])
assert.NotNil(s.T(), resp["content_attributes"])
}
func (s *MessageHandlerTestSuite) TestCreate_MissingContent() {
@@ -316,7 +344,7 @@ func (s *MessageHandlerTestSuite) TestCreate_InvalidConversationID() {
assert.Equal(s.T(), http.StatusBadRequest, w.Code)
}
// --- Get Tests ---
// --- Get Tests ---
func (s *MessageHandlerTestSuite) TestGet_Success() {
w := httptest.NewRecorder()
@@ -350,7 +378,7 @@ func (s *MessageHandlerTestSuite) TestGet_InvalidID() {
assert.Equal(s.T(), http.StatusBadRequest, w.Code)
}
// --- Update Tests ---
// --- Update Tests ---
func (s *MessageHandlerTestSuite) TestUpdate_Success() {
payload := map[string]interface{}{
@@ -367,9 +395,7 @@ func (s *MessageHandlerTestSuite) TestUpdate_Success() {
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp map[string]interface{}
json.Unmarshal(w.Body.Bytes(), &resp)
assert.True(s.T(), resp["success"].(bool))
data := resp["data"].(map[string]interface{})
assert.Equal(s.T(), "Updated content", data["content"])
assert.Equal(s.T(), "Updated content", resp["content"])
}
func (s *MessageHandlerTestSuite) TestUpdate_NotFound() {
@@ -387,7 +413,7 @@ func (s *MessageHandlerTestSuite) TestUpdate_NotFound() {
assert.Equal(s.T(), http.StatusNotFound, w.Code)
}
// --- Delete Tests ---
// --- Delete Tests ---
func (s *MessageHandlerTestSuite) TestDelete_Success() {
w := httptest.NewRecorder()
@@ -407,7 +433,7 @@ func (s *MessageHandlerTestSuite) TestDelete_NotFound() {
assert.Equal(s.T(), http.StatusNotFound, w.Code)
}
// --- Retry Tests ---
// --- Retry Tests ---
func (s *MessageHandlerTestSuite) TestRetry_Success() {
w := httptest.NewRecorder()
@@ -418,9 +444,8 @@ func (s *MessageHandlerTestSuite) TestRetry_Success() {
assert.Equal(s.T(), http.StatusOK, w.Code)
var resp map[string]interface{}
json.Unmarshal(w.Body.Bytes(), &resp)
assert.True(s.T(), resp["success"].(bool))
data := resp["data"].(map[string]interface{})
assert.Equal(s.T(), float64(s.testMessage.ID), data["id"])
assert.Equal(s.T(), float64(s.testMessage.ID), resp["id"])
assert.Equal(s.T(), float64(1), resp["message_type"])
}
func (s *MessageHandlerTestSuite) TestRetry_InvalidAccountID() {
@@ -464,7 +489,7 @@ func (s *MessageHandlerTestSuite) TestRetry_AccountMismatch() {
assert.Equal(s.T(), http.StatusNotFound, w.Code)
}
// --- Translate Tests ---
// --- Translate Tests ---
func (s *MessageHandlerTestSuite) TestTranslate_Success() {
payload := map[string]interface{}{
@@ -579,7 +604,7 @@ func (s *MessageHandlerTestSuite) TestTranslate_LLMError() {
}
func (s *MessageHandlerTestSuite) TestTranslate_EmptyChoices() {
// Set LLM to return response with no choices
// Set LLM to return response with no choices
s.mockLLM.chatResponse = &llm.ChatResponse{
Choices: []llm.ChatChoice{},
}
@@ -637,4 +662,4 @@ func TestDirectUploadHandler_InvalidContentType(t *testing.T) {
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusBadRequest, w.Code)
}
}